// File: /workspace/github_c_makefile_star2_O2/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 $0xa8, %rsp
movl %r8d, %ebp
movsd %xmm7, 0x28(%rsp)
movsd %xmm5, 0x30(%rsp)
movl %ecx, %ebx
movl %edx, %r14d
movq %rdi, %r15
movsd %xmm2, 0x40(%rsp)
movsd %xmm1, 0x38(%rsp)
movsd %xmm0, 0xa0(%rsp)
movsd 0xd0(%rsp), %xmm2
movsd %xmm4, 0x48(%rsp)
movapd %xmm4, %xmm8
decl %esi
cvtsi2sd %esi, %xmm1
subsd %xmm3, %xmm8
movapd %xmm3, %xmm9
movsd %xmm3, 0x98(%rsp)
movsd %xmm6, 0x50(%rsp)
movapd %xmm6, %xmm3
subsd %xmm5, %xmm3
leal -0x1(%r14), %eax
cvtsi2sd %eax, %xmm4
subsd %xmm7, %xmm2
leal -0x1(%rbx), %eax
movsd %xmm1, 0x70(%rsp)
movsd %xmm8, 0x78(%rsp)
divsd %xmm8, %xmm1
subsd %xmm9, %xmm0
mulsd %xmm1, %xmm0
movsd %xmm4, 0x68(%rsp)
movsd %xmm3, 0x80(%rsp)
divsd %xmm3, %xmm4
movsd %xmm4, 0x20(%rsp)
cvtsi2sd %eax, %xmm1
movsd %xmm1, 0x60(%rsp)
movsd %xmm2, 0x88(%rsp)
divsd %xmm2, %xmm1
movsd %xmm1, 0x90(%rsp)
callq 0x2050
movsd %xmm0, 0x58(%rsp)
movsd 0x38(%rsp), %xmm0
subsd 0x30(%rsp), %xmm0
mulsd 0x20(%rsp), %xmm0
callq 0x2050
movsd %xmm0, 0x20(%rsp)
movsd 0x40(%rsp), %xmm0
subsd 0x28(%rsp), %xmm0
mulsd 0x90(%rsp), %xmm0
callq 0x2050
movsd 0x98(%rsp), %xmm6
movsd 0x30(%rsp), %xmm5
movsd 0x28(%rsp), %xmm4
movsd 0xa0(%rsp), %xmm10
movsd 0x38(%rsp), %xmm1
movsd 0x40(%rsp), %xmm2
testl %ebp, %ebp
jne 0x9bc3
ucomisd 0xd0(%rsp), %xmm2
ja 0x9d0c
ucomisd 0x50(%rsp), %xmm1
ja 0x9d0c
ucomisd 0x48(%rsp), %xmm10
ja 0x9d0c
ucomisd %xmm10, %xmm6
ja 0x9d0c
ucomisd %xmm1, %xmm5
ja 0x9d0c
ucomisd %xmm2, %xmm4
ja 0x9d0c
movsd 0x78(%rsp), %xmm8
divsd 0x70(%rsp), %xmm8
movsd 0x80(%rsp), %xmm7
divsd 0x68(%rsp), %xmm7
cvttsd2si 0x58(%rsp), %edx
cvttsd2si 0x20(%rsp), %eax
movsd 0x88(%rsp), %xmm11
divsd 0x60(%rsp), %xmm11
cvttsd2si %xmm0, %ecx
leal -0x1(%rdx), %esi
leal -0x1(%rax), %edi
movslq %ecx, %rcx
cvtsi2sd %esi, %xmm0
mulsd %xmm8, %xmm0
addsd %xmm6, %xmm0
cvtsi2sd %edx, %xmm3
mulsd %xmm8, %xmm3
addsd %xmm6, %xmm3
cvtsi2sd %edi, %xmm6
mulsd %xmm7, %xmm6
addsd %xmm5, %xmm6
cvtsi2sd %eax, %xmm9
mulsd %xmm7, %xmm9
leal -0x1(%rcx), %r8d
cvtsi2sd %r8d, %xmm7
addsd %xmm5, %xmm9
mulsd %xmm11, %xmm7
cvtsi2sd %ecx, %xmm8
mulsd %xmm11, %xmm8
imull %ebx, %r14d
imull %r14d, %esi
movslq %esi, %rsi
leaq (%r15,%rsi,8), %rsi
imull %ebx, %edi
movslq %edi, %rdi
leaq (%rsi,%rdi,8), %r8
imull %edx, %r14d
movslq %r14d, %rdx
leaq (%r15,%rdx,8), %rdx
leaq (%rdx,%rdi,8), %rdi
addsd %xmm4, %xmm7
addsd %xmm4, %xmm8
movsd -0x8(%rdi,%rcx,8), %xmm4
subsd %xmm0, %xmm10
subsd %xmm0, %xmm3
movsd (%rdi,%rcx,8), %xmm5
divsd %xmm3, %xmm10
movsd -0x8(%r8,%rcx,8), %xmm3
subsd %xmm6, %xmm1
subsd %xmm6, %xmm9
movsd (%r8,%rcx,8), %xmm6
imull %eax, %ebx
movslq %ebx, %rax
leaq (%rsi,%rax,8), %rsi
leaq (%rdx,%rax,8), %rax
divsd %xmm9, %xmm1
movups -0x8(%rax,%rcx,8), %xmm0
subsd %xmm7, %xmm2
subsd %xmm7, %xmm8
movsd -0x8(%rsi,%rcx,8), %xmm7
divsd %xmm8, %xmm2
movsd (%rsi,%rcx,8), %xmm8
movsd %xmm8, 0x10(%rsp)
movups %xmm0, (%rsp)
movapd %xmm10, %xmm0
callq 0x9d17
addq $0xa8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movsd 0xd8(%rsp), %xmm0
jmp 0x9cfe