// File: /workspace/github_cpp_makefile_star2_O1/qmmlib[P]QmmLibrary/linear.cpp
// Function: solve_l2r_lr_dual(problem const*, double*, double, double, double)
void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, double Cn)
{
	int l = prob->l;
	int w_size = prob->n;
	int i, s, iter = 0;
	double *xTx = new double[l];
	int max_iter = 1000;
	int *index = new int[l];		
	double *alpha = new double[2*l]; // store alpha and C - alpha
	schar *y = new schar[l];	
	int max_inner_iter = 100; // for inner Newton
	double innereps = 1e-2; 
	double innereps_min = min(1e-8, eps);
	double upper_bound[3] = {Cn, 0, Cp};

	for(i=0; i<l; i++)
	{
		if(prob->y[i] > 0)
		{
			y[i] = +1; 
		}
		else
		{
			y[i] = -1;
		}
	}
		
	// Initial alpha can be set here. Note that
	// 0 < alpha[i] < upper_bound[GETI(i)]
	// alpha[2*i] + alpha[2*i+1] = upper_bound[GETI(i)]
	for(i=0; i<l; i++)
	{
		alpha[2*i] = min(0.001*upper_bound[GETI(i)], 1e-8);
		alpha[2*i+1] = upper_bound[GETI(i)] - alpha[2*i];
	}

	for(i=0; i<w_size; i++)
		w[i] = 0;
	for(i=0; i<l; i++)
	{
		xTx[i] = 0;
		feature_node *xi = prob->x[i];
		while (xi->index != -1)
		{
			double val = xi->value;
			xTx[i] += val*val;
			w[xi->index-1] += y[i]*alpha[2*i]*val;
			xi++;
		}
		index[i] = i;
	}

	while (iter < max_iter)
	{
		for (i=0; i<l; i++)
		{
			int j = i+rand()%(l-i);
			swap(index[i], index[j]);
		}
		int newton_iter = 0;
		double Gmax = 0;
		for (s=0; s<l; s++)
		{
			i = index[s];
			schar yi = y[i];
			double C = upper_bound[GETI(i)];
			double ywTx = 0, xisq = xTx[i];
			feature_node *xi = prob->x[i];
			while (xi->index != -1)
			{
				ywTx += w[xi->index-1]*xi->value;
				xi++;
			}
			ywTx *= y[i];
			double a = xisq, b = ywTx;

			// Decide to minimize g_1(z) or g_2(z)
			int ind1 = 2*i, ind2 = 2*i+1, sign = 1;
			if(0.5*a*(alpha[ind2]-alpha[ind1])+b < 0) 
			{
				ind1 = 2*i+1;
				ind2 = 2*i;
				sign = -1;
			}

			//  g_t(z) = z*log(z) + (C-z)*log(C-z) + 0.5a(z-alpha_old)^2 + sign*b(z-alpha_old)
			double alpha_old = alpha[ind1];
			double z = alpha_old;
			if(C - z < 0.5 * C) 
				z = 0.1*z;
			double gp = a*(z-alpha_old)+sign*b+log(z/(C-z));
			Gmax = max(Gmax, fabs(gp));

			// Newton method on the sub-problem
			const double eta = 0.1; // xi in the paper
			int inner_iter = 0;
			while (inner_iter <= max_inner_iter) 
			{
				if(fabs(gp) < innereps)
					break;
				double gpp = a + C/(C-z)/z;
				double tmpz = z - gp/gpp;
				if(tmpz <= 0) 
					z *= eta;
				else // tmpz in (0, C)
					z = tmpz;
				gp = a*(z-alpha_old)+sign*b+log(z/(C-z));
				newton_iter++;
				inner_iter++;
			}

			if(inner_iter > 0) // update w
			{
				alpha[ind1] = z;
				alpha[ind2] = C-z;
				xi = prob->x[i];
				while (xi->index != -1)
				{
					w[xi->index-1] += sign*(z-alpha_old)*yi*xi->value;
					xi++;
				}  
			}
		}

		iter++;
		if(iter % 10 == 0)
			info(".");

		if(Gmax < eps) 
			break;

		if(newton_iter <= l/10) 
			innereps = max(innereps_min, 0.1*innereps);

	}

	info("\noptimization finished, #iter = %d\n",iter);
	if (iter >= max_iter)
		info("\nWARNING: reaching max number of iterations\nUsing -s 0 may be faster (also see FAQ)\n\n");

	// calculate objective value
	
	double v = 0;
	for(i=0; i<w_size; i++)
		v += w[i] * w[i];
	v *= 0.5;
	for(i=0; i<l; i++)
		v += alpha[2*i] * log(alpha[2*i]) + alpha[2*i+1] * log(alpha[2*i+1]) 
			- upper_bound[GETI(i)] * log(upper_bound[GETI(i)]);
	info("Objective value = %lf\n", v);

	delete [] xTx;
	delete [] alpha;
	delete [] y;
	delete [] index;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x118, %rsp            # imm = 0x118
movsd %xmm2, 0x40(%rsp)
movsd %xmm1, 0x20(%rsp)
movsd %xmm0, 0x58(%rsp)
movq %rsi, %rbp
movq %rdi, %rcx
movslq (%rdi), %rbx
movq %rbx, %r12
shlq $0x4, %r12
testq %rbx, %rbx
movq $-0x1, %rax
cmovsq %rax, %r12
leaq (,%rbx,4), %r14
testq %rbx, %rbx
cmovsq %rax, %r14
leaq (,%rbx,8), %rdi
testq %rbx, %rbx
movq %rcx, 0x30(%rsp)
movl 0x4(%rcx), %ecx
movq %rcx, 0x70(%rsp)
cmovsq %rax, %rdi
callq 0x3030
movq %rax, 0x80(%rsp)
movq %r14, %rdi
movq %rbx, %r14
callq 0x3030
movq %rax, %r15
movq %r12, %rdi
callq 0x3030
movq %rax, 0x18(%rsp)
movq %rbx, %rdi
callq 0x3030
movq %rax, %r13
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
movq $0x0, 0xa8(%rsp)
movsd 0x20(%rsp), %xmm0
movsd %xmm0, 0xb0(%rsp)
testq %rbx, %rbx
jle 0x72f1
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rax
xorl %ecx, %ecx
xorpd %xmm0, %xmm0
movsd (%rax,%rcx,8), %xmm1
ucomisd %xmm0, %xmm1
setbe %dl
negb %dl
orb $0x1, %dl
movb %dl, (%r13,%rcx)
incq %rcx
cmpq %rcx, %r14
jne 0x72d3
testl %r14d, %r14d
jle 0x7341
movq 0x18(%rsp), %rax
addq $0x8, %rax
xorl %ecx, %ecx
movsd 0xff87(%rip), %xmm0     # 0x17290
movsbq (%r13,%rcx), %rdx
movsd 0xa8(%rsp,%rdx,8), %xmm1
movapd %xmm1, %xmm2
mulsd %xmm0, %xmm2
minsd 0xff60(%rip), %xmm2     # 0x17288
movsd %xmm2, -0x8(%rax)
subsd %xmm2, %xmm1
movsd %xmm1, (%rax)
incq %rcx
addq $0x10, %rax
cmpq %rcx, %r14
jne 0x7309
movq 0x70(%rsp), %rax
testl %eax, %eax
movq 0x80(%rsp), %r12
jle 0x7364
leaq (,%rax,8), %rdx
movq %rbp, %rdi
xorl %esi, %esi
callq 0x3110
testl %r14d, %r14d
jle 0x73f5
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rax
xorl %ecx, %ecx
movq 0x18(%rsp), %r8
movq $0x0, (%r12,%rcx,8)
movq (%rax,%rcx,8), %rdx
movl (%rdx), %esi
cmpl $-0x1, %esi
je 0x73e9
movsbl (%r13,%rcx), %edi
xorps %xmm0, %xmm0
cvtsi2sd %edi, %xmm0
movq %rcx, %rdi
shlq $0x4, %rdi
mulsd (%r8,%rdi), %xmm0
movsd (%r12,%rcx,8), %xmm1
addq $0x10, %rdx
movsd -0x8(%rdx), %xmm2
movapd %xmm2, %xmm3
mulsd %xmm2, %xmm3
addsd %xmm3, %xmm1
movsd %xmm1, (%r12,%rcx,8)
movslq %esi, %rsi
mulsd %xmm0, %xmm2
addsd -0x8(%rbp,%rsi,8), %xmm2
movsd %xmm2, -0x8(%rbp,%rsi,8)
movl (%rdx), %esi
addq $0x10, %rdx
cmpl $-0x1, %esi
jne 0x73b4
movl %ecx, (%r15,%rcx,4)
incq %rcx
cmpq %r14, %rcx
jne 0x737d
movsd 0xfe8b(%rip), %xmm0     # 0x17288
minsd 0x58(%rsp), %xmm0
imulq $0x66666667, %r14, %rcx # imm = 0x66666667
movq %rcx, %rax
shrq $0x3f, %rax
sarq $0x22, %rcx
addl %eax, %ecx
movq %rcx, 0xd0(%rsp)
movl %r14d, %eax
movq %rax, 0xc8(%rsp)
movsd 0xfe66(%rip), %xmm1     # 0x17298
movsd %xmm1, 0x8(%rsp)
xorl %ebx, %ebx
movq %r15, 0x88(%rsp)
movq %r14, 0x78(%rsp)
movq %r13, 0x90(%rsp)
movsd %xmm0, 0xc0(%rsp)
cmpl $0x3e8, %ebx            # imm = 0x3E8
je 0x787d
movl %ebx, 0x6c(%rsp)
testl %r14d, %r14d
jle 0x749e
movq 0xc8(%rsp), %rbx
xorl %r14d, %r14d
callq 0x30a0
cltd
idivl %ebx
movslq %edx, %rax
addq %r14, %rax
movl (%r15,%r14,4), %ecx
movl (%r15,%rax,4), %edx
movl %edx, (%r15,%r14,4)
movl %ecx, (%r15,%rax,4)
incq %r14
decq %rbx
jne 0x7478
movq 0x78(%rsp), %r14
testl %r14d, %r14d
jle 0x77ee
xorpd %xmm2, %xmm2
xorl %r13d, %r13d
movl $0x0, 0x14(%rsp)
movsd %xmm2, 0x60(%rsp)
movslq (%r15,%r13,4), %r15
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%r15,8), %rax
movl (%rax), %ecx
xorpd %xmm3, %xmm3
cmpl $-0x1, %ecx
je 0x74fe
addq $0x10, %rax
movslq %ecx, %rcx
movsd -0x8(%rbp,%rcx,8), %xmm0
mulsd -0x8(%rax), %xmm0
addsd %xmm0, %xmm3
movl (%rax), %ecx
addq $0x10, %rax
cmpl $-0x1, %ecx
jne 0x74e1
movq 0x90(%rsp), %rax
movsbq (%rax,%r15), %rax
movsbl %al, %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd (%r12,%r15,8), %xmm5
movsd %xmm0, 0xd8(%rsp)
mulsd %xmm0, %xmm3
leal (%r15,%r15), %ecx
leal 0x1(%r15,%r15), %edx
movapd %xmm5, %xmm0
movsd 0xfb93(%rip), %xmm2     # 0x170d0
mulsd %xmm2, %xmm0
movslq %edx, %rbx
movq 0x18(%rsp), %rdi
movsd (%rdi,%rbx,8), %xmm1
movslq %ecx, %rcx
subsd (%rdi,%rcx,8), %xmm1
mulsd %xmm0, %xmm1
addsd %xmm3, %xmm1
xorl %edx, %edx
xorpd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
movl %ecx, %esi
cmoval %ebx, %esi
movsd 0xa8(%rsp,%rax,8), %xmm7
cmoval %ecx, %ebx
seta %dl
leaq 0xfd4d(%rip), %rax      # 0x172d0
movsd (%rax,%rdx,8), %xmm4
movslq %esi, %r12
movsd (%rdi,%r12,8), %xmm6
movapd %xmm7, %xmm8
subsd %xmm6, %xmm8
movapd %xmm7, %xmm0
mulsd %xmm2, %xmm0
movapd %xmm6, %xmm1
mulsd 0xfb39(%rip), %xmm1     # 0x170e8
cmpltsd %xmm0, %xmm8
andpd %xmm8, %xmm1
andnpd %xmm6, %xmm8
orpd %xmm1, %xmm8
movapd %xmm8, %xmm0
movapd %xmm6, 0xf0(%rsp)
subsd %xmm6, %xmm0
movsd %xmm4, 0xe0(%rsp)
mulsd %xmm4, %xmm3
movsd %xmm5, 0x38(%rsp)
mulsd %xmm5, %xmm0
movsd %xmm3, 0xe8(%rsp)
addsd %xmm3, %xmm0
movapd %xmm0, 0x40(%rsp)
movsd %xmm7, 0x98(%rsp)
movapd %xmm7, %xmm1
subsd %xmm8, %xmm1
movapd %xmm8, 0x20(%rsp)
movapd %xmm8, %xmm0
divsd %xmm1, %xmm0
callq 0x3190
movapd %xmm0, %xmm5
addsd 0x40(%rsp), %xmm5
movapd %xmm5, %xmm4
andpd 0xfab3(%rip), %xmm4     # 0x170f0
movsd 0x8(%rsp), %xmm0
ucomisd %xmm4, %xmm0
ja 0x7734
movapd %xmm4, 0x100(%rsp)
xorl %eax, %eax
movsd 0x38(%rsp), %xmm2
movl %eax, %r14d
movsd 0x98(%rsp), %xmm3
movapd %xmm3, %xmm0
movapd 0x20(%rsp), %xmm4
subsd %xmm4, %xmm0
movapd %xmm3, %xmm1
divsd %xmm0, %xmm1
divsd %xmm4, %xmm1
addsd %xmm2, %xmm1
divsd %xmm1, %xmm5
movapd %xmm4, %xmm0
subsd %xmm5, %xmm0
mulsd 0xfa4c(%rip), %xmm4     # 0x170e8
movapd %xmm0, %xmm2
cmpnlesd 0xe967(%rip), %xmm2     # 0x16010
andpd %xmm2, %xmm0
andnpd %xmm4, %xmm2
orpd %xmm0, %xmm2
movapd %xmm2, 0x40(%rsp)
movapd %xmm2, 0x20(%rsp)
movapd %xmm3, %xmm1
subsd %xmm2, %xmm1
movapd %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x3190
movapd 0x40(%rsp), %xmm5
movsd 0x38(%rsp), %xmm2
leal 0x1(%r14), %eax
cmpl $0x63, %r14d
ja 0x7722
subsd 0xf0(%rsp), %xmm5
mulsd %xmm2, %xmm5
addsd 0xe8(%rsp), %xmm5
addsd %xmm0, %xmm5
movapd %xmm5, %xmm0
andpd 0xf9de(%rip), %xmm0     # 0x170f0
movsd 0x8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x765e
addl %eax, 0x14(%rsp)
movq 0x78(%rsp), %r14
movapd 0x100(%rsp), %xmm4
movsd 0x8(%rsp), %xmm0
ucomisd %xmm4, %xmm0
movsd 0x60(%rsp), %xmm2
movsd 0xe0(%rsp), %xmm1
ja 0x77cc
movq 0x18(%rsp), %rcx
movapd 0x20(%rsp), %xmm3
movsd %xmm3, (%rcx,%r12,8)
movsd 0x98(%rsp), %xmm0
subsd %xmm3, %xmm0
movslq %ebx, %rax
movsd %xmm0, (%rcx,%rax,8)
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%r15,8), %rax
movl (%rax), %ecx
cmpl $-0x1, %ecx
je 0x77cc
movapd 0x20(%rsp), %xmm0
subsd 0xf0(%rsp), %xmm0
mulsd %xmm0, %xmm1
mulsd 0xd8(%rsp), %xmm1
addq $0x10, %rax
movslq %ecx, %rcx
movsd -0x8(%rax), %xmm0
mulsd %xmm1, %xmm0
addsd -0x8(%rbp,%rcx,8), %xmm0
movsd %xmm0, -0x8(%rbp,%rcx,8)
movl (%rax), %ecx
addq $0x10, %rax
cmpl $-0x1, %ecx
jne 0x77a9
maxsd %xmm4, %xmm2
incq %r13
cmpq %r14, %r13
movq 0x88(%rsp), %r15
movq 0x80(%rsp), %r12
jne 0x74bb
jmp 0x77fa
movl $0x0, 0x14(%rsp)
xorpd %xmm2, %xmm2
movl 0x6c(%rsp), %ebx
incl %ebx
imull $0xcccccccd, %ebx, %eax # imm = 0xCCCCCCCD
rorl %eax
cmpl $0x19999999, %eax       # imm = 0x19999999
movq 0x90(%rsp), %r13
ja 0x7831
leaq 0x10130(%rip), %rdi     # 0x1794e
xorl %eax, %eax
movsd %xmm2, 0x60(%rsp)
callq 0x7152
movsd 0x60(%rsp), %xmm2
movsd 0x58(%rsp), %xmm0
ucomisd %xmm2, %xmm0
ja 0x786b
movl 0x14(%rsp), %eax
cmpl 0xd0(%rsp), %eax
jg 0x786b
movsd 0x8(%rsp), %xmm1
mulsd 0xf890(%rip), %xmm1     # 0x170e8
movsd 0xc0(%rsp), %xmm0
maxsd %xmm1, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x58(%rsp), %xmm0
ucomisd %xmm2, %xmm0
jbe 0x7458
jmp 0x7882
movl $0x3e8, %ebx            # imm = 0x3E8
leaq 0xfbf1(%rip), %rdi      # 0x1747a
movl %ebx, %esi
xorl %eax, %eax
callq 0x7152
cmpl $0x3e8, %ebx            # imm = 0x3E8
jl 0x78a8
leaq 0xfc4b(%rip), %rdi      # 0x174ec
xorl %eax, %eax
callq 0x7152
movq 0x70(%rsp), %rcx
xorpd %xmm1, %xmm1
testl %ecx, %ecx
jle 0x78d5
xorl %eax, %eax
movsd (%rbp,%rax,8), %xmm0
mulsd %xmm0, %xmm0
addsd %xmm0, %xmm1
incq %rax
cmpq %rax, %rcx
jne 0x78b7
mulsd 0xf7fb(%rip), %xmm1     # 0x170d0
testl %r14d, %r14d
jle 0x7975
movq 0x18(%rsp), %rbx
addq $0x8, %rbx
xorl %r15d, %r15d
movsd %xmm1, 0x40(%rsp)
movsd -0x8(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x3190
movsd %xmm0, 0x20(%rsp)
movsd (%rbx), %xmm0
movsd %xmm0, 0x38(%rsp)
callq 0x3190
mulsd 0x38(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
mulsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x20(%rsp)
movsbq (%r13,%r15), %rax
movsd 0xa8(%rsp,%rax,8), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x3190
movsd 0x40(%rsp), %xmm1
mulsd 0x8(%rsp), %xmm0
movsd 0x20(%rsp), %xmm2
subsd %xmm0, %xmm2
addsd %xmm2, %xmm1
incq %r15
addq $0x10, %rbx
cmpq %r15, %r14
jne 0x78ea
leaq 0xfb4f(%rip), %rdi      # 0x174cb
movapd %xmm1, %xmm0
movb $0x1, %al
callq 0x7152
movq %r12, %rdi
callq 0x32c0
movq 0x18(%rsp), %rdi
callq 0x32c0
movq %r13, %rdi
callq 0x32c0
movq 0x88(%rsp), %rdi
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32c0