// File: qmmlib[P]QmmLibrary/linear.cpp
// Function: train
model* train(const problem *prob, const parameter *param)
{
	int i,j;
	int l = prob->l;
	int n = prob->n;
	int w_size = prob->n;
	model *model_ = Malloc(model,1);

	if(prob->bias>=0)
		model_->nr_feature=n-1;
	else
		model_->nr_feature=n;
	model_->param = *param;
	model_->bias = prob->bias;

	if(param->solver_type == L2R_L2LOSS_SVR ||
	   param->solver_type == L2R_L1LOSS_SVR_DUAL ||
	   param->solver_type == L2R_L2LOSS_SVR_DUAL)
	{
		model_->w = Malloc(double, w_size);
		model_->nr_class = 2;
		model_->label = NULL;
		train_one(prob, param, &model_->w[0], 0, 0, model_);
	}
	else
	{
		int nr_class;
		int *label = NULL;
		int *start = NULL;
		int *count = NULL;
		int *perm = Malloc(int,l);

		// group training data of the same class
		group_classes(prob,&nr_class,&label,&start,&count,perm);

		model_->nr_class=nr_class;
		model_->label = Malloc(int,nr_class);
		for(i=0;i<nr_class;i++)
			model_->label[i] = label[i];

		// calculate weighted C
		double *weighted_C = Malloc(double, nr_class);
		for(i=0;i<nr_class;i++)
			weighted_C[i] = param->C;
		for(i=0;i<param->nr_weight;i++)
		{
			for(j=0;j<nr_class;j++)
				if(param->weight_label[i] == label[j])
					break;
			if(j == nr_class)
				fprintf(stderr,"WARNING: class label %d specified in weight is not found\n", param->weight_label[i]);
			else
				weighted_C[j] *= param->weight[i];
		}

		// constructing the subproblem
		feature_node **x = Malloc(feature_node *,l);
		for(i=0;i<l;i++)
			x[i] = prob->x[perm[i]];

		int k;
		problem sub_prob;
		sub_prob.l = l;
		sub_prob.n = n;
		sub_prob.x = Malloc(feature_node *,sub_prob.l);
		sub_prob.y = Malloc(double,sub_prob.l);

		for(k=0; k<sub_prob.l; k++)
			sub_prob.x[k] = x[k];

		// multi-class svm by Crammer and Singer
		if(param->solver_type == MCSVM_CS)
		{
			model_->w=Malloc(double, n*nr_class);
			for(i=0;i<nr_class;i++)
				for(j=start[i];j<start[i]+count[i];j++)
					sub_prob.y[j] = i;
			Solver_MCSVM_CS Solver(&sub_prob, nr_class, weighted_C, param->eps);
			Solver.Solve(model_->w);
		}
		else if(param->solver_type == MMCD_SM)
		{
			model_->w=Malloc(double, n*nr_class);
			for(i=0;i<nr_class;i++)
				for(j=start[i];j<start[i]+count[i];j++)
					sub_prob.y[j] = i;

			problem prob_col;
			feature_node *x_space = NULL;
			transpose(&sub_prob, &x_space ,&prob_col);
		
			solve_mmcd_sm(&prob_col, param,model_->w, weighted_C[0],start,count,nr_class);
			
			//delete [] prob_col.y;
			//delete [] prob_col.x;
			//delete [] x_space;
		}
		else
		{
			if(nr_class == 2)
			{
				model_->w=Malloc(double, w_size);

				int e0 = start[0]+count[0];
				k=0;
				for(; k<e0; k++)
					sub_prob.y[k] = +1;
				for(; k<sub_prob.l; k++)
					sub_prob.y[k] = -1;

				train_one(&sub_prob, param, &model_->w[0], weighted_C[0], weighted_C[1],model_);
			}
			else
			{
				model_->w=Malloc(double, w_size*nr_class);
				double *w=Malloc(double, w_size);
				for(i=0;i<nr_class;i++)
				{
					int si = start[i];
					int ei = si+count[i];

					k=0;
					for(; k<si; k++)
						sub_prob.y[k] = -1;
					for(; k<ei; k++)
						sub_prob.y[k] = +1;
					for(; k<sub_prob.l; k++)
						sub_prob.y[k] = -1;

					train_one(&sub_prob, param, w, weighted_C[i], param->C,model_);

					for(int j=0;j<w_size;j++)
						model_->w[j*nr_class+i] = w[j];
				}
				free(w);
			}

		}

		free(x);
		free(label);
		free(start);
		free(count);
		free(perm);
		free(sub_prob.x);
		free(sub_prob.y);
		free(weighted_C);
	}
	return model_;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x24(%rbp)
movl $0xd0, %edi
callq 0x33d0
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rax
movsd 0x18(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0xa1a2
movl -0x20(%rbp), %ecx
subl $0x1, %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0xb4(%rax)
jmp 0xa1af
movl -0x20(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0xb4(%rax)
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdi
movl $0xb0, %edx
callq 0x3230
movq -0x8(%rbp), %rax
movsd 0x18(%rax), %xmm0
movq -0x30(%rbp), %rax
movsd %xmm0, 0xc8(%rax)
movq -0x10(%rbp), %rax
cmpl $0xb, (%rax)
je 0xa1f1
movq -0x10(%rbp), %rax
cmpl $0xd, (%rax)
je 0xa1f1
movq -0x10(%rbp), %rax
cmpl $0xc, (%rax)
jne 0xa250
movslq -0x24(%rbp), %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xb8(%rax)
movq -0x30(%rbp), %rax
movl $0x2, 0xb0(%rax)
movq -0x30(%rbp), %rax
movq $0x0, 0xc0(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
movq 0xb8(%rax), %rdx
movq -0x30(%rbp), %rcx
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0xa9b0
jmp 0xa98c
movq $0x0, -0x40(%rbp)
movq $0x0, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
movslq -0x1c(%rbp), %rdi
shlq $0x2, %rdi
callq 0x33d0
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %r9
leaq -0x34(%rbp), %rsi
leaq -0x40(%rbp), %rdx
leaq -0x48(%rbp), %rcx
leaq -0x50(%rbp), %r8
callq 0xb4c0
movl -0x34(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0xb0(%rax)
movslq -0x34(%rbp), %rdi
shlq $0x2, %rdi
callq 0x33d0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xc0(%rax)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xa2f5
movq -0x40(%rbp), %rax
movslq -0x14(%rbp), %rcx
movl (%rax,%rcx,4), %edx
movq -0x30(%rbp), %rax
movq 0xc0(%rax), %rax
movslq -0x14(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa2c5
movslq -0x34(%rbp), %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, -0x60(%rbp)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xa339
movq -0x10(%rbp), %rax
movsd 0x88(%rax), %xmm0
movq -0x60(%rbp), %rax
movslq -0x14(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa30d
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x90(%rcx), %eax
jge 0xa3fa
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xa390
movq -0x10(%rbp), %rax
movq 0x98(%rax), %rax
movslq -0x14(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movq -0x40(%rbp), %rcx
movslq -0x18(%rbp), %rdx
cmpl (%rcx,%rdx,4), %eax
jne 0xa383
jmp 0xa390
jmp 0xa385
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xa35a
movl -0x18(%rbp), %eax
cmpl -0x34(%rbp), %eax
jne 0xa3c4
movq 0x20c39(%rip), %rax     # 0x2afd8
movq (%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x98(%rax), %rax
movslq -0x14(%rbp), %rcx
movl (%rax,%rcx,4), %edx
leaq 0x1b107(%rip), %rsi     # 0x254c2
movb $0x0, %al
callq 0x3400
jmp 0xa3ea
movq -0x10(%rbp), %rax
movq 0xa0(%rax), %rax
movslq -0x14(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x60(%rbp), %rax
movslq -0x18(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
jmp 0xa3ec
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa340
movslq -0x1c(%rbp), %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, -0x68(%rbp)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0xa449
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x58(%rbp), %rcx
movslq -0x14(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x68(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa412
movl -0x1c(%rbp), %eax
movl %eax, -0x90(%rbp)
movl -0x20(%rbp), %eax
movl %eax, -0x8c(%rbp)
movslq -0x90(%rbp), %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, -0x80(%rbp)
movslq -0x90(%rbp), %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, -0x88(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x90(%rbp), %eax
jge 0xa4bb
movq -0x68(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x80(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0xa48d
movq -0x10(%rbp), %rax
cmpl $0x4, (%rax)
jne 0xa5d0
movl -0x20(%rbp), %eax
imull -0x34(%rbp), %eax
movslq %eax, %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xb8(%rax)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xa550
movq -0x48(%rbp), %rax
movslq -0x14(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x48(%rbp), %rcx
movslq -0x14(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movq -0x50(%rbp), %rdx
movslq -0x14(%rbp), %rsi
addl (%rdx,%rsi,4), %ecx
cmpl %ecx, %eax
jge 0xa543
cvtsi2sdl -0x14(%rbp), %xmm0
movq -0x88(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xa506
jmp 0xa545
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa4f0
movl -0x34(%rbp), %edx
movq -0x60(%rbp), %rcx
movq -0x10(%rbp), %rax
movsd 0x80(%rax), %xmm0
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x128(%rbp)
leaq -0x90(%rbp), %rsi
movl $0x186a0, %r8d          # imm = 0x186A0
callq 0x7ef0
movq -0x128(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0xb8(%rax), %rsi
callq 0x8380
jmp 0xa59c
leaq -0xc8(%rbp), %rdi
callq 0x7fc0
jmp 0xa941
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x7fc0
jmp 0xa999
movq -0x10(%rbp), %rax
cmpl $0x33, (%rax)
jne 0xa6be
movl -0x20(%rbp), %eax
imull -0x34(%rbp), %eax
movslq %eax, %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xb8(%rax)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xa665
movq -0x48(%rbp), %rax
movslq -0x14(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x48(%rbp), %rcx
movslq -0x14(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movq -0x50(%rbp), %rdx
movslq -0x14(%rbp), %rsi
addl (%rdx,%rsi,4), %ecx
cmpl %ecx, %eax
jge 0xa658
cvtsi2sdl -0x14(%rbp), %xmm0
movq -0x88(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xa61b
jmp 0xa65a
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa605
movq $0x0, -0x100(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x100(%rbp), %rsi
leaq -0xf8(%rbp), %rdx
callq 0xb750
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
movq 0xb8(%rax), %rdx
movq -0x60(%rbp), %rax
movsd (%rax), %xmm0
movq -0x48(%rbp), %rcx
movq -0x50(%rbp), %r8
movl -0x34(%rbp), %r9d
leaq -0xf8(%rbp), %rdi
callq 0xbab0
jmp 0xa93f
cmpl $0x2, -0x34(%rbp)
jne 0xa78f
movslq -0x24(%rbp), %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xb8(%rax)
movq -0x48(%rbp), %rax
movl (%rax), %eax
movq -0x50(%rbp), %rcx
addl (%rcx), %eax
movl %eax, -0x104(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x104(%rbp), %eax
jge 0xa72a
movq -0x88(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movsd 0x1990e(%rip), %xmm0    # 0x24028
movsd %xmm0, (%rax,%rcx,8)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0xa6fc
jmp 0xa72c
movl -0x6c(%rbp), %eax
cmpl -0x90(%rbp), %eax
jge 0xa75a
movq -0x88(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movsd 0x198e6(%rip), %xmm0    # 0x24030
movsd %xmm0, (%rax,%rcx,8)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0xa72c
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
movq 0xb8(%rax), %rdx
movq -0x60(%rbp), %rax
movsd (%rax), %xmm0
movq -0x60(%rbp), %rax
movsd 0x8(%rax), %xmm1
movq -0x30(%rbp), %rcx
leaq -0x90(%rbp), %rdi
callq 0xa9b0
jmp 0xa93d
movl -0x24(%rbp), %eax
imull -0x34(%rbp), %eax
movslq %eax, %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xb8(%rax)
movslq -0x24(%rbp), %rdi
shlq $0x3, %rdi
callq 0x33d0
movq %rax, -0x110(%rbp)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xa931
movq -0x48(%rbp), %rax
movslq -0x14(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x114(%rbp)
movl -0x114(%rbp), %eax
movq -0x50(%rbp), %rcx
movslq -0x14(%rbp), %rdx
addl (%rcx,%rdx,4), %eax
movl %eax, -0x118(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x114(%rbp), %eax
jge 0xa834
movq -0x88(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movsd 0x1980c(%rip), %xmm0    # 0x24030
movsd %xmm0, (%rax,%rcx,8)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0xa806
jmp 0xa836
movl -0x6c(%rbp), %eax
cmpl -0x118(%rbp), %eax
jge 0xa864
movq -0x88(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movsd 0x197d4(%rip), %xmm0    # 0x24028
movsd %xmm0, (%rax,%rcx,8)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0xa836
jmp 0xa866
movl -0x6c(%rbp), %eax
cmpl -0x90(%rbp), %eax
jge 0xa894
movq -0x88(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movsd 0x197ac(%rip), %xmm0    # 0x24030
movsd %xmm0, (%rax,%rcx,8)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0xa866
movq -0x10(%rbp), %rsi
movq -0x110(%rbp), %rdx
movq -0x60(%rbp), %rax
movslq -0x14(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movsd 0x88(%rax), %xmm1
movq -0x30(%rbp), %rcx
leaq -0x90(%rbp), %rdi
callq 0xa9b0
movl $0x0, -0x11c(%rbp)
movl -0x11c(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0xa921
movq -0x110(%rbp), %rax
movslq -0x11c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x30(%rbp), %rax
movq 0xb8(%rax), %rax
movl -0x11c(%rbp), %ecx
imull -0x34(%rbp), %ecx
addl -0x14(%rbp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x11c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x11c(%rbp)
jmp 0xa8d2
jmp 0xa923
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa7cb
movq -0x110(%rbp), %rdi
callq 0x3370
jmp 0xa93f
jmp 0xa941
movq -0x68(%rbp), %rdi
callq 0x3370
movq -0x40(%rbp), %rdi
callq 0x3370
movq -0x48(%rbp), %rdi
callq 0x3370
movq -0x50(%rbp), %rdi
callq 0x3370
movq -0x58(%rbp), %rdi
callq 0x3370
movq -0x80(%rbp), %rdi
callq 0x3370
movq -0x88(%rbp), %rdi
callq 0x3370
movq -0x60(%rbp), %rdi
callq 0x3370
movq -0x30(%rbp), %rax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
movq -0xd0(%rbp), %rdi
callq 0x34b0
nopw %cs:(%rax,%rax)