// File: /workspace/github_cpp_makefile_star2_O3/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 $0xf8, %rsp
movsd %xmm2, 0x20(%rsp)
movsd %xmm1, 0x30(%rsp)
movsd %xmm0, 0x80(%rsp)
movq %rsi, %r13
movq %rdi, %rcx
movslq (%rdi), %r12
movq %r12, %r15
shlq $0x4, %r15
testq %r12, %r12
movq $-0x1, %rax
cmovsq %rax, %r15
leaq (,%r12,4), %rbx
testq %r12, %r12
cmovsq %rax, %rbx
leaq (,%r12,8), %rdi
testq %r12, %r12
movq %rcx, 0x60(%rsp)
movl 0x4(%rcx), %ecx
movq %rcx, 0x78(%rsp)
cmovsq %rax, %rdi
callq 0x3030
movq %rax, 0x48(%rsp)
movq %rbx, %rdi
callq 0x3030
movq %rax, %rbp
movq %r15, %rdi
callq 0x3030
movq %rax, 0x18(%rsp)
movq %r12, %rdi
callq 0x3030
movq %rax, %r14
movl %r12d, %r15d
movsd 0x11e11(%rip), %xmm0    # 0x192b8
movsd 0x20(%rsp), %xmm1
movsd %xmm1, 0xa0(%rsp)
movq $0x0, 0xa8(%rsp)
movsd 0x30(%rsp), %xmm1
movsd %xmm1, 0xb0(%rsp)
testq %r12, %r12
jle 0x7555
movapd %xmm0, %xmm2
movq 0x60(%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, (%r14,%rcx)
incq %rcx
cmpq %rcx, %r15
jne 0x74e9
testl %r15d, %r15d
jle 0x7555
movapd %xmm2, %xmm3
movq 0x18(%rsp), %rax
addq $0x8, %rax
xorl %ecx, %ecx
movsd 0x11d9e(%rip), %xmm0    # 0x192c0
movsbq (%r14,%rcx), %rdx
movsd 0xa8(%rsp,%rdx,8), %xmm1
movapd %xmm1, %xmm2
mulsd %xmm0, %xmm2
minsd %xmm3, %xmm2
movsd %xmm2, -0x8(%rax)
subsd %xmm2, %xmm1
movsd %xmm1, (%rax)
incq %rcx
addq $0x10, %rax
cmpq %rcx, %r15
jne 0x7522
movq 0x78(%rsp), %rax
testl %eax, %eax
jle 0x7570
leaq (,%rax,8), %rdx
movq %r13, %rdi
xorl %esi, %esi
callq 0x3110
testl %r15d, %r15d
movq 0x48(%rsp), %rbx
jle 0x7604
movq 0x60(%rsp), %rax
movq 0x10(%rax), %rax
xorl %ecx, %ecx
movq 0x18(%rsp), %r8
movq $0x0, (%rbx,%rcx,8)
movq (%rax,%rcx,8), %rdx
movl (%rdx), %esi
cmpl $-0x1, %esi
je 0x75f8
movsbl (%r14,%rcx), %edi
xorps %xmm0, %xmm0
cvtsi2sd %edi, %xmm0
movq %rcx, %rdi
shlq $0x4, %rdi
mulsd (%r8,%rdi), %xmm0
addq $0x10, %rdx
xorpd %xmm1, %xmm1
movsd -0x8(%rdx), %xmm2
movapd %xmm2, %xmm3
mulsd %xmm2, %xmm3
addsd %xmm3, %xmm1
movsd %xmm1, (%rbx,%rcx,8)
movslq %esi, %rsi
mulsd %xmm0, %xmm2
addsd -0x8(%r13,%rsi,8), %xmm2
movsd %xmm2, -0x8(%r13,%rsi,8)
movl (%rdx), %esi
addq $0x10, %rdx
cmpl $-0x1, %esi
jne 0x75c2
movl %ecx, (%rbp,%rcx,4)
incq %rcx
cmpq %r15, %rcx
jne 0x758e
movq %r14, 0x88(%rsp)
movsd 0x11ca4(%rip), %xmm1    # 0x192b8
minsd 0x80(%rsp), %xmm1
movslq %r15d, %rax
imulq $0x66666667, %rax, %rcx # imm = 0x66666667
movq %rcx, %rax
shrq $0x3f, %rax
sarq $0x22, %rcx
addl %eax, %ecx
movq %rcx, 0xc0(%rsp)
movsd 0x109f4(%rip), %xmm0    # 0x18038
movsd %xmm0, 0x8(%rsp)
movq $0x0, 0x70(%rsp)
movq %rbp, 0x58(%rsp)
movq %r15, 0x50(%rsp)
movsd %xmm1, 0xb8(%rsp)
xorpd %xmm1, %xmm1
movl $0x0, 0x14(%rsp)
testl %r15d, %r15d
jle 0x7a1a
movq %r15, %rbx
xorl %r14d, %r14d
callq 0x30a0
cltd
idivl %ebx
movslq %edx, %rax
addq %r14, %rax
movl (%rbp,%r14,4), %ecx
movl (%rbp,%rax,4), %edx
movl %edx, (%rbp,%r14,4)
movl %ecx, (%rbp,%rax,4)
incq %r14
decq %rbx
jne 0x7681
xorpd %xmm1, %xmm1
movl $0x0, 0x14(%rsp)
testl %r15d, %r15d
movq 0x48(%rsp), %rbx
jle 0x7a1a
xorl %r12d, %r12d
movl $0x0, 0x14(%rsp)
movsd %xmm1, 0x28(%rsp)
movslq (%rbp,%r12,4), %rbp
movq 0x60(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%rbp,8), %rax
movl (%rax), %ecx
xorpd %xmm3, %xmm3
cmpl $-0x1, %ecx
je 0x7713
addq $0x10, %rax
movslq %ecx, %rcx
movsd -0x8(%r13,%rcx,8), %xmm0
mulsd -0x8(%rax), %xmm0
addsd %xmm0, %xmm3
movl (%rax), %ecx
addq $0x10, %rax
cmpl $-0x1, %ecx
jne 0x76f5
movq 0x88(%rsp), %rax
movsbq (%rax,%rbp), %rax
movsbl %al, %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd (%rbx,%rbp,8), %xmm5
movsd %xmm0, 0xd0(%rsp)
mulsd %xmm0, %xmm3
leal (%rbp,%rbp), %ecx
leal 0x1(%rbp,%rbp), %edx
movapd %xmm5, %xmm0
movsd 0x119b0(%rip), %xmm2    # 0x19100
mulsd %xmm2, %xmm0
movslq %edx, %r14
movq 0x18(%rsp), %rdi
movsd (%rdi,%r14,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 %r14d, %esi
movsd 0xa8(%rsp,%rax,8), %xmm6
cmoval %ecx, %r14d
seta %dl
leaq 0x11ba7(%rip), %rax     # 0x19340
movsd (%rax,%rdx,8), %xmm4
movslq %esi, %r15
movsd (%rdi,%r15,8), %xmm7
movapd %xmm6, %xmm8
subsd %xmm7, %xmm8
movapd %xmm6, %xmm0
mulsd %xmm2, %xmm0
movapd %xmm7, %xmm1
mulsd 0x11953(%rip), %xmm1    # 0x19118
cmpltsd %xmm0, %xmm8
andpd %xmm8, %xmm1
andnpd %xmm7, %xmm8
orpd %xmm1, %xmm8
movapd %xmm8, %xmm0
movapd %xmm7, 0xe0(%rsp)
subsd %xmm7, %xmm0
movsd %xmm4, 0xc8(%rsp)
mulsd %xmm4, %xmm3
movsd %xmm5, 0x20(%rsp)
mulsd %xmm5, %xmm0
movsd %xmm3, 0xd8(%rsp)
addsd %xmm3, %xmm0
movapd %xmm0, 0x90(%rsp)
movsd %xmm6, 0x68(%rsp)
movapd %xmm6, %xmm1
subsd %xmm8, %xmm1
movapd %xmm8, 0x30(%rsp)
movapd %xmm8, %xmm0
divsd %xmm1, %xmm0
callq 0x31a0
addsd 0x90(%rsp), %xmm0
movapd %xmm0, %xmm3
andpd 0x118ce(%rip), %xmm3    # 0x19120
movsd 0x8(%rsp), %xmm1
ucomisd %xmm3, %xmm1
jbe 0x7868
movq 0x58(%rsp), %rbp
jmp 0x7958
movapd %xmm3, 0x90(%rsp)
xorl %eax, %eax
movsd 0x20(%rsp), %xmm3
movapd 0x30(%rsp), %xmm5
movl %eax, %ebx
movsd 0x68(%rsp), %xmm4
movapd %xmm4, %xmm1
subsd %xmm5, %xmm1
movapd %xmm4, %xmm2
divsd %xmm1, %xmm2
divsd %xmm5, %xmm2
addsd %xmm3, %xmm2
divsd %xmm2, %xmm0
movapd %xmm5, %xmm1
subsd %xmm0, %xmm1
mulsd 0x11865(%rip), %xmm5    # 0x19118
movapd %xmm1, %xmm0
cmpnlesd 0x10780(%rip), %xmm0    # 0x18040
andpd %xmm0, %xmm1
andnpd %xmm5, %xmm0
orpd %xmm1, %xmm0
movapd %xmm0, 0x30(%rsp)
movapd %xmm4, %xmm1
subsd %xmm0, %xmm1
divsd %xmm1, %xmm0
callq 0x31a0
movapd 0x30(%rsp), %xmm5
movsd 0x20(%rsp), %xmm3
leal 0x1(%rbx), %eax
cmpl $0x63, %ebx
ja 0x7935
movapd %xmm0, %xmm1
movapd %xmm5, %xmm0
subsd 0xe0(%rsp), %xmm0
mulsd %xmm3, %xmm0
addsd 0xd8(%rsp), %xmm0
addsd %xmm1, %xmm0
movapd %xmm0, %xmm1
andpd 0x117fb(%rip), %xmm1    # 0x19120
movsd 0x8(%rsp), %xmm2
ucomisd %xmm1, %xmm2
jbe 0x787f
addl %eax, 0x14(%rsp)
movsd 0x8(%rsp), %xmm0
movapd 0x90(%rsp), %xmm3
ucomisd %xmm3, %xmm0
jbe 0x7978
movq 0x58(%rsp), %rbp
movq 0x48(%rsp), %rbx
movq 0x50(%rsp), %r15
movsd 0x28(%rsp), %xmm1
maxsd %xmm3, %xmm1
incq %r12
cmpq %r15, %r12
jne 0x76ce
jmp 0x7a1a
movq 0x18(%rsp), %rcx
movsd %xmm5, (%rcx,%r15,8)
movsd 0x68(%rsp), %xmm0
subsd %xmm5, %xmm0
movslq %r14d, %rax
movsd %xmm0, (%rcx,%rax,8)
movq 0x60(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%rbp,8), %rax
movl (%rax), %ecx
cmpl $-0x1, %ecx
movq 0x48(%rsp), %rbx
movsd 0x28(%rsp), %xmm1
je 0x7a0b
subsd 0xe0(%rsp), %xmm5
movsd 0xc8(%rsp), %xmm2
mulsd %xmm5, %xmm2
mulsd 0xd0(%rsp), %xmm2
addq $0x10, %rax
movq 0x58(%rsp), %rbp
movq 0x50(%rsp), %r15
movslq %ecx, %rcx
movsd -0x8(%rax), %xmm0
mulsd %xmm2, %xmm0
addsd -0x8(%r13,%rcx,8), %xmm0
movsd %xmm0, -0x8(%r13,%rcx,8)
movl (%rax), %ecx
addq $0x10, %rax
cmpl $-0x1, %ecx
jne 0x79e1
jmp 0x7963
movq 0x58(%rsp), %rbp
movq 0x50(%rsp), %r15
jmp 0x7963
movq 0x70(%rsp), %rax
leal 0x1(%rax), %r12d
imull $0xcccccccd, %r12d, %eax # imm = 0xCCCCCCCD
rorl %eax
cmpl $0x19999999, %eax       # imm = 0x19999999
ja 0x7a4d
leaq 0x11f84(%rip), %rdi     # 0x199be
xorl %eax, %eax
movsd %xmm1, 0x28(%rsp)
callq 0x735c
movsd 0x28(%rsp), %xmm1
movsd 0x80(%rsp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x7ab4
movl 0x14(%rsp), %eax
cmpl 0xc0(%rsp), %eax
jg 0x7a8a
movsd 0x8(%rsp), %xmm2
mulsd 0x116a1(%rip), %xmm2    # 0x19118
movsd 0xb8(%rsp), %xmm0
maxsd %xmm2, %xmm0
movsd %xmm0, 0x8(%rsp)
movl %r12d, %eax
movq %rax, 0x70(%rsp)
cmpl $0x3e8, %r12d           # imm = 0x3E8
jne 0x7666
leaq 0x11a44(%rip), %rdi     # 0x194ea
movl $0x3e8, %esi            # imm = 0x3E8
xorl %eax, %eax
callq 0x735c
jmp 0x7acf
leaq 0x11a2f(%rip), %rdi     # 0x194ea
movl %r12d, %esi
xorl %eax, %eax
callq 0x735c
cmpl $0x3e7, 0x70(%rsp)      # imm = 0x3E7
jb 0x7add
leaq 0x11a86(%rip), %rdi     # 0x1955c
xorl %eax, %eax
callq 0x735c
movq 0x78(%rsp), %rcx
testl %ecx, %ecx
movq 0x88(%rsp), %r12
xorpd %xmm1, %xmm1
jle 0x7b13
xorl %eax, %eax
movsd (%r13,%rax,8), %xmm0
mulsd %xmm0, %xmm0
addsd %xmm0, %xmm1
incq %rax
cmpq %rax, %rcx
jne 0x7af4
mulsd 0x115ed(%rip), %xmm1    # 0x19100
testl %r15d, %r15d
jle 0x7bb7
movq 0x18(%rsp), %r14
addq $0x8, %r14
movq %r15, %r13
xorl %r15d, %r15d
movsd %xmm1, 0x20(%rsp)
movsd -0x8(%r14), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x31a0
movsd %xmm0, 0x30(%rsp)
movsd (%r14), %xmm0
movsd %xmm0, 0x68(%rsp)
callq 0x31a0
mulsd 0x68(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
mulsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x30(%rsp)
movsbq (%r12,%r15), %rax
movsd 0xa8(%rsp,%rax,8), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x31a0
movsd 0x20(%rsp), %xmm1
mulsd 0x8(%rsp), %xmm0
movsd 0x30(%rsp), %xmm2
subsd %xmm0, %xmm2
addsd %xmm2, %xmm1
incq %r15
addq $0x10, %r14
cmpq %r15, %r13
jne 0x7b2b
leaq 0x1197d(%rip), %rdi     # 0x1953b
movapd %xmm1, %xmm0
movb $0x1, %al
callq 0x735c
movq %rbx, %rdi
callq 0x32d0
movq 0x18(%rsp), %rdi
callq 0x32d0
movq %r12, %rdi
callq 0x32d0
movq %rbp, %rdi
addq $0xf8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32d0