// File: myudelson[P]hmm-scalable/predicthmmst.cpp
// Function: main
int main (int argc, char ** argv) {
	clock_t tm0 = clock();
	printf("predicthmm starting...\n");
	set_task_defaults(&task);
	
	char input_file[1024];
	char model_file[1024];
	char predict_file[1024];
	
	parse_arguments(argc, argv, input_file, model_file, predict_file);
    // task.predictions = 2; // do not force it on

    // read data
    if(task.binaryinput==0) {
        InputUtilSt::readTxt(input_file, &task);
    } else {
        InputUtilSt::readBin(input_file, &task);
    }
    
    // read model header
	FILE *fid = fopen(model_file,"r");
	if(fid == NULL)
	{
		fprintf(stderr,"Can't read model file %s\n",model_file);
		exit(1);
	}
	int max_line_length = 1024;
	char *line = Malloc(char,(size_t)max_line_length);
	NDAT line_no = 0;
    struct task task_model;
    set_task_defaults(&task_model);
    bool overwrite = false;
//    if(overwrite)
        readSolverInfo(fid, &task_model, &line_no);
//    else
//        readSolverInfo(fid, &inittask, &line_no);
    
    // copy partial info from task_model to task
    if(task.nO==0) task.nO = task_model.nO;
    task.structure = task_model.structure;
    task.solver = task_model.solver;
    task.solver_setting = task_model.solver_setting;
    
    // copy number of states from the model
    task.nS = task_model.nS;
    
    // if number of states or observations >2, then no check
    if( task.nO>2 || task.nS>2) {
        task.do_not_check_constraints = 1;
    }
    
	// copy number of slices from the model
	task.nZ = task_model.nZ;
    //
    // create hmm Object
    //
    HMMProblemSt *hmm = NULL;
	switch(task.structure)
	{
		case STRUCTURE_SKILL: // Conjugate Gradient Descent
//            case STRUCTURE_GROUP: // Conjugate Gradient Descent
			hmm = new HMMProblemSt(&task);
			break;
        case STRUCTURE_ELO: // Gradient Descent, pT=f(K,G), other by K
            hmm = new HMMProblemEloSt(&task);
            break;
        default:
            fprintf(stderr,"Solver specified (%d) is not supported!\n",task.structure);
            exit(1);
            break;
	}
    // read model body
    hmm->readModelBody(fid, &task_model, &line_no, overwrite);
  	fclose(fid);
	free(line);
	
	if(task.quiet == 0)
        printf("input read, nO=%d, nG=%d, nK=%d, nI=%d, nZ=%d\n",task.nO, task.nG, task.nK, task.nI, task.nZ);
	
	clock_t tm = clock();
//    if(task.metrics>0 || task.predictions>0) {
        metrics = Calloc(NUMBER, (size_t)7);// LL, AIC, BIC, RMSE, RMSEnonull, Acc, Acc_nonull;
//    }
    HMMProblemSt::predict(metrics, predict_file, &task, &hmm, 1, NULL);

//    predict(predict_file, hmm);
	if(task.quiet == 0)
		printf("predicting is done in %8.6f seconds\n",(NUMBER)(clock()-tm)/CLOCKS_PER_SEC);
    //if( task.predictions>0 ) {
        printf("trained model LL=%15.7f (%15.7f), AIC=%8.6f, BIC=%8.6f, RMSE=%8.6f (%8.6f), Acc=%8.6f (%8.6f)\n",
               metrics[0], metrics[1], // ll's
               2*hmm->getModelParamN() + 2*metrics[0], // AIC
               hmm->getModelParamN()*safelog(task.N) + 2*metrics[0], //BIC
               metrics[2], metrics[3], // rmse's
               metrics[4], metrics[5]); // acc's
    //}
    
    // post-prediction runs
    hmm->postPredictionSave(predict_file);
    
    // recycle memory
    free(metrics);
	destroy_input_data(&task);
    delete hmm;

    if(task.quiet == 0)
		printf("overall time running is %8.6f seconds\n",(NUMBER)(clock()-tm0)/CLOCKS_PER_SEC);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1640, %rsp           # imm = 0x1640
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
callq 0x3180
movq %rax, -0x18(%rbp)
leaq 0x178a3(%rip), %rdi     # 0x1b12c
movb $0x0, %al
callq 0x3060
leaq 0x1ea61(%rip), %rdi     # 0x222f8
callq 0x8d90
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq -0x420(%rbp), %rdx
leaq -0x820(%rbp), %rcx
leaq -0xc20(%rbp), %r8
callq 0x3dc0
cmpl $0x0, 0x1eaac(%rip)     # 0x22370
jne 0x38db
leaq -0x420(%rbp), %rdi
leaq 0x1ea24(%rip), %rsi     # 0x222f8
callq 0xba30
jmp 0x38ee
leaq -0x420(%rbp), %rdi
leaq 0x1ea0f(%rip), %rsi     # 0x222f8
callq 0xdae0
leaq -0x820(%rbp), %rdi
leaq 0x17848(%rip), %rsi     # 0x1b144
callq 0x3310
movq %rax, -0xc28(%rbp)
cmpq $0x0, -0xc28(%rbp)
jne 0x393b
movq 0x1e6bf(%rip), %rax     # 0x21fd8
movq (%rax), %rdi
leaq -0x820(%rbp), %rdx
leaq 0x1781c(%rip), %rsi     # 0x1b146
movb $0x0, %al
callq 0x33c0
movl $0x1, %edi
callq 0x3330
movl $0x400, -0xc2c(%rbp)    # imm = 0x400
movslq -0xc2c(%rbp), %rdi
shlq $0x0, %rdi
callq 0x3380
movq %rax, -0xc38(%rbp)
movl $0x0, -0xc3c(%rbp)
leaq -0x15d0(%rbp), %rdi
callq 0x8d90
movb $0x0, -0x15d1(%rbp)
movq -0xc28(%rbp), %rdi
leaq -0x15d0(%rbp), %rsi
leaq -0xc3c(%rbp), %rdx
callq 0x98a0
movsbl 0x1f25f(%rip), %eax     # 0x22bf9
cmpl $0x0, %eax
jne 0x39ab
movb -0xccf(%rbp), %al
movb %al, 0x1f24e(%rip)      # 0x22bf9
movb -0x1582(%rbp), %al
movb %al, 0x1e98f(%rip)      # 0x22346
movb -0x1581(%rbp), %al
movb %al, 0x1e984(%rip)      # 0x22347
movb -0x1580(%rbp), %al
movb %al, 0x1e979(%rip)      # 0x22348
movb -0xcd0(%rbp), %al
movb %al, 0x1f21d(%rip)      # 0x22bf8
movsbl 0x1f217(%rip), %eax     # 0x22bf9
cmpl $0x2, %eax
jg 0x39f3
movsbl 0x1f20a(%rip), %eax     # 0x22bf8
cmpl $0x2, %eax
jle 0x39fa
movb $0x1, 0x1e940(%rip)     # 0x2233a
movb -0xcc0(%rbp), %al
movb %al, 0x1f202(%rip)      # 0x22c08
movq $0x0, -0x15e0(%rbp)
movsbl 0x1e92e(%rip), %eax     # 0x22346
movl %eax, -0x15fc(%rbp)
subl $0x1, %eax
je 0x3a35
jmp 0x3a25
movl -0x15fc(%rbp), %eax
subl $0xe, %eax
je 0x3a95
jmp 0x3af2
movl $0xd0, %edi
callq 0x3270
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x1608(%rbp)
leaq 0x1e8a5(%rip), %rsi     # 0x222f8
callq 0x11310
jmp 0x3a5a
movq -0x1608(%rbp), %rax
movq %rax, -0x15e0(%rbp)
jmp 0x3b1b
movq -0x1608(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x15e8(%rbp)
movl %eax, -0x15ec(%rbp)
movl $0xd0, %esi
callq 0x3280
jmp 0x3da6
movl $0x110, %edi            # imm = 0x110
callq 0x3270
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x1610(%rbp)
leaq 0x1e845(%rip), %rsi     # 0x222f8
callq 0x199a0
jmp 0x3aba
movq -0x1610(%rbp), %rax
movq %rax, -0x15e0(%rbp)
jmp 0x3b1b
movq -0x1610(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x15e8(%rbp)
movl %eax, -0x15ec(%rbp)
movl $0x110, %esi            # imm = 0x110
callq 0x3280
jmp 0x3da6
movq 0x1e4df(%rip), %rax     # 0x21fd8
movq (%rax), %rdi
movsbl 0x1e843(%rip), %edx     # 0x22346
leaq 0x17656(%rip), %rsi     # 0x1b160
movb $0x0, %al
callq 0x33c0
movl $0x1, %edi
callq 0x3330
movq -0x15e0(%rbp), %rdi
movq -0xc28(%rbp), %rsi
movb -0x15d1(%rbp), %r8b
movq (%rdi), %rax
leaq -0x15d0(%rbp), %rdx
leaq -0xc3c(%rbp), %rcx
andb $0x1, %r8b
movzbl %r8b, %r8d
callq *0x60(%rax)
movq -0xc28(%rbp), %rdi
callq 0x3260
movq -0xc38(%rbp), %rdi
callq 0x3320
movsbl 0x1e7d9(%rip), %eax     # 0x22344
cmpl $0x0, %eax
jne 0x3ba0
movsbl 0x1f082(%rip), %esi     # 0x22bf9
movl 0x1f07f(%rip), %edx     # 0x22bfc
movl 0x1f07d(%rip), %ecx     # 0x22c00
movl 0x1f07a(%rip), %r8d     # 0x22c04
movsbl 0x1f076(%rip), %r9d     # 0x22c08
leaq 0x175f0(%rip), %rdi     # 0x1b189
movb $0x0, %al
callq 0x3060
callq 0x3180
movq %rax, -0x15f8(%rbp)
movl $0x7, %edi
movl $0x8, %esi
callq 0x3170
movq %rax, 0x1f0c6(%rip)     # 0x22c88
movq 0x1f0bf(%rip), %rdi     # 0x22c88
leaq -0xc20(%rbp), %rsi
leaq 0x1e721(%rip), %rdx     # 0x222f8
leaq -0x15e0(%rbp), %rcx
movl $0x1, %r8d
xorl %eax, %eax
movl %eax, %r9d
callq 0x15400
movsbl 0x1e74f(%rip), %eax     # 0x22344
cmpl $0x0, %eax
jne 0x3c25
callq 0x3180
subq -0x15f8(%rbp), %rax
cvtsi2sd %rax, %xmm0
movsd 0x173f5(%rip), %xmm1    # 0x1b008
divsd %xmm1, %xmm0
leaq 0x1759a(%rip), %rdi     # 0x1b1b8
movb $0x1, %al
callq 0x3060
movq 0x1f05c(%rip), %rax     # 0x22c88
movsd (%rax), %xmm0
movsd %xmm0, -0x1620(%rbp)
movq 0x1f049(%rip), %rax     # 0x22c88
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x1630(%rbp)
movq -0x15e0(%rbp), %rdi
callq 0x15c30
shll %eax
cvtsi2sd %eax, %xmm1
movq 0x1f023(%rip), %rax     # 0x22c88
movsd (%rax), %xmm0
addsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x1628(%rbp)
movq -0x15e0(%rbp), %rdi
callq 0x15c30
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x1638(%rbp)
cvtsi2sdl 0x1ef57(%rip), %xmm0 # 0x22bf0
callq 0x7690
movsd -0x1638(%rbp), %xmm3
movsd -0x1630(%rbp), %xmm1
movsd -0x1628(%rbp), %xmm2
movaps %xmm0, %xmm5
movsd -0x1620(%rbp), %xmm0
movq 0x1efc0(%rip), %rax     # 0x22c88
movsd 0x17340(%rip), %xmm4    # 0x1b010
mulsd (%rax), %xmm4
mulsd %xmm5, %xmm3
addsd %xmm4, %xmm3
movq 0x1efa5(%rip), %rax     # 0x22c88
movsd 0x10(%rax), %xmm4
movq 0x1ef99(%rip), %rax     # 0x22c88
movsd 0x18(%rax), %xmm5
movq 0x1ef8d(%rip), %rax     # 0x22c88
movsd 0x20(%rax), %xmm6
movq 0x1ef81(%rip), %rax     # 0x22c88
movsd 0x28(%rax), %xmm7
leaq 0x174ca(%rip), %rdi     # 0x1b1dd
movb $0x8, %al
callq 0x3060
movq -0x15e0(%rbp), %rdi
leaq -0xc20(%rbp), %rsi
movq (%rdi), %rax
callq *0x68(%rax)
movq 0x1ef53(%rip), %rdi     # 0x22c88
callq 0x3320
leaq 0x1e5b7(%rip), %rdi     # 0x222f8
callq 0x93d0
movq -0x15e0(%rbp), %rax
movq %rax, -0x1618(%rbp)
cmpq $0x0, %rax
je 0x3d67
movq -0x1618(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movsbl 0x1e5d6(%rip), %eax     # 0x22344
cmpl $0x0, %eax
jne 0x3d9b
callq 0x3180
subq -0x18(%rbp), %rax
cvtsi2sd %rax, %xmm0
movsd 0x1727f(%rip), %xmm1    # 0x1b008
divsd %xmm1, %xmm0
leaq 0x174a8(%rip), %rdi     # 0x1b23c
movb $0x1, %al
callq 0x3060
xorl %eax, %eax
addq $0x1640, %rsp           # imm = 0x1640
popq %rbp
retq
movq -0x15e8(%rbp), %rdi
callq 0x3490
nopw %cs:(%rax,%rax)