// File: qmmlib[P]QmmLibrary/do_predict_iter.cpp
// Function: do_predict_iter(char*, model const*)
double do_predict_iter(char* file_name, const struct model* model_)
{
	FILE *input = fopen(file_name,"r");
	int max_nr_attr = 64;
	struct feature_node *x = (struct feature_node *) malloc(max_nr_attr*sizeof(struct feature_node));
	
	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_);
	int j, n;
	int nr_feature=get_nr_feature(model_);
	if(model_->bias>=0)
		n=nr_feature+1;
	else
		n=nr_feature;

	int max_line_len = 1024;
	char * line = (char *)malloc(max_line_len*sizeof(char));
	int len;
	while(fgets(line,max_line_len,input) != NULL)
	{
		while(strrchr(line,'\n') == NULL)
		{
			max_line_len *= 2;
			line = (char *) realloc(line,max_line_len);
			len = (int) strlen(line);
			if(fgets(line+len,max_line_len-len,input) == NULL)
				break;
		}
	
		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
		{
			fprintf(stderr,"Wrong input format at line %d\n", total+1);
			exit(1);
		}

		target_label = strtod(label,&endptr);
		if(endptr == label || *endptr != '\0')
		{
			fprintf(stderr,"Wrong input format at line %d\n", total+1);
			exit(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)
			{
				fprintf(stderr,"Wrong input format at line %d\n", total+1);
				exit(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)))
			{
				fprintf(stderr,"Wrong input format at line %d\n", total+1);
				exit(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;

		predict_label = predict(model_,x);

		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;
	}
	free(line);
	free(x);
	fclose(input);
	
	return ((double)correct/(double)total)*100.0f;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
leaq 0x404c(%rip), %rsi      # 0x2500a
callq 0x3360
movq %rax, -0x18(%rbp)
movl $0x40, -0x1c(%rbp)
movslq -0x1c(%rbp), %rdi
shlq $0x4, %rdi
callq 0x33d0
movq %rax, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x38(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x40(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x48(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x50(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x58(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rdi
callq 0xf300
movl %eax, -0x64(%rbp)
movq -0x10(%rbp), %rdi
callq 0xf2e0
movl %eax, -0x70(%rbp)
movq -0x10(%rbp), %rax
movsd 0xc8(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x21055
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x2105b
movl -0x70(%rbp), %eax
movl %eax, -0x6c(%rbp)
movl $0x400, -0x74(%rbp)     # imm = 0x400
movslq -0x74(%rbp), %rdi
shlq $0x0, %rdi
callq 0x33d0
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
movl -0x74(%rbp), %esi
movq -0x18(%rbp), %rdx
callq 0x3460
cmpq $0x0, %rax
je 0x21519
jmp 0x2108f
movq -0x80(%rbp), %rdi
movl $0xa, %esi
callq 0x3330
cmpq $0x0, %rax
jne 0x210f5
movl -0x74(%rbp), %eax
shll %eax
movl %eax, -0x74(%rbp)
movq -0x80(%rbp), %rdi
movslq -0x74(%rbp), %rsi
callq 0x3490
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
callq 0x3120
movl %eax, -0x84(%rbp)
movq -0x80(%rbp), %rdi
movslq -0x84(%rbp), %rax
addq %rax, %rdi
movl -0x74(%rbp), %esi
subl -0x84(%rbp), %esi
movq -0x18(%rbp), %rdx
callq 0x3460
cmpq $0x0, %rax
jne 0x210f3
jmp 0x210f5
jmp 0x2108f
movl $0x0, -0x88(%rbp)
movl $0x0, -0xbc(%rbp)
movq -0x80(%rbp), %rdi
leaq 0x3f17(%rip), %rsi      # 0x2502b
callq 0x3440
movq %rax, -0xb0(%rbp)
cmpq $0x0, -0xb0(%rbp)
jne 0x21152
movq 0x9ea7(%rip), %rax      # 0x2afd8
movq (%rax), %rdi
movl -0x30(%rbp), %edx
addl $0x1, %edx
leaq 0x3d6b(%rip), %rsi      # 0x24eac
movb $0x0, %al
callq 0x3400
movl $0x1, %edi
callq 0x3380
movq -0xb0(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x31e0
movsd %xmm0, -0x90(%rbp)
movq -0xb8(%rbp), %rax
cmpq -0xb0(%rbp), %rax
je 0x2118c
movq -0xb8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
je 0x211b4
movq 0x9e45(%rip), %rax      # 0x2afd8
movq (%rax), %rdi
movl -0x30(%rbp), %edx
addl $0x1, %edx
leaq 0x3d09(%rip), %rsi      # 0x24eac
movb $0x0, %al
callq 0x3400
movl $0x1, %edi
callq 0x3380
jmp 0x211b6
movl -0x88(%rbp), %eax
movl -0x1c(%rbp), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
jl 0x211e3
movl -0x1c(%rbp), %eax
shll %eax
movl %eax, -0x1c(%rbp)
movq -0x28(%rbp), %rdi
movslq -0x1c(%rbp), %rsi
shlq $0x4, %rsi
callq 0x3490
movq %rax, -0x28(%rbp)
xorl %eax, %eax
movl %eax, %edi
leaq 0x3e3b(%rip), %rsi      # 0x25029
callq 0x3440
movq %rax, -0xa0(%rbp)
xorl %eax, %eax
movl %eax, %edi
leaq 0x3e21(%rip), %rsi      # 0x25026
callq 0x3440
movq %rax, -0xa8(%rbp)
cmpq $0x0, -0xa8(%rbp)
jne 0x21220
jmp 0x213a7
callq 0x3040
movl $0x0, (%rax)
movq -0xa0(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
movl $0xa, %edx
callq 0x33f0
movl %eax, %ecx
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movl %ecx, (%rax)
movq -0xb8(%rbp), %rax
cmpq -0xa0(%rbp), %rax
je 0x2129e
callq 0x3040
cmpl $0x0, (%rax)
jne 0x2129e
movq -0xb8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jne 0x2129e
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
cmpl -0xbc(%rbp), %eax
jg 0x212c6
movq 0x9d33(%rip), %rax      # 0x2afd8
movq (%rax), %rdi
movl -0x30(%rbp), %edx
addl $0x1, %edx
leaq 0x3bf7(%rip), %rsi      # 0x24eac
movb $0x0, %al
callq 0x3400
movl $0x1, %edi
callq 0x3380
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl %eax, -0xbc(%rbp)
callq 0x3040
movl $0x0, (%rax)
movq -0xa8(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x31e0
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd %xmm0, 0x8(%rax)
movq -0xb8(%rbp), %rax
cmpq -0xa8(%rbp), %rax
je 0x21352
callq 0x3040
cmpl $0x0, (%rax)
jne 0x21352
movq -0xb8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
je 0x2137a
movq -0xb8(%rbp), %rax
movsbl (%rax), %edi
callq 0x3060
cmpl $0x0, %eax
jne 0x2137a
movq 0x9c7f(%rip), %rax      # 0x2afd8
movq (%rax), %rdi
movl -0x30(%rbp), %edx
addl $0x1, %edx
leaq 0x3b43(%rip), %rsi      # 0x24eac
movb $0x0, %al
callq 0x3400
movl $0x1, %edi
callq 0x3380
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
cmpl -0x70(%rbp), %eax
jg 0x213a2
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x211b6
movq -0x10(%rbp), %rax
movsd 0xc8(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x21405
movl -0x6c(%rbp), %ecx
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movsd 0xc8(%rax), %xmm0
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd %xmm0, 0x8(%rax)
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
movq -0x28(%rbp), %rax
movslq -0x88(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0xe3a0
movsd %xmm0, -0x98(%rbp)
movsd -0x98(%rbp), %xmm0
ucomisd -0x90(%rbp), %xmm0
jne 0x2144f
jp 0x2144f
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movsd -0x98(%rbp), %xmm0
subsd -0x90(%rbp), %xmm0
movsd -0x98(%rbp), %xmm2
subsd -0x90(%rbp), %xmm2
movsd -0x38(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x38(%rbp)
movsd -0x98(%rbp), %xmm0
addsd -0x40(%rbp), %xmm0
movsd %xmm0, -0x40(%rbp)
movsd -0x90(%rbp), %xmm0
addsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movsd -0x98(%rbp), %xmm0
movsd -0x98(%rbp), %xmm2
movsd -0x50(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x50(%rbp)
movsd -0x90(%rbp), %xmm0
movsd -0x90(%rbp), %xmm2
movsd -0x58(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x58(%rbp)
movsd -0x98(%rbp), %xmm0
movsd -0x90(%rbp), %xmm2
movsd -0x60(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x60(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x21073
movq -0x80(%rbp), %rdi
callq 0x3370
movq -0x28(%rbp), %rdi
callq 0x3370
movq -0x18(%rbp), %rdi
callq 0x32b0
cvtsi2sdl -0x2c(%rbp), %xmm0
cvtsi2sdl -0x30(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd 0x2afe(%rip), %xmm1     # 0x24048
mulsd %xmm1, %xmm0
addq $0xc0, %rsp
popq %rbp
retq
nopw (%rax,%rax)