// File: /workspace/github_cpp_makefile_star2_O2/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, 0x80(%rsp)
movq %rsi, %r13
movq %rdi, %rcx
movslq (%rdi), %rbx
movq %rbx, %r15
shlq $0x4, %r15
testq %rbx, %rbx
pushq $-0x1
popq %rax
cmovsq %rax, %r15
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, 0x58(%rsp)
cmovsq %rax, %rdi
callq 0x3030
movq %rax, %rbp
movq %r14, %rdi
callq 0x3030
movq %rax, %r12
movq %r15, %rdi
callq 0x3030
movq %rax, %r14
movq %rbx, %rdi
callq 0x3030
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x90(%rsp)
andq $0x0, 0x98(%rsp)
movq %rax, %r15
movsd 0x20(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
xorl %eax, %eax
testl %ebx, %ebx
movl $0x0, %ecx
movq %rbx, 0x78(%rsp)
cmovgl %ebx, %ecx
movq %rcx, 0x10(%rsp)
xorpd %xmm0, %xmm0
cmpq %rax, 0x10(%rsp)
je 0x6c41
movq 0x30(%rsp), %rcx
movq 0x8(%rcx), %rcx
movsd (%rcx,%rax,8), %xmm1
ucomisd %xmm0, %xmm1
setbe %cl
negb %cl
orb $0x1, %cl
movb %cl, (%r15,%rax)
incq %rax
jmp 0x6c17
leaq 0x8(%r14), %rax
xorl %ecx, %ecx
movsd 0xf669(%rip), %xmm0     # 0x162b8
movsd 0xf669(%rip), %xmm1     # 0x162c0
movsd %xmm1, 0x50(%rsp)
cmpq %rcx, 0x10(%rsp)
je 0x6c98
movsbq (%r15,%rcx), %rdx
movsd 0x98(%rsp,%rdx,8), %xmm1
movapd %xmm1, %xmm2
mulsd %xmm0, %xmm2
minsd 0xf63e(%rip), %xmm2     # 0x162c0
movsd %xmm2, -0x8(%rax)
subsd %xmm2, %xmm1
movsd %xmm1, (%rax)
incq %rcx
addq $0x10, %rax
jmp 0x6c5d
xorl %eax, %eax
movq 0x58(%rsp), %rcx
testl %ecx, %ecx
cmovlel %eax, %ecx
cmpq %rax, %rcx
je 0x6cb4
andq $0x0, (%r13,%rax,8)
incq %rax
jmp 0x6ca4
movq %rcx, 0x58(%rsp)
xorl %eax, %eax
cmpq 0x10(%rsp), %rax
je 0x6d2c
andq $0x0, (%rbp,%rax,8)
movq 0x30(%rsp), %rcx
movq 0x10(%rcx), %rcx
movq (%rcx,%rax,8), %rcx
movq %rax, %rdx
shlq $0x4, %rdx
xorpd %xmm0, %xmm0
movslq (%rcx), %rsi
cmpq $-0x1, %rsi
je 0x6d23
movsbl (%r15,%rax), %edi
cvtsi2sd %edi, %xmm1
movsd 0x8(%rcx), %xmm2
mulsd (%r14,%rdx), %xmm1
mulsd %xmm2, %xmm1
mulsd %xmm2, %xmm2
addsd %xmm2, %xmm0
movsd %xmm0, (%rbp,%rax,8)
addsd -0x8(%r13,%rsi,8), %xmm1
movsd %xmm1, -0x8(%r13,%rsi,8)
addq $0x10, %rcx
jmp 0x6ce0
movl %eax, (%r12,%rax,4)
incq %rax
jmp 0x6cbb
movsd 0x50(%rsp), %xmm0
minsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
pushq $0xa
popq %rcx
movq 0x78(%rsp), %rax
cltd
idivl %ecx
movl %eax, 0x70(%rsp)
movsd 0xe2e0(%rip), %xmm0     # 0x15038
movsd %xmm0, 0x68(%rsp)
xorl %esi, %esi
movq %r14, 0x60(%rsp)
movq %r12, 0xc0(%rsp)
movq %rbp, 0xb8(%rsp)
movq %r15, 0xb0(%rsp)
cmpl $0x3e8, %esi            # imm = 0x3E8
je 0x7160
movl %esi, 0x74(%rsp)
movq 0x78(%rsp), %rax
movl %eax, %ebx
xorl %r14d, %r14d
cmpq %r14, 0x10(%rsp)
je 0x6dc3
callq 0x30a0
cltd
idivl %ebx
movslq %edx, %rax
addq %r14, %rax
movl (%r12,%r14,4), %ecx
movl (%r12,%rax,4), %edx
movl %edx, (%r12,%r14,4)
movl %ecx, (%r12,%rax,4)
incq %r14
decl %ebx
jmp 0x6d97
xorl %eax, %eax
xorpd %xmm1, %xmm1
xorl %edi, %edi
cmpq 0x10(%rsp), %rax
movq 0x60(%rsp), %r14
movsd %xmm1, 0x88(%rsp)
movl %edi, 0x1c(%rsp)
je 0x70f2
movq %rax, 0xe0(%rsp)
movslq (%r12,%rax,4), %r12
movsbq (%r15,%r12), %rax
movsd 0x98(%rsp,%rax,8), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd (%rbp,%r12,8), %xmm0
movsd %xmm0, 0x38(%rsp)
movq 0x30(%rsp), %rcx
movq 0x10(%rcx), %rcx
movq (%rcx,%r12,8), %rcx
xorpd %xmm4, %xmm4
movslq (%rcx), %rdx
cmpq $-0x1, %rdx
je 0x6e45
movsd -0x8(%r13,%rdx,8), %xmm0
mulsd 0x8(%rcx), %xmm0
addsd %xmm0, %xmm4
addq $0x10, %rcx
jmp 0x6e26
movsbl %al, %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0xd0(%rsp)
mulsd %xmm0, %xmm4
leal (%r12,%r12), %ebx
leal 0x1(%r12,%r12), %ebp
movsd 0x38(%rsp), %xmm3
movapd %xmm3, %xmm0
movsd 0xf28c(%rip), %xmm1     # 0x16100
mulsd %xmm1, %xmm0
movslq %ebp, %rax
movsd (%r14,%rax,8), %xmm2
movslq %ebx, %rcx
subsd (%r14,%rcx,8), %xmm2
mulsd %xmm0, %xmm2
addsd %xmm4, %xmm2
xorl %edx, %edx
xorpd %xmm0, %xmm0
movsd %xmm2, 0xc8(%rsp)
ucomisd %xmm2, %xmm0
cmoval %eax, %ecx
seta %dl
leaq 0xf43e(%rip), %rax      # 0x162f0
movsd (%rax,%rdx,8), %xmm5
movslq %ecx, %r15
movsd (%r14,%r15,8), %xmm6
movsd 0x8(%rsp), %xmm2
movapd %xmm2, %xmm7
subsd %xmm6, %xmm7
movapd %xmm2, %xmm0
mulsd %xmm1, %xmm0
movapd %xmm6, %xmm1
mulsd 0xf236(%rip), %xmm1     # 0x16118
cmpltsd %xmm0, %xmm7
andpd %xmm7, %xmm1
andnpd %xmm6, %xmm7
orpd %xmm1, %xmm7
movapd %xmm7, 0x40(%rsp)
movapd %xmm7, %xmm0
movapd %xmm6, 0xf0(%rsp)
subsd %xmm6, %xmm0
movsd %xmm5, 0xd8(%rsp)
mulsd %xmm5, %xmm4
mulsd %xmm3, %xmm0
movsd %xmm4, 0xe8(%rsp)
addsd %xmm4, %xmm0
movapd %xmm0, 0x20(%rsp)
movapd %xmm2, %xmm1
subsd %xmm7, %xmm1
movapd %xmm7, %xmm0
divsd %xmm1, %xmm0
callq 0x31b0
movapd 0x40(%rsp), %xmm5
addsd 0x20(%rsp), %xmm0
movapd %xmm0, %xmm1
andpd 0xf1c5(%rip), %xmm1     # 0x16120
movapd %xmm1, 0x100(%rsp)
xorl %r14d, %r14d
cmpl $0x64, %r14d
ja 0x702d
movapd %xmm0, %xmm1
andpd 0xf1a3(%rip), %xmm1     # 0x16120
movsd 0x68(%rsp), %xmm2
ucomisd %xmm1, %xmm2
ja 0x702d
movsd 0x8(%rsp), %xmm3
movapd %xmm3, %xmm1
subsd %xmm5, %xmm1
movapd %xmm3, %xmm2
divsd %xmm1, %xmm2
divsd %xmm5, %xmm2
movsd 0x38(%rsp), %xmm4
addsd %xmm4, %xmm2
divsd %xmm2, %xmm0
movapd %xmm5, %xmm1
subsd %xmm0, %xmm1
mulsd 0xf153(%rip), %xmm5     # 0x16118
movapd %xmm1, %xmm2
cmpnlesd 0xe06e(%rip), %xmm2     # 0x15040
andpd %xmm2, %xmm1
andnpd %xmm5, %xmm2
orpd %xmm1, %xmm2
movapd %xmm2, 0x40(%rsp)
movapd %xmm2, %xmm0
subsd 0xf0(%rsp), %xmm0
mulsd %xmm4, %xmm0
addsd 0xe8(%rsp), %xmm0
movapd %xmm0, 0x20(%rsp)
movapd %xmm3, %xmm1
subsd %xmm2, %xmm1
movapd %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x31b0
addsd 0x20(%rsp), %xmm0
incl %r14d
movapd 0x40(%rsp), %xmm5
jmp 0x6f67
testl %r14d, %r14d
movsd 0x88(%rsp), %xmm1
movl 0x1c(%rsp), %edi
movsd 0xd8(%rsp), %xmm2
je 0x70be
xorpd %xmm0, %xmm0
ucomisd 0xc8(%rsp), %xmm0
cmoval %ebx, %ebp
movq 0x60(%rsp), %rcx
movsd %xmm5, (%rcx,%r15,8)
movsd 0x8(%rsp), %xmm0
subsd %xmm5, %xmm0
movslq %ebp, %rax
movsd %xmm0, (%rcx,%rax,8)
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%r12,8), %rax
subsd 0xf0(%rsp), %xmm5
mulsd %xmm5, %xmm2
mulsd 0xd0(%rsp), %xmm2
movslq (%rax), %rcx
cmpq $-0x1, %rcx
je 0x70be
movsd 0x8(%rax), %xmm0
mulsd %xmm2, %xmm0
addsd -0x8(%r13,%rcx,8), %xmm0
movsd %xmm0, -0x8(%r13,%rcx,8)
addq $0x10, %rax
jmp 0x7098
maxsd 0x100(%rsp), %xmm1
addl %r14d, %edi
movq 0xe0(%rsp), %rax
incq %rax
movq 0xc0(%rsp), %r12
movq 0xb8(%rsp), %rbp
movq 0xb0(%rsp), %r15
jmp 0x6dcb
movl 0x74(%rsp), %esi
incl %esi
movl %esi, %eax
xorl %edx, %edx
pushq $0xa
popq %rcx
divl %ecx
testl %edx, %edx
jne 0x7124
leaq 0xf882(%rip), %rdi      # 0x1698e
xorl %eax, %eax
movl %esi, %ebx
callq 0x6a9e
movl 0x1c(%rsp), %edi
movsd 0x88(%rsp), %xmm1
movl %ebx, %esi
movsd 0x80(%rsp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x7165
cmpl 0x70(%rsp), %edi
jg 0x6d7d
movsd 0x68(%rsp), %xmm1
mulsd 0xefcd(%rip), %xmm1     # 0x16118
movsd 0x50(%rsp), %xmm0
maxsd %xmm1, %xmm0
movsd %xmm0, 0x68(%rsp)
jmp 0x6d7d
movl $0x3e8, %esi            # imm = 0x3E8
leaq 0xf34e(%rip), %rdi      # 0x164ba
xorl %eax, %eax
movl %esi, %ebx
callq 0x6a9e
cmpl $0x3e8, %ebx            # imm = 0x3E8
jl 0x718b
leaq 0xf3a8(%rip), %rdi      # 0x1652c
xorl %eax, %eax
callq 0x6a9e
xorpd %xmm1, %xmm1
xorl %eax, %eax
movq 0x58(%rsp), %rcx
cmpq %rax, %rcx
je 0x71af
movsd (%r13,%rax,8), %xmm0
mulsd %xmm0, %xmm0
addsd %xmm0, %xmm1
incq %rax
jmp 0x7196
mulsd 0xef49(%rip), %xmm1     # 0x16100
movq %r14, %rbx
addq $0x8, %rbx
xorl %r14d, %r14d
cmpq %r14, 0x10(%rsp)
je 0x7252
movsd -0x8(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd %xmm1, 0x40(%rsp)
callq 0x31b0
movsd %xmm0, 0x20(%rsp)
movsd (%rbx), %xmm0
movsd %xmm0, 0x38(%rsp)
callq 0x31b0
mulsd 0x38(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
mulsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x20(%rsp)
movsbq (%r15,%r14), %rax
movsd 0x98(%rsp,%rax,8), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x31b0
movsd 0x40(%rsp), %xmm1
mulsd 0x8(%rsp), %xmm0
movsd 0x20(%rsp), %xmm2
subsd %xmm0, %xmm2
addsd %xmm2, %xmm1
incq %r14
addq $0x10, %rbx
jmp 0x71c1
leaq 0xf2b2(%rip), %rdi      # 0x1650b
movapd %xmm1, %xmm0
movb $0x1, %al
callq 0x6a9e
movq %rbp, %rdi
callq 0x32f0
movq 0x60(%rsp), %rdi
callq 0x32f0
movq %r15, %rdi
callq 0x32f0
movq %r12, %rdi
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32f0