// File: qmmlib[P]QmmLibrary/predict.c
// Function: do_predict(_IO_FILE*, _IO_FILE*)
void do_predict(FILE *input, FILE *output)
{
	int correct = 0;
	int total = 0;
	double error = 0;
	double sump = 0, sumt = 0, sumpp = 0, sumtt = 0, sumpt = 0;

	int nr_class=get_nr_class(model_);
	double *prob_estimates=NULL;
	int j, n;
	int nr_feature=get_nr_feature(model_);
	if(model_->bias>=0)
		n=nr_feature+1;
	else
		n=nr_feature;

	if(flag_predict_probability)
	{
		int *labels;

		if(!check_probability_model(model_))
		{
			fprintf(stderr, "probability output is only supported for logistic regression\n");
			exit(1);
		}

		labels=(int *) malloc(nr_class*sizeof(int));
		get_labels(model_,labels);
		prob_estimates = (double *) malloc(nr_class*sizeof(double));
		fprintf(output,"labels");		
		for(j=0;j<nr_class;j++)
			fprintf(output," %d",labels[j]);
		fprintf(output,"\n");
		free(labels);
	}

	max_line_len = 1024;
	line = (char *)malloc(max_line_len*sizeof(char));
	while(readline(input) != NULL)
	{
		int i = 0;
		double target_label, predict_label;
		char *idx, *val, *label, *endptr;
		int inst_max_index = 0; // strtol gives 0 if wrong format

		label = strtok(line," \t\n");
		if(label == NULL) // empty line
			exit_input_error(total+1);

		target_label = strtod(label,&endptr);
		if(endptr == label || *endptr != '\0')
			exit_input_error(total+1);

		while(1)
		{
			if(i>=max_nr_attr-2)	// need one more for index = -1
			{
				max_nr_attr *= 2;
				x = (struct feature_node *) realloc(x,max_nr_attr*sizeof(struct feature_node));
			}

			idx = strtok(NULL,":");
			val = strtok(NULL," \t");

			if(val == NULL)
				break;
			errno = 0;
			x[i].index = (int) strtol(idx,&endptr,10);
			if(endptr == idx || errno != 0 || *endptr != '\0' || x[i].index <= inst_max_index)
				exit_input_error(total+1);
			else
				inst_max_index = x[i].index;

			errno = 0;
			x[i].value = strtod(val,&endptr);
			if(endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
				exit_input_error(total+1);

			// feature indices larger than those in training are not used
			if(x[i].index <= nr_feature)
				++i;
		}

		if(model_->bias>=0)
		{
			x[i].index = n;
			x[i].value = model_->bias;
			i++;
		}
		x[i].index = -1;

		if(flag_predict_probability)
		{
			int j;
			predict_label = predict_probability(model_,x,prob_estimates);
			fprintf(output,"%g",predict_label);
			for(j=0;j<model_->nr_class;j++)
				fprintf(output," %g",prob_estimates[j]);
			fprintf(output,"\n");
		}
		else
		{
			predict_label = predict(model_,x);
			fprintf(output,"%g\n",predict_label);
		}

		if(predict_label == target_label)
			++correct;
		error += (predict_label-target_label)*(predict_label-target_label);
                sump += predict_label;
                sumt += target_label;
                sumpp += predict_label*predict_label;
                sumtt += target_label*target_label;
                sumpt += predict_label*target_label;
                ++total;
        }
        if(model_->param.solver_type==L2R_L2LOSS_SVR || 
           model_->param.solver_type==L2R_L1LOSS_SVR_DUAL || 
           model_->param.solver_type==L2R_L2LOSS_SVR_DUAL)
        {
                printf("Mean squared error = %g (regression)\n",error/total);
                printf("Squared correlation coefficient = %g (regression)\n",
                       ((total*sumpt-sump*sumt)*(total*sumpt-sump*sumt))/
                       ((total*sumpp-sump*sump)*(total*sumtt-sumt*sumt))
                       );
        }
	else
		printf("Accuracy = %g%% (%d/%d)\n",(double) correct/total*100,correct,total);
	if(flag_predict_probability)
		free(prob_estimates);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x20(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x28(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x30(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x38(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x40(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x48(%rbp)
movq 0x23dc0(%rip), %rdi     # 0x27488
callq 0xdc00
movl %eax, -0x4c(%rbp)
movq $0x0, -0x58(%rbp)
movq 0x23da9(%rip), %rdi     # 0x27488
callq 0xdbe0
movl %eax, -0x64(%rbp)
movq 0x23d9a(%rip), %rax     # 0x27488
movsd 0xc8(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x370a
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x3710
movl -0x64(%rbp), %eax
movl %eax, -0x60(%rbp)
cmpl $0x0, 0x23d79(%rip)     # 0x27490
je 0x37e6
movq 0x23d64(%rip), %rdi     # 0x27488
callq 0xd0d0
cmpl $0x0, %eax
jne 0x3750
movq 0x238a3(%rip), %rax     # 0x26fd8
movq (%rax), %rdi
leaq 0x1e8f0(%rip), %rsi     # 0x2202f
movb $0x0, %al
callq 0x33c0
movl $0x1, %edi
callq 0x3340
movslq -0x4c(%rbp), %rdi
shlq $0x2, %rdi
callq 0x3390
movq %rax, -0x70(%rbp)
movq 0x23d20(%rip), %rdi     # 0x27488
movq -0x70(%rbp), %rsi
callq 0xdc20
movslq -0x4c(%rbp), %rdi
shlq $0x3, %rdi
callq 0x3390
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rdi
leaq 0x1e8e0(%rip), %rsi     # 0x2206d
movb $0x0, %al
callq 0x33c0
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0x37cb
movq -0x10(%rbp), %rdi
movq -0x70(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl (%rax,%rcx,4), %edx
leaq 0x1e8bb(%rip), %rsi     # 0x22074
movb $0x0, %al
callq 0x33c0
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x379b
movq -0x10(%rbp), %rdi
leaq 0x1e8a4(%rip), %rsi     # 0x2207a
movb $0x0, %al
callq 0x33c0
movq -0x70(%rbp), %rdi
callq 0x3330
movl $0x400, 0x23ca4(%rip)   # imm = 0x400
movslq 0x23c9d(%rip), %rdi     # 0x27494
shlq $0x0, %rdi
callq 0x3390
movq %rax, 0x23c91(%rip)     # 0x27498
movq -0x8(%rbp), %rdi
callq 0x3e00
cmpq $0x0, %rax
je 0x3c89
movl $0x0, -0x74(%rbp)
movl $0x0, -0xac(%rbp)
movq 0x23c66(%rip), %rdi     # 0x27498
leaq 0x1e83f(%rip), %rsi     # 0x22078
callq 0x3400
movq %rax, -0xa0(%rbp)
cmpq $0x0, -0xa0(%rbp)
jne 0x385a
movl -0x18(%rbp), %edi
addl $0x1, %edi
callq 0x3640
movq -0xa0(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x31a0
movsd %xmm0, -0x80(%rbp)
movq -0xa8(%rbp), %rax
cmpq -0xa0(%rbp), %rax
je 0x3891
movq -0xa8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
je 0x389c
movl -0x18(%rbp), %edi
addl $0x1, %edi
callq 0x3640
jmp 0x389e
movl -0x74(%rbp), %eax
movl 0x239e9(%rip), %ecx     # 0x27290
subl $0x2, %ecx
cmpl %ecx, %eax
jl 0x38da
movl 0x239dc(%rip), %eax     # 0x27290
shll %eax
movl %eax, 0x239d4(%rip)     # 0x27290
movq 0x23bbd(%rip), %rdi     # 0x27480
movslq 0x239c6(%rip), %rsi     # 0x27290
shlq $0x4, %rsi
callq 0x3440
movq %rax, 0x23ba6(%rip)     # 0x27480
xorl %eax, %eax
movl %eax, %edi
leaq 0x1e797(%rip), %rsi     # 0x2207c
callq 0x3400
movq %rax, -0x90(%rbp)
xorl %eax, %eax
movl %eax, %edi
leaq 0x1e782(%rip), %rsi     # 0x2207e
callq 0x3400
movq %rax, -0x98(%rbp)
cmpq $0x0, -0x98(%rbp)
jne 0x3917
jmp 0x3a60
callq 0x3040
movl $0x0, (%rax)
movq -0x90(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
movl $0xa, %edx
callq 0x33b0
movl %eax, %ecx
movq 0x23b3d(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movl %ecx, (%rax)
movq -0xa8(%rbp), %rax
cmpq -0x90(%rbp), %rax
je 0x3995
callq 0x3040
cmpl $0x0, (%rax)
jne 0x3995
movq -0xa8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jne 0x3995
movq 0x23b00(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
cmpl -0xac(%rbp), %eax
jg 0x39a2
movl -0x18(%rbp), %edi
addl $0x1, %edi
callq 0x3640
jmp 0x39bc
movq 0x23ad7(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl %eax, -0xac(%rbp)
callq 0x3040
movl $0x0, (%rax)
movq -0x98(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x31a0
movq 0x23a9f(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd %xmm0, 0x8(%rax)
movq -0xa8(%rbp), %rax
cmpq -0x98(%rbp), %rax
je 0x3a2e
callq 0x3040
cmpl $0x0, (%rax)
jne 0x3a2e
movq -0xa8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
je 0x3a39
movq -0xa8(%rbp), %rax
movsbl (%rax), %edi
callq 0x3060
cmpl $0x0, %eax
jne 0x3a39
movl -0x18(%rbp), %edi
addl $0x1, %edi
callq 0x3640
movq 0x23a40(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
cmpl -0x64(%rbp), %eax
jg 0x3a5b
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x389e
movq 0x23a21(%rip), %rax     # 0x27488
movsd 0xc8(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x3abe
movl -0x60(%rbp), %ecx
movq 0x239fe(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movl %ecx, (%rax)
movq 0x239f2(%rip), %rax     # 0x27488
movsd 0xc8(%rax), %xmm0
movq 0x239db(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd %xmm0, 0x8(%rax)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
movq 0x239bb(%rip), %rax     # 0x27480
movslq -0x74(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
cmpl $0x0, 0x239b3(%rip)     # 0x27490
je 0x3b82
movq 0x2399e(%rip), %rdi     # 0x27488
movq 0x2398f(%rip), %rsi     # 0x27480
movq -0x58(%rbp), %rdx
callq 0xcf50
movsd %xmm0, -0x88(%rbp)
movq -0x10(%rbp), %rdi
movsd -0x88(%rbp), %xmm0
leaq 0x1e56d(%rip), %rsi     # 0x22082
movb $0x1, %al
callq 0x33c0
movl $0x0, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
movq 0x23955(%rip), %rcx     # 0x27488
cmpl 0xb0(%rcx), %eax
jge 0x3b6e
movq -0x10(%rbp), %rdi
movq -0x58(%rbp), %rax
movslq -0xb0(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
leaq 0x1e52b(%rip), %rsi     # 0x22081
movb $0x1, %al
callq 0x33c0
movl -0xb0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0x3b26
movq -0x10(%rbp), %rdi
leaq 0x1e501(%rip), %rsi     # 0x2207a
movb $0x0, %al
callq 0x33c0
jmp 0x3bb7
movq 0x238ff(%rip), %rdi     # 0x27488
movq 0x238f0(%rip), %rsi     # 0x27480
callq 0xcca0
movsd %xmm0, -0x88(%rbp)
movq -0x10(%rbp), %rdi
movsd -0x88(%rbp), %xmm0
leaq 0x1e4d5(%rip), %rsi     # 0x22085
movb $0x1, %al
callq 0x33c0
movsd -0x88(%rbp), %xmm0
ucomisd -0x80(%rbp), %xmm0
jne 0x3bd1
jp 0x3bd1
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
movsd -0x88(%rbp), %xmm0
subsd -0x80(%rbp), %xmm0
movsd -0x88(%rbp), %xmm2
subsd -0x80(%rbp), %xmm2
movsd -0x20(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x20(%rbp)
movsd -0x88(%rbp), %xmm0
addsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x28(%rbp)
movsd -0x80(%rbp), %xmm0
addsd -0x30(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
movsd -0x88(%rbp), %xmm0
movsd -0x88(%rbp), %xmm2
movsd -0x38(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x38(%rbp)
movsd -0x80(%rbp), %xmm0
movsd -0x80(%rbp), %xmm2
movsd -0x40(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
movsd -0x88(%rbp), %xmm0
movsd -0x80(%rbp), %xmm2
movsd -0x48(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x3807
movq 0x237f8(%rip), %rax     # 0x27488
cmpl $0xb, (%rax)
je 0x3cb1
movq 0x237ec(%rip), %rax     # 0x27488
cmpl $0xd, (%rax)
je 0x3cb1
movq 0x237e0(%rip), %rax     # 0x27488
cmpl $0xc, (%rax)
jne 0x3db5
movsd -0x20(%rbp), %xmm0
cvtsi2sdl -0x18(%rbp), %xmm1
divsd %xmm1, %xmm0
leaq 0x1e3c3(%rip), %rdi     # 0x22089
movb $0x1, %al
callq 0x3050
cvtsi2sdl -0x18(%rbp), %xmm0
movsd -0x48(%rbp), %xmm2
movsd -0x28(%rbp), %xmm1
mulsd -0x30(%rbp), %xmm1
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvtsi2sdl -0x18(%rbp), %xmm1
movsd -0x48(%rbp), %xmm3
movsd -0x28(%rbp), %xmm2
mulsd -0x30(%rbp), %xmm2
movq %xmm2, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm2
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
cvtsi2sdl -0x18(%rbp), %xmm1
movsd -0x38(%rbp), %xmm3
movsd -0x28(%rbp), %xmm2
mulsd -0x28(%rbp), %xmm2
movq %xmm2, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm2
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
cvtsi2sdl -0x18(%rbp), %xmm2
movsd -0x40(%rbp), %xmm4
movsd -0x30(%rbp), %xmm3
mulsd -0x30(%rbp), %xmm3
movq %xmm3, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm3
mulsd %xmm4, %xmm2
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
divsd %xmm1, %xmm0
leaq 0x1e303(%rip), %rdi     # 0x220af
movb $0x1, %al
callq 0x3050
jmp 0x3de3
cvtsi2sdl -0x14(%rbp), %xmm0
cvtsi2sdl -0x18(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd 0x1e23d(%rip), %xmm1    # 0x22008
mulsd %xmm1, %xmm0
movl -0x14(%rbp), %esi
movl -0x18(%rbp), %edx
leaq 0x1e306(%rip), %rdi     # 0x220e2
movb $0x1, %al
callq 0x3050
cmpl $0x0, 0x236a6(%rip)     # 0x27490
je 0x3df5
movq -0x58(%rbp), %rdi
callq 0x3330
addq $0xb0, %rsp
popq %rbp
retq
nop