// File: TBody[P]atomicpp/atomicpp/Spline/BicubicSpline.cpp
// Function: atomicpp::BicubicSpline::call0D(double, double)
double BicubicSpline::call0D(const double eval_x, const double eval_y){
	
	// Bounds checking -- make sure you haven't dropped off the end of the array
	if ((eval_x <= x_values[0]) or (eval_x >= x_values[x_values.size()-1])){
		// An easy error to make is supplying the function arguments already having taken the log10
		std::stringstream errMsg;
		errMsg << "X value off grid - require (" << x_values[0] << " < " << eval_x << " < " << x_values[x_values.size()-1] << ")";
		throw std::runtime_error(errMsg.str());
	};
	if ((eval_y <= y_values[0]) or (eval_y >= y_values[y_values.size()-1])){
		// An easy error to make is supplying the function arguments already having taken the log10
		std::stringstream errMsg;
		errMsg << "Y value off grid - require (" << y_values[0] << " < " << eval_y << " < " << y_values[y_values.size()-1] << ")";
		throw std::runtime_error(errMsg.str());
	};

	// Perform a basic interpolation based on linear distance
	// values to search for
	// Look through the x_values and y_values attributes of RateCoefficient to find nearest (strictly lower)
	// Subtract 1 from answer to account for indexing from 0
	int low_x = lower_bound(x_values.begin(), x_values.end(), eval_x) - x_values.begin() - 1;
	int low_y = lower_bound(y_values.begin(), y_values.end(), eval_y) - y_values.begin() - 1;

	double x_norm = 1/(x_values[low_x+1] - x_values[low_x+0]); //Spacing between grid points
	double y_norm = 1/(y_values[low_y+1] - y_values[low_y+0]); //Spacing between grid points

	double x = (eval_x - x_values[low_x])*x_norm;
	double y = (eval_y - y_values[low_y])*y_norm;

	// // Construct the simple interpolation grid
	// // Find weightings based on linear distance
	// // w01 ------ w11    y
	// //  | \     / |      |
	// //  |  w(x,y) |    --/--x
	// //  | /     \ |      |
	// // w00 ------ w10

	grid_matrix alpha_sub = alpha_coeff[low_x][low_y];

	double x_vector[4] = {1, x, x*x, x*x*x}; //Row vector
	double y_vector[4] = {1, y, y*y, y*y*y}; //Column vector

	double return_value = 0.0;
	for(int i=0; i<4; ++i){
		for(int j=0; j<4; ++j){
			return_value += x_vector[i] * alpha_sub[i][j] * y_vector[j];
		}
	}
	// return_value = x_vector[0] * alpha_sub[0][0] * y_vector[0];

	return return_value;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x540, %rsp            # imm = 0x540
movq %rdi, -0x8(%rbp)
movsd %xmm0, -0x10(%rbp)
movsd %xmm1, -0x18(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x470(%rbp)
movsd -0x10(%rbp), %xmm0
movsd %xmm0, -0x468(%rbp)
xorl %eax, %eax
movl %eax, %esi
callq 0x5950
movsd -0x468(%rbp), %xmm1
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jae 0x24dea
movq -0x470(%rbp), %rdi
movsd -0x10(%rbp), %xmm0
movsd %xmm0, -0x478(%rbp)
callq 0x1d4d0
movq -0x470(%rbp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0x5950
movsd -0x478(%rbp), %xmm0
ucomisd (%rax), %xmm0
jb 0x24fb1
leaq -0x1a0(%rbp), %rdi
callq 0x4290
leaq -0x190(%rbp), %rdi
leaq 0x140c6(%rip), %rsi     # 0x38eca
callq 0x43a0
movq %rax, -0x480(%rbp)
jmp 0x24e12
movq -0x470(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5950
movq -0x480(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x4640
movq %rax, -0x488(%rbp)
jmp 0x24e3b
movq -0x488(%rbp), %rdi
leaq 0x13d0c(%rip), %rsi     # 0x38b55
callq 0x43a0
movq %rax, -0x490(%rbp)
jmp 0x24e57
movq -0x490(%rbp), %rdi
movsd -0x10(%rbp), %xmm0
callq 0x4640
movq %rax, -0x498(%rbp)
jmp 0x24e71
movq -0x498(%rbp), %rdi
leaq 0x13cd6(%rip), %rsi     # 0x38b55
callq 0x43a0
movq %rax, -0x4a0(%rbp)
jmp 0x24e8d
movq -0x470(%rbp), %rdi
callq 0x1d4d0
movq -0x470(%rbp), %rdi
movq %rax, %rsi
decq %rsi
callq 0x5950
movq -0x4a0(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x4640
movq %rax, -0x4a8(%rbp)
jmp 0x24ec4
movq -0x4a8(%rbp), %rdi
leaq 0x13627(%rip), %rsi     # 0x384f9
callq 0x43a0
jmp 0x24ed9
movb $0x1, -0x1d1(%rbp)
movl $0x10, %edi
callq 0x41b0
movq %rax, -0x4b0(%rbp)
leaq -0x1d0(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0x4390
jmp 0x24f06
movq -0x4b0(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
callq 0x4570
jmp 0x24f1b
movq -0x4b0(%rbp), %rdi
movb $0x0, -0x1d1(%rbp)
movq 0x2a0c0(%rip), %rsi     # 0x4eff0
movq 0x2a069(%rip), %rdx     # 0x4efa0
callq 0x45b0
jmp 0x25629
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1a8(%rbp)
movl %eax, -0x1ac(%rbp)
jmp 0x24fa0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1a8(%rbp)
movl %eax, -0x1ac(%rbp)
jmp 0x24f87
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1a8(%rbp)
movl %eax, -0x1ac(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x4220
testb $0x1, -0x1d1(%rbp)
jne 0x24f92
jmp 0x24f9e
movq -0x4b0(%rbp), %rdi
callq 0x42b0
jmp 0x24fa0
leaq -0x1a0(%rbp), %rdi
callq 0x42c0
jmp 0x2561d
movq -0x470(%rbp), %rdi
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x4b8(%rbp)
addq $0x18, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5950
movsd -0x4b8(%rbp), %xmm1
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jae 0x25034
movq -0x470(%rbp), %rdi
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x4c0(%rbp)
movq %rdi, %rax
addq $0x18, %rax
movq %rax, -0x4c8(%rbp)
addq $0x18, %rdi
callq 0x1d4d0
movq -0x4c8(%rbp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0x5950
movsd -0x4c0(%rbp), %xmm0
ucomisd (%rax), %xmm0
jb 0x2520a
leaq -0x360(%rbp), %rdi
callq 0x4290
leaq -0x350(%rbp), %rdi
leaq 0x13eb8(%rip), %rsi     # 0x38f06
callq 0x43a0
movq %rax, -0x4d0(%rbp)
jmp 0x2505c
movq -0x470(%rbp), %rdi
addq $0x18, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5950
movq -0x4d0(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x4640
movq %rax, -0x4d8(%rbp)
jmp 0x25089
movq -0x4d8(%rbp), %rdi
leaq 0x13abe(%rip), %rsi     # 0x38b55
callq 0x43a0
movq %rax, -0x4e0(%rbp)
jmp 0x250a5
movq -0x4e0(%rbp), %rdi
movsd -0x18(%rbp), %xmm0
callq 0x4640
movq %rax, -0x4e8(%rbp)
jmp 0x250bf
movq -0x4e8(%rbp), %rdi
leaq 0x13a88(%rip), %rsi     # 0x38b55
callq 0x43a0
movq %rax, -0x4f0(%rbp)
jmp 0x250db
movq -0x470(%rbp), %rdi
addq $0x18, %rdi
movq %rdi, -0x500(%rbp)
callq 0x1d4d0
movq -0x500(%rbp), %rdi
movq %rax, %rsi
decq %rsi
callq 0x5950
movq -0x4f0(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x4640
movq %rax, -0x4f8(%rbp)
jmp 0x2511d
movq -0x4f8(%rbp), %rdi
leaq 0x133ce(%rip), %rsi     # 0x384f9
callq 0x43a0
jmp 0x25132
movb $0x1, -0x381(%rbp)
movl $0x10, %edi
callq 0x41b0
movq %rax, -0x508(%rbp)
leaq -0x380(%rbp), %rdi
leaq -0x360(%rbp), %rsi
callq 0x4390
jmp 0x2515f
movq -0x508(%rbp), %rdi
leaq -0x380(%rbp), %rsi
callq 0x4570
jmp 0x25174
movq -0x508(%rbp), %rdi
movb $0x0, -0x381(%rbp)
movq 0x29e67(%rip), %rsi     # 0x4eff0
movq 0x29e10(%rip), %rdx     # 0x4efa0
callq 0x45b0
jmp 0x25629
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1a8(%rbp)
movl %eax, -0x1ac(%rbp)
jmp 0x251f9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1a8(%rbp)
movl %eax, -0x1ac(%rbp)
jmp 0x251e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1a8(%rbp)
movl %eax, -0x1ac(%rbp)
leaq -0x380(%rbp), %rdi
callq 0x4220
testb $0x1, -0x381(%rbp)
jne 0x251eb
jmp 0x251f7
movq -0x508(%rbp), %rdi
callq 0x42b0
jmp 0x251f9
leaq -0x360(%rbp), %rdi
callq 0x42c0
jmp 0x2561d
movq -0x470(%rbp), %rdi
callq 0x1da50
movq -0x470(%rbp), %rdi
movq %rax, -0x398(%rbp)
callq 0x1dfe0
movq %rax, -0x3a0(%rbp)
movq -0x398(%rbp), %rdi
movq -0x3a0(%rbp), %rsi
leaq -0x10(%rbp), %rdx
callq 0x22820
movq -0x470(%rbp), %rdi
movq %rax, -0x390(%rbp)
callq 0x1da50
movq %rax, -0x3a8(%rbp)
leaq -0x390(%rbp), %rdi
leaq -0x3a8(%rbp), %rsi
callq 0x1df70
movq -0x470(%rbp), %rdi
subq $0x1, %rax
movl %eax, -0x388(%rbp)
addq $0x18, %rdi
callq 0x1da50
movq -0x470(%rbp), %rdi
movq %rax, -0x3c0(%rbp)
addq $0x18, %rdi
callq 0x1dfe0
movq %rax, -0x3c8(%rbp)
movq -0x3c0(%rbp), %rdi
movq -0x3c8(%rbp), %rsi
leaq -0x18(%rbp), %rdx
callq 0x22820
movq -0x470(%rbp), %rdi
movq %rax, -0x3b8(%rbp)
addq $0x18, %rdi
callq 0x1da50
movq %rax, -0x3d0(%rbp)
leaq -0x3b8(%rbp), %rdi
leaq -0x3d0(%rbp), %rsi
callq 0x1df70
movq -0x470(%rbp), %rdi
subq $0x1, %rax
movl %eax, -0x3ac(%rbp)
movl -0x388(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x5950
movq -0x470(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x528(%rbp)
movl -0x388(%rbp), %eax
addl $0x0, %eax
movslq %eax, %rsi
callq 0x5950
movsd -0x528(%rbp), %xmm1
movq -0x470(%rbp), %rdi
subsd (%rax), %xmm1
movsd 0x10cb3(%rip), %xmm0    # 0x36008
divsd %xmm1, %xmm0
movsd %xmm0, -0x3d8(%rbp)
addq $0x18, %rdi
movl -0x3ac(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x5950
movq -0x470(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x520(%rbp)
addq $0x18, %rdi
movl -0x3ac(%rbp), %eax
addl $0x0, %eax
movslq %eax, %rsi
callq 0x5950
movsd -0x520(%rbp), %xmm1
movq -0x470(%rbp), %rdi
subsd (%rax), %xmm1
movsd 0x10c4f(%rip), %xmm0    # 0x36008
divsd %xmm1, %xmm0
movsd %xmm0, -0x3e0(%rbp)
movsd -0x10(%rbp), %xmm0
movsd %xmm0, -0x518(%rbp)
movslq -0x388(%rbp), %rsi
callq 0x5950
movsd -0x518(%rbp), %xmm0
movq -0x470(%rbp), %rdi
subsd (%rax), %xmm0
mulsd -0x3d8(%rbp), %xmm0
movsd %xmm0, -0x3e8(%rbp)
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x510(%rbp)
addq $0x18, %rdi
movslq -0x3ac(%rbp), %rsi
callq 0x5950
movsd -0x510(%rbp), %xmm0
movq -0x470(%rbp), %rdi
subsd (%rax), %xmm0
mulsd -0x3e0(%rbp), %xmm0
movsd %xmm0, -0x3f0(%rbp)
addq $0x48, %rdi
movslq -0x388(%rbp), %rsi
callq 0x268e0
movq %rax, %rdi
movslq -0x3ac(%rbp), %rsi
callq 0x1ac80
movq %rax, %rsi
leaq -0x408(%rbp), %rdi
callq 0x20ee0
movsd 0x10b91(%rip), %xmm0    # 0x36008
movsd %xmm0, -0x430(%rbp)
movsd -0x3e8(%rbp), %xmm0
movsd %xmm0, -0x428(%rbp)
movsd -0x3e8(%rbp), %xmm0
mulsd -0x3e8(%rbp), %xmm0
movsd %xmm0, -0x420(%rbp)
movsd -0x3e8(%rbp), %xmm0
mulsd -0x3e8(%rbp), %xmm0
mulsd -0x3e8(%rbp), %xmm0
movsd %xmm0, -0x418(%rbp)
movsd 0x10b39(%rip), %xmm0    # 0x36008
movsd %xmm0, -0x450(%rbp)
movsd -0x3f0(%rbp), %xmm0
movsd %xmm0, -0x448(%rbp)
movsd -0x3f0(%rbp), %xmm0
mulsd -0x3f0(%rbp), %xmm0
movsd %xmm0, -0x440(%rbp)
movsd -0x3f0(%rbp), %xmm0
mulsd -0x3f0(%rbp), %xmm0
mulsd -0x3f0(%rbp), %xmm0
movsd %xmm0, -0x438(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x458(%rbp)
movl $0x0, -0x45c(%rbp)
cmpl $0x4, -0x45c(%rbp)
jge 0x255f0
movl $0x0, -0x460(%rbp)
cmpl $0x4, -0x460(%rbp)
jge 0x255da
movslq -0x45c(%rbp), %rax
movsd -0x430(%rbp,%rax,8), %xmm0
movsd %xmm0, -0x530(%rbp)
movslq -0x45c(%rbp), %rsi
leaq -0x408(%rbp), %rdi
callq 0x22870
movq %rax, %rdi
movslq -0x460(%rbp), %rsi
callq 0x5950
movsd -0x530(%rbp), %xmm0
mulsd (%rax), %xmm0
movslq -0x460(%rbp), %rax
movsd -0x450(%rbp,%rax,8), %xmm2
movsd -0x458(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x458(%rbp)
movl -0x460(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x460(%rbp)
jmp 0x2554b
jmp 0x255dc
movl -0x45c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x45c(%rbp)
jmp 0x25534
movsd -0x458(%rbp), %xmm0
movsd %xmm0, -0x538(%rbp)
leaq -0x408(%rbp), %rdi
callq 0x19150
movsd -0x538(%rbp), %xmm0
addq $0x540, %rsp            # imm = 0x540
popq %rbp
retq
movq -0x1a8(%rbp), %rdi
callq 0x45e0
nopl (%rax)