// File: /workspace/github_cpp_makefile_star2_O2/cjlin1[P]liblinear/linear.cpp
// Function: solve_l2r_l1l2_svc(problem const*, parameter const*, double*, double, double, int)
static int solve_l2r_l1l2_svc(const problem *prob, const parameter *param, double *w, double Cp, double Cn, int max_iter=300)
{
	int l = prob->l;
	int w_size = prob->n;
	double eps = param->eps;
	int solver_type = param->solver_type;
	int i, s, iter = 0;
	double C, d, G;
	double *QD = new double[l];
	int *index = new int[l];
	double *alpha = new double[l];
	schar *y = new schar[l];
	int active_size = l;

	// PG: projected gradient, for shrinking and stopping
	double PG;
	double PGmax_old = INF;
	double PGmin_old = -INF;
	double PGmax_new, PGmin_new;

	// default solver_type: L2R_L2LOSS_SVC_DUAL
	double diag[3] = {0.5/Cn, 0, 0.5/Cp};
	double upper_bound[3] = {INF, 0, INF};
	if(solver_type == L2R_L1LOSS_SVC_DUAL)
	{
		diag[0] = 0;
		diag[2] = 0;
		upper_bound[0] = Cn;
		upper_bound[2] = 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)]
	for(i=0; i<l; i++)
		alpha[i] = 0;

	for(i=0; i<w_size; i++)
		w[i] = 0;
	for(i=0; i<l; i++)
	{
		QD[i] = diag[GETI(i)];

		feature_node * const xi = prob->x[i];
		QD[i] += sparse_operator::nrm2_sq(xi);
		sparse_operator::axpy(y[i]*alpha[i], xi, w);

		index[i] = i;
	}

	while (iter < max_iter)
	{
		PGmax_new = -INF;
		PGmin_new = INF;

		for (i=0; i<active_size; i++)
		{
			int j = i+rand()%(active_size-i);
			swap(index[i], index[j]);
		}

		for (s=0; s<active_size; s++)
		{
			i = index[s];
			const schar yi = y[i];
			feature_node * const xi = prob->x[i];

			G = yi*sparse_operator::dot(w, xi)-1;

			C = upper_bound[GETI(i)];
			G += alpha[i]*diag[GETI(i)];

			PG = 0;
			if (alpha[i] == 0)
			{
				if (G > PGmax_old)
				{
					active_size--;
					swap(index[s], index[active_size]);
					s--;
					continue;
				}
				else if (G < 0)
					PG = G;
			}
			else if (alpha[i] == C)
			{
				if (G < PGmin_old)
				{
					active_size--;
					swap(index[s], index[active_size]);
					s--;
					continue;
				}
				else if (G > 0)
					PG = G;
			}
			else
				PG = G;

			PGmax_new = max(PGmax_new, PG);
			PGmin_new = min(PGmin_new, PG);

			if(fabs(PG) > 1.0e-12)
			{
				double alpha_old = alpha[i];
				alpha[i] = min(max(alpha[i] - G/QD[i], 0.0), C);
				d = (alpha[i] - alpha_old)*yi;
				sparse_operator::axpy(d, xi, w);
			}
		}

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

		if(PGmax_new - PGmin_new <= eps &&
			fabs(PGmax_new) <= eps && fabs(PGmin_new) <= eps)
		{
			if(active_size == l)
				break;
			else
			{
				active_size = l;
				info("*");
				PGmax_old = INF;
				PGmin_old = -INF;
				continue;
			}
		}
		PGmax_old = PGmax_new;
		PGmin_old = PGmin_new;
		if (PGmax_old <= 0)
			PGmax_old = INF;
		if (PGmin_old >= 0)
			PGmin_old = -INF;
	}

	info("\noptimization finished, #iter = %d\n",iter);

	// calculate objective value

	double v = 0;
	int nSV = 0;
	for(i=0; i<w_size; i++)
		v += w[i]*w[i];
	for(i=0; i<l; i++)
	{
		v += alpha[i]*(alpha[i]*diag[GETI(i)] - 2);
		if(alpha[i] > 0)
			++nSV;
	}
	info("Objective value = %lf\n",v/2);
	info("nSV = %d\n",nSV);

	// Reconstruct w from the primal-dual relationship w=sum(\alpha_i y_i x_i)
	// This may reduce the weight density. Some zero weights become non-zeros
	// due to the numerical update w <- w + (alpha[i] - alpha_old) y_i x_i.
	if (param->w_recalc)
	{
		for(i=0; i<w_size; i++)
			w[i] = 0;
		for(i=0; i<l; i++)
		{
			feature_node * const xi = prob->x[i];
			if(alpha[i] > 0)
				sparse_operator::axpy(y[i]*alpha[i], xi, w);
		}
	}

	delete [] QD;
	delete [] alpha;
	delete [] y;
	delete [] index;

	return iter;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movsd %xmm1, 0x60(%rsp)
