// File: PeterDenton[P]Nu-Pert/src/Minimization.cpp
// Function: double gss_min<double>(double (*)(double, double const*), double, double, double, double*)
T gss_min(T (*f)(T, const T*), T a_initial, T b_initial, T tol, T *p)
{
	T gr = (sqrt(5.) - 1) / 2;
	T a = a_initial;
	T b = b_initial;
	T c = b - gr * (b - a);
	T d = a + gr * (b - a);
	while (std::abs(c - d) > tol)
	{
		if (f(c, p) < f(d, p))
		{
			b = d;
			d = c;
			c = b - gr * (b - a);
		}
		else
		{
			a = c;
			c = d;
			d = a + gr * (b - a);
		}
	}
	T ret = (b + a) / 2.;

	// Warns user in case final minimum is close to an edge
	if (std::abs(ret - a_initial) < 2 * tol or std::abs(b_initial - ret) < 2 * tol)
		EdgeCaseWarning W(a_initial, b_initial, ret);
	return ret;
}

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0xc0(%rsp)
movsd %xmm0, 0xb8(%rsp)
movsd %xmm1, 0xb0(%rsp)
movsd %xmm2, 0xa8(%rsp)
movq %rsi, 0xa0(%rsp)
movsd 0x4756(%rip), %xmm0     # 0x12470
callq 0x20f0
movsd 0x42f1(%rip), %xmm1     # 0x12018
subsd %xmm1, %xmm0
movsd 0x42d5(%rip), %xmm1     # 0x12008
divsd %xmm1, %xmm0
movsd %xmm0, 0x98(%rsp)
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x90(%rsp)
movsd 0xb0(%rsp), %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x88(%rsp), %xmm1
movsd 0x98(%rsp), %xmm0
movsd 0x88(%rsp), %xmm2
subsd 0x90(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x90(%rsp), %xmm1
movsd 0x98(%rsp), %xmm0
movsd 0x88(%rsp), %xmm2
subsd 0x90(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
movsd 0x80(%rsp), %xmm0
subsd 0x78(%rsp), %xmm0
callq 0x7490
ucomisd 0xa8(%rsp), %xmm0
jbe 0xdf0e
movq 0xc0(%rsp), %rax
movsd 0x80(%rsp), %xmm0
movq 0xa0(%rsp), %rdi
callq *%rax
movsd %xmm0, 0x8(%rsp)
movq 0xc0(%rsp), %rax
movsd 0x78(%rsp), %xmm0
movq 0xa0(%rsp), %rdi
callq *%rax
movsd 0x8(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0xdeb6
movsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
movsd 0x88(%rsp), %xmm1
movsd 0x98(%rsp), %xmm0
movsd 0x88(%rsp), %xmm2
subsd 0x90(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
jmp 0xdf09
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x90(%rsp)
movsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x90(%rsp), %xmm1
movsd 0x98(%rsp), %xmm0
movsd 0x88(%rsp), %xmm2
subsd 0x90(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
jmp 0xdde2
movsd 0x88(%rsp), %xmm0
addsd 0x90(%rsp), %xmm0
movsd 0x40e0(%rip), %xmm1     # 0x12008
divsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x70(%rsp), %xmm0
subsd 0xb8(%rsp), %xmm0
callq 0x7490
movaps %xmm0, %xmm1
movsd 0x40b7(%rip), %xmm0     # 0x12008
mulsd 0xa8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
ja 0xdf8e
movsd 0xb0(%rsp), %xmm0
subsd 0x70(%rsp), %xmm0
callq 0x7490
movaps %xmm0, %xmm1
movsd 0x4089(%rip), %xmm0     # 0x12008
mulsd 0xa8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0xdfba
movsd 0xb8(%rsp), %xmm0
movsd 0xb0(%rsp), %xmm1
movsd 0x70(%rsp), %xmm2
leaq 0x10(%rsp), %rdi
callq 0x10ed0
leaq 0x10(%rsp), %rdi
callq 0xdfd0
movsd 0x70(%rsp), %xmm0
addq $0xc8, %rsp
retq
nopl (%rax,%rax)