// File: /workspace/github_c_makefile_star2_O3/guszejnovdavid[P]MISFIT/trilinear_interpol.c
// Function: trilinear_interp(double, double, double, double const*, int, int, int, double, double, double, double, double, double, int, double)
double trilinear_interp(double X, double Y, double Z, const double *tbl, 
      const int N_X, const int N_Y, const int N_Z,
      const double X_MIN, const double X_MAX, 
      const double Y_MIN, const double Y_MAX,
      const double Z_MIN, const double Z_MAX,
      const int OUT_OF_DOMAIN, const double OUT_OF_DOMAIN_VALUE)
{

  double f111,f211,f212,f112, f121,f221,f222,f122;
  double X_A,X_B,Y_A,Y_B,Z_A,Z_B;

/* grid spacing */
  const double delta_X = (X_MAX-X_MIN)/(N_X-1);
  const double delta_Y = (Y_MAX-Y_MIN)/(N_Y-1);
  const double delta_Z = (Z_MAX-Z_MIN)/(N_Z-1);
 
  const double delta_X_inv = (N_X-1)/(X_MAX-X_MIN);
  const double delta_Y_inv = (N_Y-1)/(Y_MAX-Y_MIN);
  const double delta_Z_inv = (N_Z-1)/(Z_MAX-Z_MIN);
  int i,j,k;
  double X_unit, Y_unit, Z_unit;


  /* select upper right grid point BUG!!!!!! randomly (but very rarely) 
 sometimes select WRONG point!!!*/
  i = (int) ceil( (X-X_MIN)*delta_X_inv);
  j = (int) ceil( (Y-Y_MIN)*delta_Y_inv);
  k = (int) ceil( (Z-Z_MIN)*delta_Z_inv);

/* Return OUT_OF_DOMAIN_VALUE if X or Y or Z are under/overflown */
/* edge of the domain and out-of-range values */
   if( OUT_OF_DOMAIN==0 ) 
   {
     if( (X<X_MIN) || (Y<Y_MIN) || (Z<Z_MIN) || (X>X_MAX) || (Y>Y_MAX) || (Z>Z_MAX) ) return OUT_OF_DOMAIN_VALUE;
   };
   
/* cell corner values */ 
// f222=TBL[i][j][k] declared as double TBL[N_X+1][N_Y+1][N_Z+1]; tbl=&TBL[0][0][0]

  f111 = *(tbl+(N_Z)*(N_Y)*(i-1)+(N_Z)*(j-1)+k-1)   ; //TBL[i-1][j-1][k-1];
  f211 = *(tbl+(N_Z)*(N_Y)*i+(N_Z)*(j-1)+k-1)   ;// TBL[i][j-1][k-1];
  f212 = *(tbl+(N_Z)*(N_Y)*i+(N_Z)*(j-1)+k)   ;//TBL[i][j-1][k];
  f112 = *(tbl+(N_Z)*(N_Y)*(i-1)+(N_Z)*(j-1)+k)   ;//TBL[i-1][j-1][k];
  f121 = *(tbl+(N_Z)*(N_Y)*(i-1)+(N_Z)*j+k-1);    //TBL[i-1][j][k-1];
  f221 = *(tbl+(N_Z)*(N_Y)*i+(N_Z)*j+k-1);  //TBL[i][j][k-1];
  f222 = *(tbl+(N_Z)*(N_Y)*i+(N_Z)*j+k)   ; //TBL[i][j][k];
  f122 = *(tbl+(N_Z)*(N_Y)*(i-1)+(N_Z)*j+k); //TBL[i-1][j][k];

  X_A = X_MIN + (i-1)*delta_X;    
  X_B = X_MIN + i*delta_X;    
  
  Y_A = Y_MIN + (j-1)*delta_Y;
  Y_B = Y_MIN + j*delta_Y;

  Z_A = Z_MIN + (k-1)*delta_Z;
  Z_B = Z_MIN + k*delta_Z;


/* Rescalling to unit cube {0,1}^3 */
  X_unit = (X-X_A)/(X_B-X_A);
  Y_unit = (Y-Y_A)/(Y_B-Y_A);
  Z_unit = (Z-Z_A)/(Z_B-Z_A);

  return trilinear_interp_unit_cube(X_unit,Y_unit,Z_unit, f111,f211,f212,f112,f121,f221,f222,f122);

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0xf8, %rsp
movl %r8d, %r15d
movsd %xmm7, (%rsp)
movl %ecx, %ebx
movl %edx, %ebp
movq %rdi, %r14
movsd %xmm2, 0x8(%rsp)
movsd 0x120(%rsp), %xmm8
movapd %xmm6, 0x90(%rsp)
movapd %xmm4, 0x80(%rsp)
unpcklpd %xmm4, %xmm6            # xmm6 = xmm6[0],xmm4[0]
movapd %xmm5, 0x60(%rsp)
movapd %xmm5, %xmm2
movapd %xmm3, 0x70(%rsp)
unpcklpd %xmm3, %xmm2            # xmm2 = xmm2[0],xmm3[0]
subpd %xmm2, %xmm6
movd %esi, %xmm4
movd %edx, %xmm3
punpckldq %xmm4, %xmm3    # xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1]
pcmpeqd %xmm4, %xmm4
paddd %xmm4, %xmm3
movapd %xmm1, 0x50(%rsp)
movapd %xmm0, 0x40(%rsp)
unpcklpd %xmm0, %xmm1            # xmm1 = xmm1[0],xmm0[0]
movapd %xmm1, 0xe0(%rsp)
movapd %xmm1, %xmm0
movapd %xmm2, 0xd0(%rsp)
subpd %xmm2, %xmm0
cvtdq2pd %xmm3, %xmm1
movapd %xmm1, 0xb0(%rsp)
movapd %xmm6, 0xc0(%rsp)
divpd %xmm6, %xmm1
mulpd %xmm0, %xmm1
movapd %xmm1, %xmm0
movapd %xmm1, 0x10(%rsp)
movapd %xmm8, %xmm2
subsd %xmm7, %xmm2
leal -0x1(%rbx), %eax
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
movsd %xmm1, 0x28(%rsp)
movsd %xmm2, 0x30(%rsp)
divsd %xmm2, %xmm1
movsd %xmm1, 0x38(%rsp)
callq 0x2050
movapd %xmm0, 0xa0(%rsp)
movaps 0x10(%rsp), %xmm0
movhlps %xmm0, %xmm0            # xmm0 = xmm0[1,1]
callq 0x2050
movaps %xmm0, 0x10(%rsp)
movsd 0x8(%rsp), %xmm0
subsd (%rsp), %xmm0
mulsd 0x38(%rsp), %xmm0
callq 0x2050
movsd (%rsp), %xmm3
movsd 0x8(%rsp), %xmm6
testl %r15d, %r15d
jne 0xa466
ucomisd 0x120(%rsp), %xmm6
ja 0xa62d
movapd 0x50(%rsp), %xmm1
ucomisd 0x90(%rsp), %xmm1
ja 0xa62d
movapd 0x40(%rsp), %xmm1
ucomisd 0x80(%rsp), %xmm1
ja 0xa62d
movapd 0x70(%rsp), %xmm1
ucomisd 0x40(%rsp), %xmm1
ja 0xa62d
movapd 0x60(%rsp), %xmm1
ucomisd 0x50(%rsp), %xmm1
ja 0xa62d
ucomisd %xmm6, %xmm3
ja 0xa62d
movsd 0x30(%rsp), %xmm7
divsd 0x28(%rsp), %xmm7
movapd 0xc0(%rsp), %xmm5
divpd 0xb0(%rsp), %xmm5
movapd 0xa0(%rsp), %xmm1
unpcklpd 0x10(%rsp), %xmm1       # xmm1 = xmm1[0],mem[0]
cvttpd2dq %xmm1, %xmm1
cvttsd2si %xmm0, %eax
imull %ebx, %ebp
pcmpeqd %xmm4, %xmm4
paddd %xmm1, %xmm4
pshufd $0x55, %xmm4, %xmm0     # xmm0 = xmm4[1,1,1,1]
movd %xmm0, %ecx
imull %ebp, %ecx
movslq %ecx, %rcx
leaq (%r14,%rcx,8), %rcx
movd %xmm4, %edx
imull %ebx, %edx
movslq %edx, %rdx
leaq (%rcx,%rdx,8), %rdi
cltq
pshufd $0x55, %xmm1, %xmm0     # xmm0 = xmm1[1,1,1,1]
movd %xmm0, %esi
imull %ebp, %esi
movslq %esi, %rsi
leaq (%r14,%rsi,8), %r8
leaq (%r8,%rdx,8), %rsi
movd %xmm1, %edx
imull %ebx, %edx
movslq %edx, %r9
leaq (%rcx,%r9,8), %rdx
leaq (%r8,%r9,8), %rcx
cvtdq2pd %xmm1, %xmm0
leal -0x1(%rax), %r8d
xorps %xmm1, %xmm1
cvtsi2sd %r8d, %xmm1
mulsd %xmm7, %xmm1
addsd %xmm3, %xmm1
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
mulsd %xmm7, %xmm2
addsd %xmm3, %xmm2
cvtdq2pd %xmm4, %xmm3
mulpd %xmm5, %xmm3
movapd 0xd0(%rsp), %xmm4
addpd %xmm4, %xmm3
mulpd %xmm5, %xmm0
addpd %xmm4, %xmm0
movapd 0xe0(%rsp), %xmm7
subpd %xmm3, %xmm7
subpd %xmm3, %xmm0
divpd %xmm0, %xmm7
subsd %xmm1, %xmm6
subsd %xmm1, %xmm2
divsd %xmm2, %xmm6
movapd 0x1381(%rip), %xmm3     # 0xb8e0
subpd %xmm7, %xmm3
movapd %xmm3, %xmm1
unpckhpd %xmm3, %xmm1            # xmm1 = xmm1[1],xmm3[1]
movsd -0x8(%rdi,%rax,8), %xmm4
mulsd %xmm1, %xmm4
mulsd %xmm3, %xmm4
movsd 0xacf(%rip), %xmm2      # 0xb050
subsd %xmm6, %xmm2
movapd %xmm7, %xmm0
unpckhpd %xmm7, %xmm0            # xmm0 = xmm0[1],xmm7[1]
movsd -0x8(%rsi,%rax,8), %xmm5
mulsd %xmm0, %xmm5
mulsd %xmm3, %xmm5
mulsd %xmm2, %xmm5
mulsd %xmm2, %xmm4
addsd %xmm5, %xmm4
movsd -0x8(%rdx,%rax,8), %xmm5
mulsd %xmm1, %xmm5
mulsd %xmm7, %xmm5
mulsd %xmm2, %xmm5
addsd %xmm4, %xmm5
movsd (%rdi,%rax,8), %xmm4
mulsd %xmm1, %xmm4
mulsd %xmm3, %xmm4
mulsd %xmm6, %xmm4
addsd %xmm5, %xmm4
movsd (%rsi,%rax,8), %xmm5
mulsd %xmm0, %xmm5
mulsd %xmm3, %xmm5
mulsd %xmm6, %xmm5
addsd %xmm4, %xmm5
mulsd (%rdx,%rax,8), %xmm1
mulsd %xmm7, %xmm1
mulsd %xmm6, %xmm1
addsd %xmm5, %xmm1
movsd -0x8(%rcx,%rax,8), %xmm3
mulsd %xmm0, %xmm3
mulsd %xmm7, %xmm3
mulsd %xmm2, %xmm3
addsd %xmm1, %xmm3
mulsd (%rcx,%rax,8), %xmm0
mulsd %xmm7, %xmm0
mulsd %xmm6, %xmm0
addsd %xmm3, %xmm0
addq $0xf8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movsd 0x128(%rsp), %xmm0
jmp 0xa61f