// File: qmmlib[P]QmmLibrary/linear.cpp
// Function: save_model
int save_model(const char *model_file_name, const struct model *model_)
{
	int i;
	int nr_feature=model_->nr_feature;
	int n;
	const parameter& param = model_->param;

	if(model_->bias>=0)
		n=nr_feature+1;
	else
		n=nr_feature;
	int w_size = n;
	FILE *fp = fopen(model_file_name,"w");
	if(fp==NULL) return -1;

	char *old_locale = strdup(setlocale(LC_ALL, NULL));
	setlocale(LC_ALL, "C");

	int nr_w;
	if(model_->nr_class==2 && model_->param.solver_type != MCSVM_CS)
		nr_w=1;
	else
		nr_w=model_->nr_class;

	fprintf(fp, "solver_type %s\n", solver_type_table[param.solver_type]);
	fprintf(fp, "nr_class %d\n", model_->nr_class);
	
	if(model_->label)
	{
		fprintf(fp, "label");
		for(i=0; i<model_->nr_class; i++)
			fprintf(fp, " %d", model_->label[i]);
		fprintf(fp, "\n");
	}

	fprintf(fp, "nr_feature %d\n", param.real_dim);

	fprintf(fp, "bias %.16g\n", model_->bias);

	fprintf(fp, "w\n");
	if(param.structured_w=='f')
	{
		double ** outputw = new double*[param.tmx_c];
		for(i=0; i<param.tmx_c; i++)
			outputw[i] = new double[nr_w];
		
		for(i=0; i<nr_w; i++) //classes
		{
			for(int j=0; j<param.tmx_c; j++)
			{
				double wtoput = 0;
				for(int k=0; k<w_size;k++)
					wtoput += param.transform_matrix[k][j]*model_->w[k*nr_w+i];
				outputw[j][i] = wtoput;
			}
		}
		
		for(int k=0; k<param.tmx_c;k++)
		{
			for(i=0; i<nr_w; i++) 
				fprintf(fp, "%.16g ", outputw[k][i]);
			fprintf(fp, "\n");
		}
		
		for(i=0; i<param.tmx_c; i++)
			delete[] outputw[i];
		delete[] outputw;
	}
	else
	{
		for(i=0; i<w_size; i++)
		{
			int j;
			for(j=0; j<nr_w; j++)
				fprintf(fp, "%.16g ", model_->w[i*nr_w+j]);
			fprintf(fp, "\n");
			if(i==nr_feature-1 && (param.structured_w=='s' || param.structured_w=='a'))
			{
				int k;
				for(k=nr_feature-(param.real_dim%2==0?1:2); k>=0; k--)
				{
					int j;
					for(j=0; j<nr_w; j++) 
						fprintf(fp, "%.16g ", (param.structured_w=='a'?-1:1) * model_->w[k*nr_w+j]);
					fprintf(fp, "\n");
				}
			}
		}
	}
	setlocale(LC_ALL, old_locale);
	free(old_locale);

	if (ferror(fp) != 0 || fclose(fp) != 0) return -1;
	else return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl 0xb4(%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movsd 0xc8(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0xe858
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0xe85e
movl -0x20(%rbp), %eax
movl %eax, -0x24(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x34(%rbp)
movq -0x10(%rbp), %rdi
leaq 0x16c8d(%rip), %rsi     # 0x254fc
callq 0x3360
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0xe88b
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xedce
movl $0x6, %edi
xorl %eax, %eax
movl %eax, %esi
callq 0x3260
movq %rax, %rdi
callq 0x34f0
movq %rax, -0x48(%rbp)
movl $0x6, %edi
leaq 0x16fd3(%rip), %rsi     # 0x25884
callq 0x3260
movq -0x18(%rbp), %rax
cmpl $0x2, 0xb0(%rax)
jne 0xe8d5
movq -0x18(%rbp), %rax
cmpl $0x4, (%rax)
je 0xe8d5
movl $0x1, -0x4c(%rbp)
jmp 0xe8e2
movq -0x18(%rbp), %rax
movl 0xb0(%rax), %eax
movl %eax, -0x4c(%rbp)
movq -0x40(%rbp), %rdi
movq -0x30(%rbp), %rax
movslq (%rax), %rcx
leaq 0x1c9dc(%rip), %rax     # 0x2b2d0
movq (%rax,%rcx,8), %rdx
leaq 0x16bff(%rip), %rsi     # 0x254fe
movb $0x0, %al
callq 0x3400
movq -0x40(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0xb0(%rax), %edx
leaq 0x16bf3(%rip), %rsi     # 0x2550e
movb $0x0, %al
callq 0x3400
movq -0x18(%rbp), %rax
cmpq $0x0, 0xc0(%rax)
je 0xe999
movq -0x40(%rbp), %rdi
leaq 0x16be0(%rip), %rsi     # 0x2551b
movb $0x0, %al
callq 0x3400
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0xb0(%rcx), %eax
jge 0xe987
movq -0x40(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0xc0(%rax), %rax
movslq -0x1c(%rbp), %rcx
movl (%rax,%rcx,4), %edx
leaq 0x16bac(%rip), %rsi     # 0x25521
movb $0x0, %al
callq 0x3400
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xe949
movq -0x40(%rbp), %rdi
leaq 0x1669b(%rip), %rsi     # 0x2502d
movb $0x0, %al
callq 0x3400
movq -0x40(%rbp), %rdi
movq -0x30(%rbp), %rax
movl 0x68(%rax), %edx
leaq 0x16b7a(%rip), %rsi     # 0x25525
movb $0x0, %al
callq 0x3400
movq -0x40(%rbp), %rdi
movq -0x18(%rbp), %rax
movsd 0xc8(%rax), %xmm0
leaq 0x16b6b(%rip), %rsi     # 0x25534
movb $0x1, %al
callq 0x3400
movq -0x40(%rbp), %rdi
leaq 0x16b65(%rip), %rsi     # 0x25540
movb $0x0, %al
callq 0x3400
movq -0x30(%rbp), %rax
movsbl 0x6c(%rax), %eax
cmpl $0x66, %eax
jne 0xec16
movq -0x30(%rbp), %rax
movslq 0x7c(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x3030
movq %rax, -0x58(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x7c(%rcx), %eax
jge 0xea72
movslq -0x4c(%rbp), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x3030
movq %rax, %rdx
movq -0x58(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xea27
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0xeb3e
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x7c(%rcx), %eax
jge 0xeb2e
xorps %xmm0, %xmm0
movsd %xmm0, -0x68(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xeb06
movq -0x30(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x6c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x5c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movq 0xb8(%rax), %rax
movl -0x6c(%rbp), %ecx
imull -0x4c(%rbp), %ecx
addl -0x1c(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0x68(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x68(%rbp)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0xeaab
movsd -0x68(%rbp), %xmm0
movq -0x58(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0xea8c
jmp 0xeb30
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xea79
movl $0x0, -0x70(%rbp)
movl -0x70(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x7c(%rcx), %eax
jge 0xebaf
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0xeb92
movq -0x40(%rbp), %rdi
movq -0x58(%rbp), %rax
movslq -0x70(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
leaq 0x169c3(%rip), %rsi     # 0x25543
movb $0x1, %al
callq 0x3400
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xeb58
movq -0x40(%rbp), %rdi
leaq 0x16490(%rip), %rsi     # 0x2502d
movb $0x0, %al
callq 0x3400
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0xeb45
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x7c(%rcx), %eax
jge 0xebf4
movq -0x58(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x88(%rbp)
cmpq $0x0, %rax
je 0xebe7
movq -0x88(%rbp), %rdi
callq 0x33b0
jmp 0xebe9
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xebb6
movq -0x58(%rbp), %rax
movq %rax, -0x90(%rbp)
cmpq $0x0, %rax
je 0xec11
movq -0x90(%rbp), %rdi
callq 0x33b0
jmp 0xed8b
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0xed89
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0xec72
movq -0x40(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0xb8(%rax), %rax
movl -0x1c(%rbp), %ecx
imull -0x4c(%rbp), %ecx
addl -0x74(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
leaq 0x168e3(%rip), %rsi     # 0x25543
movb $0x1, %al
callq 0x3400
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0xec30
movq -0x40(%rbp), %rdi
leaq 0x163b0(%rip), %rsi     # 0x2502d
movb $0x0, %al
callq 0x3400
movl -0x1c(%rbp), %eax
movl -0x20(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0xed79
movq -0x30(%rbp), %rax
movsbl 0x6c(%rax), %eax
cmpl $0x73, %eax
je 0xecb3
movq -0x30(%rbp), %rax
movsbl 0x6c(%rax), %eax
cmpl $0x61, %eax
jne 0xed79
movl -0x20(%rbp), %eax
movl %eax, -0x94(%rbp)
movq -0x30(%rbp), %rax
movl 0x68(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl -0x94(%rbp), %eax
movl %edx, %esi
movl $0x2, %ecx
movl $0x1, %edx
cmpl $0x0, %esi
cmovel %edx, %ecx
subl %ecx, %eax
movl %eax, -0x78(%rbp)
cmpl $0x0, -0x78(%rbp)
jl 0xed77
movl $0x0, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0xed57
movq -0x40(%rbp), %rdi
movq -0x30(%rbp), %rax
movsbl 0x6c(%rax), %edx
movl $0x1, %eax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmpl $0x61, %edx
cmovel %ecx, %eax
cvtsi2sd %eax, %xmm0
movq -0x18(%rbp), %rax
movq 0xb8(%rax), %rax
movl -0x78(%rbp), %ecx
imull -0x4c(%rbp), %ecx
addl -0x7c(%rbp), %ecx
movslq %ecx, %rcx
mulsd (%rax,%rcx,8), %xmm0
leaq 0x167fe(%rip), %rsi     # 0x25543
movb $0x1, %al
callq 0x3400
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0xecf9
movq -0x40(%rbp), %rdi
leaq 0x162cb(%rip), %rsi     # 0x2502d
movb $0x0, %al
callq 0x3400
movl -0x78(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0xece8
jmp 0xed79
jmp 0xed7b
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xec1d
jmp 0xed8b
movq -0x48(%rbp), %rsi
movl $0x6, %edi
callq 0x3260
movq -0x48(%rbp), %rdi
callq 0x3370
movq -0x40(%rbp), %rdi
callq 0x3510
cmpl $0x0, %eax
jne 0xedbe
movq -0x40(%rbp), %rdi
callq 0x32b0
cmpl $0x0, %eax
je 0xedc7
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xedce
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)