// File: cjlin1[P]liblinear/linear.cpp
// Function: l2r_erm_fun::linesearch_and_update(double*, double*, double*, double*, double)
double l2r_erm_fun::linesearch_and_update(double *w, double *s, double *f, double *g, double alpha)
{
	int i;
	int l = prob->l;
	double sTs = 0;
	double wTs = 0;
	double gTs = 0;
	double eta = 0.01;
	int w_size = get_nr_variable();
	int max_num_linesearch = 20;
	double fold = *f;
	Xv(s, tmp);

	for (i=0;i<w_size;i++)
	{
		sTs += s[i] * s[i];
		wTs += s[i] * w[i];
		gTs += s[i] * g[i];
	}
	if(regularize_bias == 0)
	{
		// bias not used in calculating (w + \alpha s)^T (w + \alpha s)
		sTs -= s[w_size-1] * s[w_size-1];
		wTs -= s[w_size-1] * w[w_size-1];
	}

	int num_linesearch = 0;
	for(num_linesearch=0; num_linesearch < max_num_linesearch; num_linesearch++)
	{
		double loss = 0;
		for(i=0;i<l;i++)
		{
			double inner_product = tmp[i] * alpha + wx[i];
			loss += C_times_loss(i, inner_product);
		}
		*f = loss + (alpha * alpha * sTs + wTw) / 2.0 + alpha * wTs;
		if (*f - fold <= eta * alpha * gTs)
		{
			for (i=0;i<l;i++)
				wx[i] += alpha * tmp[i];
			break;
		}
		else
			alpha *= 0.5;
	}

	if (num_linesearch >= max_num_linesearch)
	{
		*f = fold;
		return 0;
	}
	else
		for (i=0;i<w_size;i++)
			w[i] += alpha * s[i];

	wTw += alpha * alpha * sTs + 2* alpha * wTs;
	return alpha;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movsd %xmm0, -0x38(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x90(%rbp)
movq 0x10(%rdi), %rax
movl (%rax), %eax
movl %eax, -0x40(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x48(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x50(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x58(%rbp)
movsd 0xd9d8(%rip), %xmm0     # 0x12030
movsd %xmm0, -0x60(%rbp)
movq (%rdi), %rax
callq *0x18(%rax)
movq -0x90(%rbp), %rdi
movl %eax, -0x64(%rbp)
movl $0x14, -0x68(%rbp)
movq -0x28(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x70(%rbp)
movq -0x20(%rbp), %rsi
movq 0x20(%rdi), %rdx
callq 0x4570
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x64(%rbp), %eax
jge 0x4733
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0x48(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0x50(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x50(%rbp)
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x30(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0x58(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x58(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x4695
movq -0x90(%rbp), %rax
cmpl $0x0, 0x30(%rax)
jne 0x47de
movq -0x20(%rbp), %rax
movl -0x64(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x20(%rbp), %rax
movl -0x64(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0x48(%rbp), %xmm1
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x20(%rbp), %rax
movl -0x64(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movl -0x64(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0x50(%rbp), %xmm1
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x50(%rbp)
movl $0x0, -0x74(%rbp)
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
cmpl -0x68(%rbp), %eax
jge 0x4950
xorps %xmm0, %xmm0
movsd %xmm0, -0x80(%rbp)
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x40(%rbp), %eax
jge 0x486b
movq -0x90(%rbp), %rdi
movq 0x20(%rdi), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd -0x38(%rbp), %xmm2
movq 0x18(%rdi), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x88(%rbp)
movl -0x3c(%rbp), %esi
movsd -0x88(%rbp), %xmm0
movq (%rdi), %rax
callq *0x40(%rax)
addsd -0x80(%rbp), %xmm0
movsd %xmm0, -0x80(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x4807
movq -0x90(%rbp), %rax
movsd -0x80(%rbp), %xmm1
movsd -0x38(%rbp), %xmm0
mulsd -0x38(%rbp), %xmm0
movsd -0x48(%rbp), %xmm3
movsd 0x28(%rax), %xmm2
mulsd %xmm3, %xmm0
addsd %xmm2, %xmm0
movsd 0xe555(%rip), %xmm2     # 0x12df0
divsd %xmm2, %xmm0
addsd %xmm0, %xmm1
movsd -0x38(%rbp), %xmm0
movsd -0x50(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movq -0x28(%rbp), %rax
movsd %xmm0, (%rax)
movq -0x28(%rbp), %rax
movsd (%rax), %xmm1
subsd -0x70(%rbp), %xmm1
movsd -0x60(%rbp), %xmm0
mulsd -0x38(%rbp), %xmm0
mulsd -0x58(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x492e
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x40(%rbp), %eax
jge 0x492c
movq -0x90(%rbp), %rax
movsd -0x38(%rbp), %xmm0
movq 0x20(%rax), %rcx
movslq -0x3c(%rbp), %rdx
movsd (%rcx,%rdx,8), %xmm2
movq 0x18(%rax), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x48e6
jmp 0x4950
movsd 0xd6e2(%rip), %xmm0     # 0x12018
mulsd -0x38(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
jmp 0x4942
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x47ec
movl -0x74(%rbp), %eax
cmpl -0x68(%rbp), %eax
jl 0x4972
movsd -0x70(%rbp), %xmm0
movq -0x28(%rbp), %rax
movsd %xmm0, (%rax)
xorps %xmm0, %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x49fe
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x64(%rbp), %eax
jge 0x49b8
movsd -0x38(%rbp), %xmm0
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq -0x18(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x4979
jmp 0x49ba
movq -0x90(%rbp), %rax
movsd -0x38(%rbp), %xmm0
mulsd -0x38(%rbp), %xmm0
movsd -0x48(%rbp), %xmm2
movsd 0xe418(%rip), %xmm1     # 0x12df0
mulsd -0x38(%rbp), %xmm1
mulsd -0x50(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
addsd 0x28(%rax), %xmm0
movsd %xmm0, 0x28(%rax)
movsd -0x38(%rbp), %xmm0
movsd %xmm0, -0x8(%rbp)
movsd -0x8(%rbp), %xmm0
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax)