// File: cjlin1[P]liblinear/linear.cpp
// Function: train_one(problem const*, parameter const*, double*, double, double)
static void train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn)
{
	int solver_type = param->solver_type;
	int dual_solver_max_iter = 300;
	int iter;

	bool is_regression = (solver_type==L2R_L2LOSS_SVR ||
				solver_type==L2R_L1LOSS_SVR_DUAL ||
				solver_type==L2R_L2LOSS_SVR_DUAL);

	// Some solvers use Cp,Cn but not C array; extensions possible but no plan for now
	double *C = new double[prob->l];
	double primal_solver_tol = param->eps;
	if(is_regression)
	{
		for(int i=0;i<prob->l;i++)
			C[i] = param->C;
	}
	else
	{
		int pos = 0;
		for(int i=0;i<prob->l;i++)
		{
			if(prob->y[i] > 0)
			{
				pos++;
				C[i] = Cp;
			}
			else
				C[i] = Cn;
		}
		int neg = prob->l - pos;
		primal_solver_tol = param->eps*max(min(pos,neg), 1)/prob->l;
	}

	switch(solver_type)
	{
		case L2R_LR:
		{
			l2r_lr_fun fun_obj(prob, param, C);
			NEWTON newton_obj(&fun_obj, primal_solver_tol);
			newton_obj.set_print_string(liblinear_print_string);
			newton_obj.newton(w);
			break;
		}
		case L2R_L2LOSS_SVC:
		{
			l2r_l2_svc_fun fun_obj(prob, param, C);
			NEWTON newton_obj(&fun_obj, primal_solver_tol);
			newton_obj.set_print_string(liblinear_print_string);
			newton_obj.newton(w);
			break;
		}
		case L2R_L2LOSS_SVC_DUAL:
		{
			iter = solve_l2r_l1l2_svc(prob, param, w, Cp, Cn, dual_solver_max_iter);
			if(iter >= dual_solver_max_iter)
			{
				info("\nWARNING: reaching max number of iterations\nSwitching to use -s 2\n\n");
				// primal_solver_tol obtained from eps for dual may be too loose
				primal_solver_tol *= 0.1;
				l2r_l2_svc_fun fun_obj(prob, param, C);
				NEWTON newton_obj(&fun_obj, primal_solver_tol);
				newton_obj.set_print_string(liblinear_print_string);
				newton_obj.newton(w);
			}
			break;
		}
		case L2R_L1LOSS_SVC_DUAL:
		{
			iter = solve_l2r_l1l2_svc(prob, param, w, Cp, Cn, dual_solver_max_iter);
			if(iter >= dual_solver_max_iter)
				info("\nWARNING: reaching max number of iterations\nUsing -s 2 may be faster (also see FAQ)\n\n");			
			break;
		}
		case L1R_L2LOSS_SVC:
		{
			problem prob_col;
			feature_node *x_space = NULL;
			transpose(prob, &x_space ,&prob_col);
			solve_l1r_l2_svc(&prob_col, param, w, Cp, Cn, primal_solver_tol);
			delete [] prob_col.y;
			delete [] prob_col.x;
			delete [] x_space;
			break;
		}
		case L1R_LR:
		{
			problem prob_col;
			feature_node *x_space = NULL;
			transpose(prob, &x_space ,&prob_col);
			solve_l1r_lr(&prob_col, param, w, Cp, Cn, primal_solver_tol);
			delete [] prob_col.y;
			delete [] prob_col.x;
			delete [] x_space;
			break;
		}
		case L2R_LR_DUAL:
		{
			iter = solve_l2r_lr_dual(prob, param, w, Cp, Cn, dual_solver_max_iter);
			if(iter >= dual_solver_max_iter)
			{
				info("\nWARNING: reaching max number of iterations\nSwitching to use -s 0\n\n");
				// primal_solver_tol obtained from eps for dual may be too loose
				primal_solver_tol *= 0.1;
				l2r_lr_fun fun_obj(prob, param, C);
				NEWTON newton_obj(&fun_obj, primal_solver_tol);
				newton_obj.set_print_string(liblinear_print_string);
				newton_obj.newton(w);
			}
			break;
		}
		case L2R_L2LOSS_SVR:
		{
			l2r_l2_svr_fun fun_obj(prob, param, C);
			NEWTON newton_obj(&fun_obj, primal_solver_tol);
			newton_obj.set_print_string(liblinear_print_string);
			newton_obj.newton(w);
			break;
		}
		case L2R_L1LOSS_SVR_DUAL:
		{
			iter = solve_l2r_l1l2_svr(prob, param, w, dual_solver_max_iter);
			if(iter >= dual_solver_max_iter)
				info("\nWARNING: reaching max number of iterations\nUsing -s 11 may be faster (also see FAQ)\n\n");			

			break;
		}
		case L2R_L2LOSS_SVR_DUAL:
		{
			iter = solve_l2r_l1l2_svr(prob, param, w, dual_solver_max_iter);
			if(iter >= dual_solver_max_iter)
			{
				info("\nWARNING: reaching max number of iterations\nSwitching to use -s 11\n\n");
				// primal_solver_tol obtained from eps for dual may be too loose
				primal_solver_tol *= 0.001;
				l2r_l2_svr_fun fun_obj(prob, param, C);
				NEWTON newton_obj(&fun_obj, primal_solver_tol);
				newton_obj.set_print_string(liblinear_print_string);
				newton_obj.newton(w);
			}
			break;
		}
		default:
			fprintf(stderr, "ERROR: unknown solver_type\n");
			break;
	}

	delete[] C;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3e0, %rsp            # imm = 0x3E0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movsd %xmm0, -0x20(%rbp)
movsd %xmm1, -0x28(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
movl $0x12c, -0x30(%rbp)     # imm = 0x12C
movb $0x1, %al
cmpl $0xb, -0x2c(%rbp)
movb %al, -0x359(%rbp)
je 0x7b7a
movb $0x1, %al
cmpl $0xd, -0x2c(%rbp)
movb %al, -0x359(%rbp)
je 0x7b7a
cmpl $0xc, -0x2c(%rbp)
sete %al
movb %al, -0x359(%rbp)
movb -0x359(%rbp), %al
andb $0x1, %al
movb %al, -0x35(%rbp)
movq -0x8(%rbp), %rax
movslq (%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x48(%rbp)
testb $0x1, -0x35(%rbp)
je 0x7bfd
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl (%rcx), %eax
jge 0x7bf8
movq -0x10(%rbp), %rax
movsd 0x10(%rax), %xmm0
movq -0x40(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x7bcc
jmp 0x7cc1
movl $0x0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movl -0x54(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl (%rcx), %eax
jge 0x7c6c
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x54(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x7c4d
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
movsd -0x20(%rbp), %xmm0
movq -0x40(%rbp), %rax
movslq -0x54(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
jmp 0x7c5f
movsd -0x28(%rbp), %xmm0
movq -0x40(%rbp), %rax
movslq -0x54(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
jmp 0x7c61
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x7c0b
movq -0x8(%rbp), %rax
movl (%rax), %eax
subl -0x50(%rbp), %eax
movl %eax, -0x58(%rbp)
movq -0x10(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x368(%rbp)
movl -0x50(%rbp), %edi
movl -0x58(%rbp), %esi
callq 0xac40
movl %eax, %edi
movl $0x1, %esi
callq 0xc1a0
movsd -0x368(%rbp), %xmm0
cvtsi2sd %eax, %xmm1
mulsd %xmm1, %xmm0
movq -0x8(%rbp), %rax
cvtsi2sdl (%rax), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movl -0x2c(%rbp), %eax
movq %rax, -0x370(%rbp)
subq $0xd, %rax
ja 0x8465
movq -0x370(%rbp), %rax
leaq 0xb16d(%rip), %rcx      # 0x12e50
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x40(%rbp), %rcx
leaq -0x98(%rbp), %rdi
movq %rdi, -0x378(%rbp)
callq 0x4ac0
movq -0x378(%rbp), %rsi
movsd -0x48(%rbp), %xmm0
leaq -0xc0(%rbp), %rdi
movsd 0xa2f2(%rip), %xmm1     # 0x12018
movl $0x3e8, %edx            # imm = 0x3E8
callq 0x3740
jmp 0x7d32
movq 0xe4ff(%rip), %rsi      # 0x16238
leaq -0xc0(%rbp), %rdi
callq 0x4270
jmp 0x7d47
movq -0x18(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
callq 0x37e0
jmp 0x7d59
leaq -0xc0(%rbp), %rdi
callq 0x37d0
leaq -0x98(%rbp), %rdi
callq 0x4b60
jmp 0x847d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
jmp 0x7da8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x37d0
leaq -0x98(%rbp), %rdi
callq 0x4b60
jmp 0x84a3
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x40(%rbp), %rcx
leaq -0x118(%rbp), %rdi
movq %rdi, -0x380(%rbp)
callq 0x5160
movq -0x380(%rbp), %rsi
movsd -0x48(%rbp), %xmm0
leaq -0x140(%rbp), %rdi
movsd 0xa225(%rip), %xmm1     # 0x12018
movl $0x3e8, %edx            # imm = 0x3E8
callq 0x3740
jmp 0x7dff
movq 0xe432(%rip), %rsi      # 0x16238
leaq -0x140(%rbp), %rdi
callq 0x4270
jmp 0x7e14
movq -0x18(%rbp), %rsi
leaq -0x140(%rbp), %rdi
callq 0x37e0
jmp 0x7e26
leaq -0x140(%rbp), %rdi
callq 0x37d0
leaq -0x118(%rbp), %rdi
callq 0x5200
jmp 0x847d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
jmp 0x7e75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x37d0
leaq -0x118(%rbp), %rdi
callq 0x5200
jmp 0x84a3
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movsd -0x20(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
movl -0x30(%rbp), %ecx
callq 0xc1d0
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x30(%rbp), %eax
jl 0x7fa1
leaq 0xb473(%rip), %rdi      # 0x1332d
xorl %eax, %eax
callq 0x7120
movsd -0x48(%rbp), %xmm0
movsd 0xa152(%rip), %xmm1     # 0x12020
mulsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x40(%rbp), %rcx
leaq -0x188(%rbp), %rdi
movq %rdi, -0x388(%rbp)
callq 0x5160
movq -0x388(%rbp), %rsi
movsd -0x48(%rbp), %xmm0
leaq -0x1b0(%rbp), %rdi
movsd 0xa107(%rip), %xmm1     # 0x12018
movl $0x3e8, %edx            # imm = 0x3E8
callq 0x3740
jmp 0x7f1d
movq 0xe314(%rip), %rsi      # 0x16238
leaq -0x1b0(%rbp), %rdi
callq 0x4270
jmp 0x7f32
movq -0x18(%rbp), %rsi
leaq -0x1b0(%rbp), %rdi
callq 0x37e0
jmp 0x7f44
leaq -0x1b0(%rbp), %rdi
callq 0x37d0
leaq -0x188(%rbp), %rdi
callq 0x5200
jmp 0x7fa1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
jmp 0x7f90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x37d0
leaq -0x188(%rbp), %rdi
callq 0x5200
jmp 0x84a3
jmp 0x847d
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movsd -0x20(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
movl -0x30(%rbp), %ecx
callq 0xc1d0
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x30(%rbp), %eax
jl 0x7fdd
leaq 0xb39b(%rip), %rdi      # 0x13371
movb $0x0, %al
callq 0x7120
jmp 0x847d
movq $0x0, -0x1d8(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
leaq -0x1d0(%rbp), %rdx
callq 0xcc50
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movsd -0x20(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
movsd -0x48(%rbp), %xmm2
leaq -0x1d0(%rbp), %rdi
callq 0xcfc0
movq -0x1c8(%rbp), %rax
movq %rax, -0x390(%rbp)
cmpq $0x0, %rax
je 0x8047
movq -0x390(%rbp), %rdi
callq 0x21b0
movq -0x1c0(%rbp), %rax
movq %rax, -0x398(%rbp)
cmpq $0x0, %rax
je 0x8067
movq -0x398(%rbp), %rdi
callq 0x21b0
movq -0x1d8(%rbp), %rax
movq %rax, -0x3a0(%rbp)
cmpq $0x0, %rax
je 0x8087
movq -0x3a0(%rbp), %rdi
callq 0x21b0
jmp 0x847d
movq $0x0, -0x200(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x200(%rbp), %rsi
leaq -0x1f8(%rbp), %rdx
callq 0xcc50
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movsd -0x20(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
movsd -0x48(%rbp), %xmm2
leaq -0x1f8(%rbp), %rdi
callq 0xe1d0
movq -0x1f0(%rbp), %rax
movq %rax, -0x3a8(%rbp)
cmpq $0x0, %rax
je 0x80f1
movq -0x3a8(%rbp), %rdi
callq 0x21b0
movq -0x1e8(%rbp), %rax
movq %rax, -0x3b0(%rbp)
cmpq $0x0, %rax
je 0x8111
movq -0x3b0(%rbp), %rdi
callq 0x21b0
movq -0x200(%rbp), %rax
movq %rax, -0x3b8(%rbp)
cmpq $0x0, %rax
je 0x8131
movq -0x3b8(%rbp), %rdi
callq 0x21b0
jmp 0x847d
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movsd -0x20(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
movl -0x30(%rbp), %ecx
callq 0xfcf0
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x30(%rbp), %eax
jl 0x8251
leaq 0xb25d(%rip), %rdi      # 0x133c7
xorl %eax, %eax
callq 0x7120
movsd -0x48(%rbp), %xmm0
movsd 0x9ea2(%rip), %xmm1     # 0x12020
mulsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x40(%rbp), %rcx
leaq -0x240(%rbp), %rdi
movq %rdi, -0x3c0(%rbp)
callq 0x4ac0
movq -0x3c0(%rbp), %rsi
movsd -0x48(%rbp), %xmm0
leaq -0x268(%rbp), %rdi
movsd 0x9e57(%rip), %xmm1     # 0x12018
movl $0x3e8, %edx            # imm = 0x3E8
callq 0x3740
jmp 0x81cd
movq 0xe064(%rip), %rsi      # 0x16238
leaq -0x268(%rbp), %rdi
callq 0x4270
jmp 0x81e2
movq -0x18(%rbp), %rsi
leaq -0x268(%rbp), %rdi
callq 0x37e0
jmp 0x81f4
leaq -0x268(%rbp), %rdi
callq 0x37d0
leaq -0x240(%rbp), %rdi
callq 0x4b60
jmp 0x8251
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
jmp 0x8240
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
leaq -0x268(%rbp), %rdi
callq 0x37d0
leaq -0x240(%rbp), %rdi
callq 0x4b60
jmp 0x84a3
jmp 0x847d
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x40(%rbp), %rcx
leaq -0x2b8(%rbp), %rdi
movq %rdi, -0x3c8(%rbp)
callq 0x5830
movq -0x3c8(%rbp), %rsi
movsd -0x48(%rbp), %xmm0
leaq -0x2e0(%rbp), %rdi
movsd 0x9d88(%rip), %xmm1     # 0x12018
movl $0x3e8, %edx            # imm = 0x3E8
callq 0x3740
jmp 0x829c
movq 0xdf95(%rip), %rsi      # 0x16238
leaq -0x2e0(%rbp), %rdi
callq 0x4270
jmp 0x82b1
movq -0x18(%rbp), %rsi
leaq -0x2e0(%rbp), %rdi
callq 0x37e0
jmp 0x82c3
leaq -0x2e0(%rbp), %rdi
callq 0x37d0
leaq -0x2b8(%rbp), %rdi
callq 0x115f0
jmp 0x847d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
jmp 0x8312
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
leaq -0x2e0(%rbp), %rdi
callq 0x37d0
leaq -0x2b8(%rbp), %rdi
callq 0x115f0
jmp 0x84a3
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movl -0x30(%rbp), %ecx
callq 0x10790
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x30(%rbp), %eax
jl 0x8350
leaq 0xb0c2(%rip), %rdi      # 0x1340b
movb $0x0, %al
callq 0x7120
jmp 0x847d
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movl -0x30(%rbp), %ecx
callq 0x10790
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x30(%rbp), %eax
jl 0x8463
leaq 0xb0e3(%rip), %rdi      # 0x13462
xorl %eax, %eax
callq 0x7120
movsd -0x48(%rbp), %xmm0
movsd 0xaa75(%rip), %xmm1     # 0x12e08
mulsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x40(%rbp), %rcx
leaq -0x330(%rbp), %rdi
movq %rdi, -0x3d0(%rbp)
callq 0x5830
movq -0x3d0(%rbp), %rsi
movsd -0x48(%rbp), %xmm0
leaq -0x358(%rbp), %rdi
movsd 0x9c42(%rip), %xmm1     # 0x12018
movl $0x3e8, %edx            # imm = 0x3E8
callq 0x3740
jmp 0x83e2
movq 0xde4f(%rip), %rsi      # 0x16238
leaq -0x358(%rbp), %rdi
callq 0x4270
jmp 0x83f7
movq -0x18(%rbp), %rsi
leaq -0x358(%rbp), %rdi
callq 0x37e0
jmp 0x8409
leaq -0x358(%rbp), %rdi
callq 0x37d0
leaq -0x330(%rbp), %rdi
callq 0x115f0
jmp 0x8463
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
jmp 0x8455
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc8(%rbp)
movl %eax, -0xcc(%rbp)
leaq -0x358(%rbp), %rdi
callq 0x37d0
leaq -0x330(%rbp), %rdi
callq 0x115f0
jmp 0x84a3
jmp 0x847d
movq 0xdb74(%rip), %rax      # 0x15fe0
movq (%rax), %rdi
leaq 0xb031(%rip), %rsi      # 0x134a7
movb $0x0, %al
callq 0x21f0
movq -0x40(%rbp), %rax
movq %rax, -0x3d8(%rbp)
cmpq $0x0, %rax
je 0x849a
movq -0x3d8(%rbp), %rdi
callq 0x21b0
addq $0x3e0, %rsp            # imm = 0x3E0
popq %rbp
retq
movq -0xc8(%rbp), %rdi
callq 0x2260
nop