// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x15c0, %rsp           # imm = 0x15C0
movq %rsi, %r14
movl %edi, %ebp
callq 0x3110
movq %rax, %rbx
leaq 0xcbed(%rip), %rdi      # 0x1031c
callq 0x3310
leaq 0x12b1d(%rip), %rdi     # 0x16258
callq 0x6299
leaq 0x830(%rsp), %rdx
leaq 0x430(%rsp), %rcx
leaq 0x30(%rsp), %r8
movl %ebp, %edi
movq %r14, %rsi
callq 0x3ae0
cmpl $0x0, 0x12b6a(%rip)     # 0x162d0
je 0x377e
leaq 0x12ae9(%rip), %rsi     # 0x16258
leaq 0x830(%rsp), %rdi
callq 0x8734
jmp 0x3792
leaq 0x12ad3(%rip), %rsi     # 0x16258
leaq 0x830(%rsp), %rdi
callq 0x76f6
leaq 0xc89f(%rip), %rsi      # 0x10038
leaq 0x430(%rsp), %rdi
callq 0x3220
testq %rax, %rax
je 0x3a7c
movq %rax, %r14
leaq 0xc(%rsp), %r15
andl $0x0, (%r15)
leaq 0xc30(%rsp), %r12
movq %r12, %rdi
callq 0x6299
movq %r14, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x676f
movb 0x1337a(%rip), %al      # 0x16b59
testb %al, %al
jne 0x37f0
movb 0x1531(%rsp), %al
movb %al, 0x13369(%rip)      # 0x16b59
movsbl 0xc7e(%rsp), %edx
movb %dl, 0x12aa8(%rip)      # 0x162a6
movzwl 0xc7f(%rsp), %ecx
movw %cx, 0x12a9a(%rip)      # 0x162a7
movb 0x1530(%rsp), %cl
movb %cl, 0x1333e(%rip)      # 0x16b58
cmpb $0x3, %al
setge %al
cmpb $0x3, %cl
setge %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x3833
movb $0x1, 0x12a67(%rip)     # 0x1629a
movb 0x1540(%rsp), %al
movb %al, 0x13328(%rip)      # 0x16b68
cmpb $0xe, %dl
je 0x386f
movzbl %dl, %eax
cmpl $0x1, %eax
jne 0x3a9e
movl $0xd0, %edi
callq 0x31c0
movq %rax, %r15
leaq 0x129f3(%rip), %rsi     # 0x16258
movq %rax, %rdi
callq 0x9bec
jmp 0x388b
movl $0x110, %edi            # imm = 0x110
callq 0x31c0
movq %rax, %r15
leaq 0x129d5(%rip), %rsi     # 0x16258
movq %rax, %rdi
callq 0xf076
movq %r15, (%rsp)
movq (%r15), %rax
leaq 0xc30(%rsp), %rdx
leaq 0xc(%rsp), %rcx
movq %r15, %rdi
movq %r14, %rsi
xorl %r8d, %r8d
callq *0x60(%rax)
movq %r14, %rdi
callq 0x31b0
cmpb $0x0, 0x129ea(%rip)     # 0x162a4
jne 0x38ec
movsbl 0x13296(%rip), %esi     # 0x16b59
movl 0x13293(%rip), %edx     # 0x16b5c
movl 0x13291(%rip), %ecx     # 0x16b60
movl 0x1328e(%rip), %r8d     # 0x16b64
movsbl 0x1328a(%rip), %r9d     # 0x16b68
leaq 0xc798(%rip), %rdi      # 0x1007d
xorl %eax, %eax
callq 0x3050
callq 0x3110
movq %rax, %r14
pushq $0x7
popq %rdi
pushq $0x8
popq %rsi
callq 0x3100
movq %rax, 0x132e2(%rip)     # 0x16be8
leaq 0x1294b(%rip), %rdx     # 0x16258
leaq 0x30(%rsp), %rsi
movq %rsp, %rcx
pushq $0x1
popq %r8
movq %rax, %rdi
xorl %r9d, %r9d
callq 0xc758
cmpb $0x0, 0x12979(%rip)     # 0x162a4
jne 0x3950
callq 0x3110
subq %r14, %rax
cvtsi2sd %rax, %xmm0
divsd 0xc6c6(%rip), %xmm0     # 0x10008
leaq 0xc763(%rip), %rdi      # 0x100ac
movb $0x1, %al
callq 0x3050
movq 0x13291(%rip), %rax     # 0x16be8
movsd (%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x20(%rsp)
movq (%rsp), %rdi
callq 0xcc68
addl %eax, %eax
cvtsi2sd %eax, %xmm0
movq 0x13266(%rip), %rax     # 0x16be8
movsd (%rax), %xmm1
addsd %xmm1, %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x18(%rsp)
movq (%rsp), %rdi
callq 0xcc68
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x10(%rsp)
leaq 0x128aa(%rip), %r14     # 0x16258
cvtsi2sdl 0x1319a(%rip), %xmm0 # 0x16b50
callq 0x55d5
movq 0x13226(%rip), %rax     # 0x16be8
movsd (%rax), %xmm1
movsd 0x10(%rax), %xmm4
addsd %xmm1, %xmm1
movsd 0x10(%rsp), %xmm3
mulsd %xmm0, %xmm3
addsd %xmm1, %xmm3
movsd 0x18(%rax), %xmm5
movsd 0x20(%rax), %xmm6
movsd 0x28(%rax), %xmm7
leaq 0xc6de(%rip), %rdi      # 0x100d1
movsd 0x28(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
movsd 0x18(%rsp), %xmm2
movb $0x8, %al
callq 0x3050
movq (%rsp), %rdi
movq (%rdi), %rax
leaq 0x30(%rsp), %rsi
callq *0x68(%rax)
movq 0x131c6(%rip), %rdi     # 0x16be8
callq 0x3230
movq %r14, %rdi
callq 0x64a2
movq (%rsp), %rdi
testq %rdi, %rdi
je 0x3a3e
movq (%rdi), %rax
callq *0x8(%rax)
cmpb $0x0, 0x1285f(%rip)     # 0x162a4
jne 0x3a6a
callq 0x3110
subq %rbx, %rax
cvtsi2sd %rax, %xmm0
divsd 0xc5ac(%rip), %xmm0     # 0x10008
leaq 0xc6cd(%rip), %rdi      # 0x10130
movb $0x1, %al
callq 0x3050
xorl %eax, %eax
addq $0x15c0, %rsp           # imm = 0x15C0
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq 0x12555(%rip), %rax     # 0x15fd8
movq (%rax), %rdi
leaq 0xc5ad(%rip), %rsi      # 0x1003a
leaq 0x430(%rsp), %rdx
xorl %eax, %eax
callq 0x32d0
jmp 0x3ab6
movq 0x12533(%rip), %rax     # 0x15fd8
movq (%rax), %rdi
leaq 0xc5a5(%rip), %rsi      # 0x10054
xorl %eax, %eax
callq 0x32d0
pushq $0x1
popq %rdi
callq 0x3240
movq %rax, %rbx
movl $0x110, %esi            # imm = 0x110
jmp 0x3ad0
movq %rax, %rbx
movl $0xd0, %esi
movq %r15, %rdi
callq 0x31d0
movq %rbx, %rdi
callq 0x3390