// File: /workspace/github_cpp_makefile_star2_O2/qmmlib[P]QmmLibrary/linear.cpp
// Function: solve_l2r_l1l2_svc(problem const*, double*, double, double, double, int)
static void solve_l2r_l1l2_svc(
	const problem *prob, double *w, double eps, 
	double Cp, double Cn, int solver_type)
{
	int l = prob->l;
	int w_size = prob->n;
	int i, s, iter = 0;
	double C, d, G;
	double *QD = new double[l];
	int max_iter = 1000;
	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 *xi = prob->x[i];
		while (xi->index != -1)
		{
			double val = xi->value;
			QD[i] += val*val;
			w[xi->index-1] += y[i]*alpha[i]*val;
			xi++;
		}
		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];
			G = 0;
			schar yi = y[i];

			feature_node *xi = prob->x[i];
			while(xi->index!= -1)
			{
				G += w[xi->index-1]*(xi->value);
				xi++;
			}
			G = G*yi-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;
				xi = prob->x[i];
				while (xi->index != -1)
				{
					w[xi->index-1] += d*xi->value;
					xi++;
				}
			}
		}

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

		if(PGmax_new - 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);
	if (iter >= max_iter)
		info("\nWARNING: reaching max number of iterations\nUsing -s 2 may be faster (also see FAQ)\n\n");

	// 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);

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

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movl %edx, 0x20(%rsp)
movsd %xmm2, 0x8(%rsp)
movsd %xmm1, 0x10(%rsp)
movsd %xmm0, 0x78(%rsp)
movq %rsi, %r13
movq %rdi, %rbp
movslq (%rdi), %r14
movl 0x4(%rdi), %eax
movq %rax, 0x38(%rsp)
leaq (,%r14,8), %r15
testq %r14, %r14
pushq $-0x1
popq %rax
cmovsq %rax, %r15
leaq (,%r14,4), %rbx
cmovsq %rax, %rbx
movq %r15, %rdi
callq 0x3030
movq %rax, %r12
movq %rbx, %rdi
callq 0x3030
movq %rax, %rbx
movq %r15, %rdi
callq 0x3030
movq %rax, %r15
movq %r14, 0x40(%rsp)
movq %r14, %rdi
callq 0x3030
movsd 0x8(%rsp), %xmm2
movsd 0x3d63(%rip), %xmm0     # 0x16100
movapd %xmm0, %xmm1
divsd %xmm2, %xmm1
movsd %xmm1, 0x50(%rsp)
movsd 0x10(%rsp), %xmm1
andq $0x0, 0x58(%rsp)
divsd %xmm1, %xmm0
movsd %xmm0, 0x60(%rsp)
movapd 0x40d7(%rip), %xmm0     # 0x164a0
movapd %xmm0, 0x90(%rsp)
movabsq $0x7ff0000000000000, %rcx # imm = 0x7FF0000000000000
movq %rcx, 0xa0(%rsp)
cmpl $0x3, 0x20(%rsp)
jne 0x12409
andq $0x0, 0x50(%rsp)
andq $0x0, 0x60(%rsp)
movsd %xmm2, 0x90(%rsp)
movsd %xmm1, 0xa0(%rsp)
xorl %edx, %edx
movq 0x40(%rsp), %rcx
testl %ecx, %ecx
movl $0x0, %edi
cmovgl %ecx, %edi
xorpd %xmm0, %xmm0
cmpq %rdx, %rdi
je 0x12440
movq 0x8(%rbp), %rcx
movsd (%rcx,%rdx,8), %xmm1
ucomisd %xmm0, %xmm1
setbe %cl
negb %cl
orb $0x1, %cl
movb %cl, (%rax,%rdx)
incq %rdx
jmp 0x1241e
xorl %ecx, %ecx
movq 0x38(%rsp), %r14
cmpq %rcx, %rdi
je 0x12456
andq $0x0, (%r15,%rcx,8)
incq %rcx
jmp 0x12447
xorl %ecx, %ecx
testl %r14d, %r14d
cmovlel %ecx, %r14d
cmpq %rcx, %r14
je 0x1246f
andq $0x0, (%r13,%rcx,8)
incq %rcx
jmp 0x1245f
movq %r14, 0x38(%rsp)
xorl %esi, %esi
movq 0x40(%rsp), %r8
cmpq %rdi, %rsi
je 0x124e3
movsbq (%rax,%rsi), %rdx
movsd 0x58(%rsp,%rdx,8), %xmm0
movsd %xmm0, (%r12,%rsi,8)
movq 0x10(%rbp), %rcx
movq (%rcx,%rsi,8), %rcx
cvtsi2sd %edx, %xmm1
movslq (%rcx), %rdx
cmpq $-0x1, %rdx
je 0x124db
movsd 0x8(%rcx), %xmm2
movsd (%r15,%rsi,8), %xmm3
mulsd %xmm1, %xmm3
mulsd %xmm2, %xmm3
mulsd %xmm2, %xmm2
addsd %xmm2, %xmm0
movsd %xmm0, (%r12,%rsi,8)
addsd -0x8(%r13,%rdx,8), %xmm3
movsd %xmm3, -0x8(%r13,%rdx,8)
addq $0x10, %rcx
jmp 0x1249d
movl %esi, (%rbx,%rsi,4)
incq %rsi
jmp 0x1247b
movsd 0x3dc5(%rip), %xmm0     # 0x162b0
movsd 0x2b3d(%rip), %xmm1     # 0x15030
movl %r8d, %r14d
movapd %xmm1, 0x20(%rsp)
movapd %xmm0, 0x10(%rsp)
xorl %esi, %esi
movq %rax, 0x48(%rsp)
movq %rdi, 0x68(%rsp)
movq %r12, 0x88(%rsp)
movq %r15, 0x80(%rsp)
movq %rbp, 0x70(%rsp)
cmpl $0x3e8, %esi            # imm = 0x3E8
je 0x127d1
movl %esi, 0x8(%rsp)
testl %r14d, %r14d
movl $0x0, %ebp
cmovgl %r14d, %ebp
movl %r14d, %r12d
xorl %r15d, %r15d
cmpq %r15, %rbp
je 0x1256f
callq 0x30a0
cltd
idivl %r12d
movslq %edx, %rax
addq %r15, %rax
movl (%rbx,%r15,4), %ecx
movl (%rbx,%rax,4), %edx
movl %edx, (%rbx,%r15,4)
movl %ecx, (%rbx,%rax,4)
incq %r15
decl %r12d
jmp 0x12545
xorl %eax, %eax
movsd 0x3d37(%rip), %xmm7     # 0x162b0
movsd 0x2aaf(%rip), %xmm6     # 0x15030
movq 0x88(%rsp), %r12
movq 0x80(%rsp), %r15
movq 0x48(%rsp), %r11
movq 0x70(%rsp), %rbp
cmpl %r14d, %eax
jge 0x126ea
movslq %eax, %rdi
movl (%rbx,%rdi,4), %esi
movslq %esi, %rdx
movsbq (%r11,%rdx), %r8
movq 0x10(%rbp), %rcx
movq (%rcx,%rdx,8), %rcx
xorpd %xmm2, %xmm2
movq %rcx, %r9
movslq (%r9), %r10
cmpq $-0x1, %r10
je 0x125e1
movsd -0x8(%r13,%r10,8), %xmm0
mulsd 0x8(%r9), %xmm0
addsd %xmm0, %xmm2
addq $0x10, %r9
jmp 0x125c1
cvtsi2sd %r8d, %xmm0
mulsd %xmm0, %xmm2
addsd 0x3cae(%rip), %xmm2     # 0x162a0
movsd 0x98(%rsp,%r8,8), %xmm3
movsd (%r15,%rdx,8), %xmm1
movsd 0x58(%rsp,%r8,8), %xmm4
mulsd %xmm1, %xmm4
addsd %xmm2, %xmm4
ucomisd 0x2a27(%rip), %xmm1     # 0x15040
movslq %r14d, %r8
jne 0x12638
jp 0x12638
ucomisd 0x20(%rsp), %xmm4
ja 0x126d5
xorpd %xmm2, %xmm2
ucomisd %xmm4, %xmm2
ja 0x1265e
jmp 0x12662
ucomisd %xmm3, %xmm1
movapd %xmm4, %xmm2
jne 0x12662
jp 0x12662
movapd 0x10(%rsp), %xmm2
ucomisd %xmm4, %xmm2
ja 0x126d5
xorpd %xmm2, %xmm2
ucomisd %xmm2, %xmm4
jbe 0x12662
movapd %xmm4, %xmm2
movapd %xmm2, %xmm5
andpd 0x3ab2(%rip), %xmm5     # 0x16120
ucomisd 0x3a9a(%rip), %xmm5     # 0x16110
jbe 0x126c6
divsd (%r12,%rdx,8), %xmm4
movapd %xmm1, %xmm5
subsd %xmm4, %xmm5
maxsd 0x29b2(%rip), %xmm5     # 0x15040
minsd %xmm3, %xmm5
movsd %xmm5, (%r15,%rdx,8)
subsd %xmm1, %xmm5
mulsd %xmm0, %xmm5
movslq (%rcx), %rdx
cmpq $-0x1, %rdx
je 0x126c6
movsd 0x8(%rcx), %xmm0
mulsd %xmm5, %xmm0
addsd -0x8(%r13,%rdx,8), %xmm0
movsd %xmm0, -0x8(%r13,%rdx,8)
addq $0x10, %rcx
jmp 0x126a0
maxsd %xmm2, %xmm7
minsd %xmm2, %xmm6
incl %eax
jmp 0x1259b
decl %r14d
movl -0x4(%rbx,%r8,4), %ecx
movl %ecx, (%rbx,%rdi,4)
movl %esi, -0x4(%rbx,%r8,4)
jmp 0x1259b
movl 0x8(%rsp), %esi
incl %esi
movl %esi, %eax
xorl %edx, %edx
pushq $0xa
popq %rcx
divl %ecx
testl %edx, %edx
jne 0x1272b
leaq 0x428a(%rip), %rdi      # 0x1698e
xorl %eax, %eax
movl %esi, 0x8(%rsp)
movapd %xmm6, 0x20(%rsp)
movapd %xmm7, 0x10(%rsp)
callq 0x6a9e
movapd 0x10(%rsp), %xmm7
movapd 0x20(%rsp), %xmm6
movl 0x8(%rsp), %esi
movapd %xmm7, %xmm0
subsd %xmm6, %xmm0
movsd 0x78(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jae 0x1278e
movapd %xmm7, %xmm1
cmpnlesd 0x28f4(%rip), %xmm1     # 0x15040
andpd %xmm1, %xmm7
movsd 0x28d8(%rip), %xmm0     # 0x15030
andnpd %xmm0, %xmm1
orpd %xmm7, %xmm1
movapd %xmm1, 0x20(%rsp)
xorpd %xmm1, %xmm1
cmpnlesd %xmm6, %xmm1
andpd %xmm1, %xmm6
movsd 0x3b35(%rip), %xmm0     # 0x162b0
andnpd %xmm0, %xmm1
orpd %xmm6, %xmm1
movapd %xmm1, 0x10(%rsp)
jmp 0x12523
movq 0x40(%rsp), %rax
cmpl %eax, %r14d
je 0x127d6
movq %rax, %r14
leaq 0x3d16(%rip), %rdi      # 0x164b8
xorl %eax, %eax
movl %esi, 0x8(%rsp)
callq 0x6a9e
movl 0x8(%rsp), %esi
movsd 0x2877(%rip), %xmm0     # 0x15030
movaps %xmm0, 0x20(%rsp)
movsd 0x3aea(%rip), %xmm0     # 0x162b0
movapd %xmm0, 0x10(%rsp)
jmp 0x12523
movl $0x3e8, %esi            # imm = 0x3E8
leaq 0x3cdd(%rip), %rdi      # 0x164ba
xorl %eax, %eax
movl %esi, %ebp
callq 0x6a9e
cmpl $0x3e8, %ebp            # imm = 0x3E8
jl 0x127fc
leaq 0x3ec6(%rip), %rdi      # 0x166bb
xorl %eax, %eax
callq 0x6a9e
xorpd %xmm0, %xmm0
xorl %eax, %eax
movq 0x48(%rsp), %r14
movq 0x38(%rsp), %rcx
movq 0x68(%rsp), %rdx
cmpq %rax, %rcx
je 0x1282a
movsd (%r13,%rax,8), %xmm1
mulsd %xmm1, %xmm1
addsd %xmm1, %xmm0
incq %rax
jmp 0x12811
xorl %eax, %eax
movsd 0x3a94(%rip), %xmm1     # 0x162c8
xorpd %xmm2, %xmm2
xorl %ebp, %ebp
cmpq %rax, %rdx
je 0x12870
movsd (%r15,%rax,8), %xmm3
movsbq (%r14,%rax), %rcx
movsd 0x58(%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, %ebp
incq %rax
jmp 0x1283a
mulsd 0x3888(%rip), %xmm0     # 0x16100
leaq 0x3c8c(%rip), %rdi      # 0x1650b
movb $0x1, %al
callq 0x6a9e
leaq 0x3c95(%rip), %rdi      # 0x16522
movl %ebp, %esi
xorl %eax, %eax
callq 0x6a9e
movq %r12, %rdi
callq 0x32f0
movq %r15, %rdi
callq 0x32f0
movq %r14, %rdi
callq 0x32f0
movq %rbx, %rdi
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32f0