movsd %xmm0, 0x20(%rsp)
movq %rdx, 0x8(%rsp)
movslq (%rdi), %r13
movq %rdi, 0x18(%rsp)
movl 0x4(%rdi), %r14d
movsd 0x8(%rsi), %xmm0
movsd %xmm0, 0x48(%rsp)
movq %rsi, 0xc0(%rsp)
movl (%rsi), %ebx
leaq (,%r13,8), %r12
testq %r13, %r13
pushq $-0x1
popq %rax
cmovsq %rax, %r12
leaq (,%r13,4), %r15
cmovsq %rax, %r15
movq %r12, %rdi
callq 0x2030
movq %rax, 0x38(%rsp)
movq %r15, %rdi
callq 0x2030
movq %rax, %r15
movq %r12, %rdi
callq 0x2030
movq %rax, (%rsp)
movq %r13, 0x30(%rsp)
movq %r13, %rdi
callq 0x2030
movsd 0x60(%rsp), %xmm2
movsd 0x278d(%rip), %xmm0     # 0xcc30
movapd %xmm0, %xmm1
divsd %xmm2, %xmm1
movsd %xmm1, 0x70(%rsp)
movsd 0x20(%rsp), %xmm1
andq $0x0, 0x78(%rsp)
movq %rax, 0x10(%rsp)
divsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movapd 0x2a19(%rip), %xmm0     # 0xcef0
movapd %xmm0, 0xd0(%rsp)
movabsq $0x7ff0000000000000, %rax # imm = 0x7FF0000000000000
movq %rax, 0xe0(%rsp)
cmpl $0x3, %ebx
jne 0xa518
andq $0x0, 0x70(%rsp)
andq $0x0, 0x80(%rsp)
movsd %xmm2, 0xd0(%rsp)
movsd %xmm1, 0xe0(%rsp)
xorl %eax, %eax
movq 0x30(%rsp), %rcx
testl %ecx, %ecx
movl $0x0, %esi
cmovgl %ecx, %esi
xorpd %xmm0, %xmm0
movq 0x10(%rsp), %rdx
cmpq %rax, %rsi
je 0xa559
movq 0x18(%rsp), %rcx
movq 0x8(%rcx), %rcx
movsd (%rcx,%rax,8), %xmm1
ucomisd %xmm0, %xmm1
setbe %cl
negb %cl
orb $0x1, %cl
movb %cl, (%rdx,%rax)
incq %rax
jmp 0xa532
xorl %eax, %eax
movq (%rsp), %rcx
cmpq %rax, %rsi
je 0xa56e
andq $0x0, (%rcx,%rax,8)
incq %rax
jmp 0xa55f
xorl %eax, %eax
testl %r14d, %r14d
cmovlel %eax, %r14d
movq 0x8(%rsp), %rcx
cmpq %rax, %r14
je 0xa58b
andq $0x0, (%rcx,%rax,8)
incq %rax
jmp 0xa57c
movq %rsi, 0x40(%rsp)
movq %r14, 0xc8(%rsp)
xorl %ebx, %ebx
cmpq %rbx, 0x40(%rsp)
je 0xa601
movq 0x10(%rsp), %rax
movsbq (%rax,%rbx), %r14
movsd 0x78(%rsp,%r14,8), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x18(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%rbx,8), %r12
movq %r12, %rdi
callq 0xb4ba
addsd 0x20(%rsp), %xmm0
movq 0x38(%rsp), %rax
movsd %xmm0, (%rax,%rbx,8)
cvtsi2sd %r14d, %xmm0
movq (%rsp), %rax
mulsd (%rax,%rbx,8), %xmm0
movq %r12, %rdi
movq 0x8(%rsp), %rsi
callq 0xb47e
movl %ebx, (%r15,%rbx,4)
incq %rbx
jmp 0xa59a
movsd 0x27cf(%rip), %xmm0     # 0xcdd8
movsd 0x1a1f(%rip), %xmm1     # 0xc030
movapd %xmm1, 0xb0(%rsp)
movapd %xmm0, 0xa0(%rsp)
movq 0x30(%rsp), %rax
movl %eax, %r14d
xorl %ebx, %ebx
movq %r15, 0x50(%rsp)
cmpl $0x12c, %ebx            # imm = 0x12C
je 0xa933
movl %ebx, 0x5c(%rsp)
testl %r14d, %r14d
movl $0x0, %ebx
cmovgl %r14d, %ebx
movl %r14d, %ebp
xorl %r12d, %r12d
cmpq %r12, %rbx
je 0xa67e
callq 0x2090
cltd
idivl %ebp
movslq %edx, %rax
addq %r12, %rax
movl (%r15,%r12,4), %ecx
movl (%r15,%rax,4), %edx
movl %edx, (%r15,%r12,4)
movl %ecx, (%r15,%rax,4)
incq %r12
decl %ebp
jmp 0xa654
xorl %ebx, %ebx
movsd 0x2750(%rip), %xmm3     # 0xcdd8
movsd 0x19a0(%rip), %xmm2     # 0xc030
movl %ebx, %ebx
movapd %xmm2, 0x60(%rsp)
movapd %xmm3, 0x90(%rsp)
cmpl %r14d, %ebx
jge 0xa821
movl (%r15,%rbx,4), %r13d
movslq %r13d, %rbp
movq 0x10(%rsp), %rax
movsbq (%rax,%rbp), %r15
movq 0x18(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%rbp,8), %r12
cvtsi2sd %r15d, %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x8(%rsp), %rdi
movq %r12, %rsi
callq 0xb45a
movsd 0x20(%rsp), %xmm4
mulsd %xmm4, %xmm0
addsd 0x194e(%rip), %xmm0     # 0xc040
movsd 0xd8(%rsp,%r15,8), %xmm2
movq (%rsp), %rax
movsd (%rax,%rbp,8), %xmm1
movsd 0x78(%rsp,%r15,8), %xmm3
mulsd %xmm1, %xmm3
addsd %xmm0, %xmm3
ucomisd 0x191c(%rip), %xmm1     # 0xc038
movslq %r14d, %rax
jne 0xa730
jp 0xa730
ucomisd 0xb0(%rsp), %xmm3
ja 0xa747
jmp 0xa771
ucomisd %xmm2, %xmm1
jne 0xa785
jp 0xa785
movapd 0xa0(%rsp), %xmm0
ucomisd %xmm3, %xmm0
jbe 0xa78f
decl %r14d
movq 0x50(%rsp), %r15
movl -0x4(%r15,%rax,4), %ecx
movl %ecx, (%r15,%rbx,4)
movl %r13d, -0x4(%r15,%rax,4)
movapd 0x60(%rsp), %xmm2
movapd 0x90(%rsp), %xmm3
jmp 0xa6a1
movq (%rsp), %rax
leaq (%rax,%rbp,8), %rax
xorpd %xmm5, %xmm5
ucomisd %xmm3, %xmm5
ja 0xa7a1
jmp 0xa7a5
movq (%rsp), %rax
leaq (%rax,%rbp,8), %rax
jmp 0xa7a1
movq (%rsp), %rax
leaq (%rax,%rbp,8), %rax
xorpd %xmm5, %xmm5
ucomisd %xmm5, %xmm3
jbe 0xa7a5
movapd %xmm3, %xmm5
movapd %xmm5, %xmm0
andpd 0x24bf(%rip), %xmm0     # 0xcc70
ucomisd 0x2497(%rip), %xmm0     # 0xcc50
jbe 0xa7fe
movq 0x38(%rsp), %rcx
divsd (%rcx,%rbp,8), %xmm3
movapd %xmm1, %xmm0
subsd %xmm3, %xmm0
maxsd 0x1863(%rip), %xmm0     # 0xc038
minsd %xmm2, %xmm0
movsd %xmm0, (%rax)
subsd %xmm1, %xmm0
mulsd %xmm4, %xmm0
movq %r12, %rdi
movq 0x8(%rsp), %rsi
movapd %xmm5, 0x20(%rsp)
callq 0xb47e
movapd 0x20(%rsp), %xmm5
movapd 0x90(%rsp), %xmm3
maxsd %xmm5, %xmm3
movapd 0x60(%rsp), %xmm2
minsd %xmm5, %xmm2
incl %ebx
movq 0x50(%rsp), %r15
jmp 0xa690
movl 0x5c(%rsp), %ebx
incl %ebx
movl %ebx, %eax
xorl %edx, %edx
pushq $0xa
popq %rcx
divl %ecx
testl %edx, %edx
jne 0xa851
leaq 0x26fd(%rip), %rdi      # 0xcf38
xorl %eax, %eax
callq 0x52d8
movapd 0x90(%rsp), %xmm3
movapd 0x60(%rsp), %xmm2
movapd %xmm3, %xmm0
andpd 0x2413(%rip), %xmm0     # 0xcc70
movsd 0x48(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jb 0xa8de
movapd %xmm3, %xmm0
subsd %xmm2, %xmm0
movsd 0x48(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jb 0xa8de
movapd %xmm2, %xmm0
andpd 0x23e7(%rip), %xmm0     # 0xcc70
movsd 0x48(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jb 0xa8de
movl %ebx, %ebp
movq 0x30(%rsp), %rbx
cmpl %ebx, %r14d
je 0xa93a
leaq 0x268e(%rip), %rdi      # 0xcf3a
xorl %eax, %eax
callq 0x52d8
movsd 0x1775(%rip), %xmm0     # 0xc030
movaps %xmm0, 0xb0(%rsp)
movsd 0x250d(%rip), %xmm0     # 0xcdd8
movapd %xmm0, 0xa0(%rsp)
movl %ebx, %r14d
movl %ebp, %ebx
jmp 0xa632
movapd %xmm3, %xmm1
cmpnlesd 0x174d(%rip), %xmm1     # 0xc038
andpd %xmm1, %xmm3
movsd 0x1739(%rip), %xmm0     # 0xc030
andnpd %xmm0, %xmm1
orpd %xmm3, %xmm1
movapd %xmm1, 0xb0(%rsp)
xorpd %xmm1, %xmm1
cmpnlesd %xmm2, %xmm1
andpd %xmm1, %xmm2
movsd 0x24bb(%rip), %xmm0     # 0xcdd8
andnpd %xmm0, %xmm1
orpd %xmm2, %xmm1
movapd %xmm1, 0xa0(%rsp)
jmp 0xa632
movl $0x12c, %esi            # imm = 0x12C
jmp 0xa93c
movl %ebp, %esi
leaq 0x25f9(%rip), %rdi      # 0xcf3c
xorl %ebx, %ebx
movl %esi, %ebp
xorl %eax, %eax
callq 0x52d8
xorpd %xmm0, %xmm0
movq 0xc8(%rsp), %r14
movq 0x8(%rsp), %rax
cmpq %rbx, %r14
je 0xa976
movsd (%rax,%rbx,8), %xmm1
mulsd %xmm1, %xmm1
addsd %xmm1, %xmm0
incq %rbx
jmp 0xa95f
xorl %eax, %eax
movsd 0x24c8(%rip), %xmm1     # 0xce48
xorpd %xmm2, %xmm2
xorl %r12d, %r12d
movq 0x40(%rsp), %rdx
cmpq %rax, %rdx
je 0xa9cb
movq (%rsp), %rcx
movsd (%rcx,%rax,8), %xmm3
movq 0x10(%rsp), %rcx
movsbq (%rcx,%rax), %rcx
movsd 0x78(%rsp,%rcx,8), %xmm4
mulsd %xmm3, %xmm4
addsd %xmm1, %xmm4
mulsd %xmm3, %xmm4
addsd %xmm4, %xmm0
xorl %ecx, %ecx
ucomisd %xmm2, %xmm3
seta %cl
addl %ecx, %r12d
incq %rax
jmp 0xa98c
mulsd 0x225d(%rip), %xmm0     # 0xcc30
leaq 0x25b3(%rip), %rdi      # 0xcf8d
movb $0x1, %al
callq 0x52d8
leaq 0x25bc(%rip), %rdi      # 0xcfa4
movl %r12d, %esi
xorl %eax, %eax
callq 0x52d8
movq 0xc0(%rsp), %rax
cmpb $0x1, 0x4c(%rax)
jne 0xaa63
xorl %eax, %eax
movq 0x8(%rsp), %rcx
cmpq %rax, %r14
je 0xaa16
andq $0x0, (%rcx,%rax,8)
incq %rax
jmp 0xaa07
xorl %ebx, %ebx
xorpd %xmm1, %xmm1
cmpq %rbx, 0x40(%rsp)
je 0xaa63
movq (%rsp), %rax
movsd (%rax,%rbx,8), %xmm0
ucomisd %xmm1, %xmm0
jbe 0xaa5e
movq 0x18(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax,%rbx,8), %rdi
movq 0x10(%rsp), %rax
movsbl (%rax,%rbx), %eax
cvtsi2sd %eax, %xmm1
mulsd %xmm1, %xmm0
movq 0x8(%rsp), %rsi
callq 0xb47e
xorpd %xmm1, %xmm1
incq %rbx
jmp 0xaa1c
movq 0x38(%rsp), %rdi
callq 0x21e0
movq (%rsp), %rdi
callq 0x21e0
movq 0x10(%rsp), %rdi
callq 0x21e0
movq %r15, %rdi
callq 0x21e0
movl %ebp, %eax
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq