// File: myudelson[P]hmm-scalable/trainhmm.cpp
// Function: main
int main (int argc, char ** argv) {
//    int array[] = {1, 2, 3, 4, 5, 6, 7};
//    NDAT lim = 0;
//    int v = 5;
//    NDAT ix = binsearch(&v, array, 7, sizeof(int)); // SparseArray2D<int>::binsearch(&v, array, 7, &lim);
//    fprintf(stderr,"%d found=%d, lim=%d\n",v, ix, lim);
//    
//    v = 8;
//    ix = SparseArray2D<int>::binsearch(&v, array, 7, &lim);
//    fprintf(stderr,"%d found=%d, lim=%d\n",v, ix, lim);
//    
//    v = 0;
//    ix = SparseArray2D<int>::binsearch(&v, array, 7, &lim);
//    fprintf(stderr,"%d found=%d, lim=%d\n",v, ix, lim);
//    
//    int c = (unsigned long)ceil((double)34600/20000);
    
	clock_t tm_all = clock();//overall time //SEQ
//    double _tm_all = omp_get_wtime(); //PAR
    
	char input_file[1024]; // data
	char output_file[1024]; // model
    char colsole_file[1024]; // console copy
	char predict_file[1024]; // predictions
    
	set_param_defaults(&param);
    
    
    // parse parameters, step 1
	parse_arguments_step1(argc, argv, input_file, output_file, predict_file, colsole_file);

    FILE *fid_console = NULL;
    if(param.duplicate_console==1)
        fid_console = fopen(colsole_file,"w");
    
    if(!param.quiet) {
        printf("trainhmm starting...\n");
        if(param.duplicate_console==1) fprintf(fid_console, "trainhmm starting...\n");
    }

    clock_t tm_read = clock();//overall time //SEQ
//    double _tm_read = omp_get_wtime(); //PAR
    int read_ok = read_and_structure_data(input_file, fid_console);
    tm_read = (clock_t)(clock()-tm_read);//SEQ
    
//    _tm_read = omp_get_wtime()-_tm_read;//PAR
    
//    // experimental
//    for(NCAT k=0; k<param.nK; k++) {
//        char fn [256];
//        sprintf (fn, "b89_kts_skill%d_A.txt", k);
//        InputUtil::writeInputMatrix(fn, &param, param.k_numg[k], param.k_g_data[k]);
//    }

    if( ! read_ok )
        return 0;
    
    // once we know nO (number of observations) parse parameters, step 2
    parse_arguments_step2(argc, argv, fid_console);
    
//    write_pLo_irt();
    
    
//    //
//    // read item mean % correct
//    //
//    FILE *fid = fopen("a89_kts_train01_voc_i.txt","r");
//	max_line_length = 1024;
//	char *col;
//    string item;
//    map<string,NCAT>::iterator it;
//    param.item_complexity = Calloc(NUMBER, param.map_step_bwd->size());
//    line = (char *)malloc(max_line_length);// Malloc(char,max_line_length);
//    while( readline(fid)!=NULL) {
//		// Group
//		col = strtok(line,"\t\n\r");
//		item = string( col );
//		it = param.map_step_fwd->find(item);
//		if( it==param.map_step_fwd->end() ) { // not found
//            fprintf(stderr,"DID NOT FIND THE STEP!!\n");
//            return false;
//		}
//		else {
////            if( it->second > param.map_step_bwd->size()) {
////                int z = 0 ;
////            }
//            NUMBER v = atof( strtok(NULL,"\t\n\r") );
//            param.item_complexity[ it->second ] = v;
//		}
//    }
//    free(line);
//    fclose(fid);

    if(!param.quiet) {
        printf("input read, nO=%d, nG=%d, nK=%d, nI=%d, nZ=%d\n",param.nO, param.nG, param.nK, param.nI, param.nZ);
        if(param.duplicate_console==1) fprintf(fid_console, "input read, nO=%d, nG=%d, nK=%d, nI=%d, nZ=%d\n",param.nO, param.nG, param.nK, param.nI, param.nZ);
    }
    
    //    // write time
    //    if(param.time==1) {
    //        const char * fn = "a89_kts_times.txt";
    ////        const char * fn = "a89_uskts_times.txt";
    //        write_time_interval_data(&param, fn);
    //    }
    
    // erase blocking labels
    zeroLabels(&param);

    clock_t tm_fit = 0; //SEQ
    clock_t tm_predict = 0; //SEQ
//    double _tm_fit;//PAR
//    double _tm_predict;//PAR
    
    if(param.cv_folds==0) { // not cross-validation
        // create problem
        HMMProblem *hmm = NULL;
        switch(param.structure)
        {
            case STRUCTURE_SKILL: // Conjugate Gradient Descent
//            case STRUCTURE_GROUP: // Conjugate Gradient Descent
                hmm = new HMMProblem(&param);
                break;
                //            case STRUCTURE_PIg: // Gradient Descent: PI by group, A,B by skill
                //                hmm = new HMMProblemPiG(&param);
                //                break;
            case STRUCTURE_SKABslc: // Conjugate Gradient Descent
                hmm = new HMMProblemSlicedAB(&param);
                break;
            case STRUCTURE_SKAslc: // Conjugate Gradient Descent
                hmm = new HMMProblemSlicedA(&param);
                break;
            case STRUCTURE_PIgk: // Gradient Descent, pLo=f(K,G), other by K
                hmm = new HMMProblemPiGK(&param);
                break;
            case STRUCTURE_PIgkww: // Gradient Descent, pLo=f(K,G), other by K
                hmm = new HMMProblemPiGKww(&param);
                break;
            case STRUCTURE_PIAgk: // Gradient Descent, pLo=f(K,G), pT=f(K,G), other by K
                hmm = new HMMProblemPiAGK(&param);
                break;
            case STRUCTURE_Agk: // Gradient Descent, pT=f(K,G), other by K
                hmm = new HMMProblemAGK(&param);
                break;
//                case STRUCTURE_Agki: // Gradient Descent, pT=f(K,G), other by K
//                    hmm = new HMMProblemAGKi(&param);
//                    break;
            case STRUCTURE_PIABgk: // Gradient Descent, pT=f(K,G), other by K
                hmm = new HMMProblemPiABGK(&param);
                break;
                //            case BKT_GD_T: // Gradient Descent with Transfer
                //                hmm = new HMMProblemKT(&param);
                //                break;
            case STRUCTURE_COMP: // Gradient Descent, pT=f(K,G), other by K
                hmm = new HMMProblemComp(&param);
                break;
//             case STRUCTURE_ELOK: // Gradient Descent, pT=f(K,G), other by K
//                 hmm = new HMMProblemEloK(&param);
//                 break;

        }
        tm_fit = clock(); //SEQ
//        _tm_fit = omp_get_wtime(); //PAR
        hmm->fit();
        tm_fit = clock()-tm_fit;//SEQ
//        _tm_fit = omp_get_wtime()-_tm_fit;//PAR
        
        // write model
        hmm->toFile(output_file);
        
        if(param.metrics>0 || param.predictions>0) {
            NUMBER* metrics = Calloc(NUMBER, (size_t)7); // LL, AIC, BIC, RMSE, RMSEnonull, Acc, Acc_nonull;
            // takes care of predictions and metrics, writes predictions if param.predictions==1
            
            // temporary
            if(param.per_kc_rmse_acc) {
                param.kc_counts = Calloc(NDAT, (size_t)param.nK);
                param.kc_rmse = Calloc(NUMBER, (size_t)param.nK);
                param.kc_acc  = Calloc(NUMBER, (size_t)param.nK);
            }

            // NUMBER l1 = hmm->getSumLogPOPara(param.nSeq, param.k_data);
//            printf("hmm-style ll_no_null %15.7f\n",l1);
            
            tm_predict = clock(); //SEQ
//            _tm_predict = omp_get_wtime(); //PAR
//            if(param.structure==STRUCTURE_SKAslc) {
//                ((HMMProblemSlicedA *)hmm)->predict(metrics, predict_file, param.dat_obs, param.dat_group, param.dat_skill, param.dat_skill_stacked, param.dat_skill_rcount, param.dat_skill_rix);
//            } else if(param.structure==STRUCTURE_SKABslc) {
//                ((HMMProblemSlicedAB *)hmm)->predict(metrics, predict_file, param.dat_obs, param.dat_group, param.dat_skill, param.dat_skill_stacked, param.dat_skill_rcount, param.dat_skill_rix);
//            } else {
                HMMProblem::predict(metrics, predict_file, param.dat_obs, param.dat_group, param.dat_skill, param.dat_skill_stacked, param.dat_skill_rcount, param.dat_skill_rix, &hmm, 1, NULL);
//            }
            tm_predict = clock()-tm_predict;//SEQ
//            _tm_predict = omp_get_wtime()-_tm_predict;//PAR
            
            if( param.metrics>0 /*&& !param.quiet*/) {
                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->getNparams() + 2*metrics[0], // AIC
                       hmm->getNparams()*safelog(param.N) + 2*metrics[0], //BIC
                       metrics[2], metrics[3], // rmse's
                       metrics[4], metrics[5]); // acc's
                if(param.duplicate_console==1) fprintf(fid_console, "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->getNparams() + 2*metrics[0], // AIC
                       hmm->getNparams()*safelog(param.N) + 2*metrics[0],
                       metrics[2], metrics[3], // rmse's
                       metrics[4], metrics[5]); // acc's

            }
            free(metrics);

            // temporary
            if(param.per_kc_rmse_acc) {
                for(NCAT i=0; i<param.nK; i++) {
                    printf("KC %4u RMSE=%8.6f Acc=%8.6f\n",i,param.kc_rmse[i],param.kc_acc[i]);
                    if(param.duplicate_console==1) fprintf(fid_console, "KC %4u RMSE=%8.6f Acc=%8.6f\n",i,param.kc_rmse[i],param.kc_acc[i]);
                }
                free(param.kc_counts);
                free(param.kc_rmse);
                free(param.kc_acc);
            }
        
        } // if predict or metrics
        
        delete hmm;
    } else { // cross-validation
        NUMBER* metrics = Calloc(NUMBER, (size_t)7); // AIC, BIC, RMSE, RMSE no null
		NUMBER n_par = 0;
        switch (param.cv_strat) {
            case CV_GROUP:
                n_par = cross_validate(metrics, predict_file, output_file, &tm_fit, &tm_predict, fid_console);//SEQ
//                n_par = cross_validate(metrics, predict_file, output_file, &_tm_fit, &_tm_predict, fid_console);//PAR
                break;
            case CV_ITEM:
                n_par = cross_validate_item(metrics, predict_file, output_file, &tm_fit, &tm_predict, fid_console);//SEQ
//                n_par = cross_validate_item(metrics, predict_file, output_file, &_tm_fit, &_tm_predict, fid_console);//PAR
                break;
            case CV_NSTR:
                n_par = cross_validate_nstrat(metrics, predict_file, output_file, &tm_fit, &tm_predict, fid_console);//SEQ
//                n_par = cross_validate_nstrat(metrics, predict_file, output_file, &_tm_fit, &_tm_predict, fid_console);//PAR
                break;
            default:
                
                break;
        }

		printf("%d-fold cross-validation: LL=%15.7f (%15.7f), AIC=%8.6f, BIC=%8.6f, RMSE=%8.6f (%8.6f), Acc=%8.6f (%8.6f)\n",
			   param.cv_folds,
			   metrics[0], metrics[1], // ll's
			   2*n_par + 2*metrics[0], n_par*safelog(param.N) + 2*metrics[0],
			   metrics[2], metrics[3], // rmse's
			   metrics[4], metrics[5]); // acc's
		if(param.duplicate_console==1) fprintf(fid_console, "%d-fold cross-validation: LL=%15.7f (%15.7f), AIC=%8.6f, BIC=%8.6f, RMSE=%8.6f (%8.6f), Acc=%8.6f (%8.6f)\n",
											   param.cv_folds,
											   metrics[0], metrics[1], // ll's
											   2*n_par + 2*metrics[0], n_par*safelog(param.N) + 2*metrics[0],
											   metrics[2], metrics[3], // rmse's
											   metrics[4], metrics[5]); // acc's
		
		
        free(metrics);
    }
	// free data
	destroy_input_data(&param);
	
//	if(param.quiet == 0) {
        printf("timing: overall %f seconds, read %f, fit %f, predict %f\n",(NUMBER)((clock()-tm_all)/CLOCKS_PER_SEC), (NUMBER)tm_read/CLOCKS_PER_SEC,  (NUMBER)tm_fit/CLOCKS_PER_SEC,  (NUMBER)tm_predict/CLOCKS_PER_SEC);//SEQ
        if(param.duplicate_console==1) fprintf(fid_console, "timing: overall %f seconds, read %f, fit %f, predict %f\n",(NUMBER)((clock()-tm_all)/CLOCKS_PER_SEC), (NUMBER)tm_read/CLOCKS_PER_SEC,  (NUMBER)tm_fit/CLOCKS_PER_SEC,  (NUMBER)tm_predict/CLOCKS_PER_SEC);//SEQ
//        if(param.duplicate_console==1) fprintf(fid_console, "timing: overall %lf sec, read %lf sec, fit %lf sec, predict %lf sec\n",omp_get_wtime()-_tm_all, _tm_read, _tm_fit, _tm_predict);//PAR
//        printf("timing: overall %lf sec, read %lf sec, fit %lf sec, predict %lf sec\n",omp_get_wtime()-_tm_all, _tm_read, _tm_fit, _tm_predict);//PAR
//    }
    
    if(param.duplicate_console==1)
        fclose(fid_console);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
subq $0x11a8, %rsp           # imm = 0x11A8
movl $0x0, -0xc(%rbp)
movl %edi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
callq 0x51a0
movq %rax, -0x20(%rbp)
leaq 0x5b8de(%rip), %rdi     # 0x61358
callq 0xf9d0
movl -0x10(%rbp), %edi
movq -0x18(%rbp), %rsi
leaq -0x420(%rbp), %rdx
leaq -0x820(%rbp), %rcx
leaq -0x1020(%rbp), %r8
leaq -0xc20(%rbp), %r9
callq 0x68a0
movq $0x0, -0x1028(%rbp)
movsbl 0x5b8d3(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x5ad8
leaq -0xc20(%rbp), %rdi
leaq 0x4e73c(%rip), %rsi     # 0x54208
callq 0x53a0
movq %rax, -0x1028(%rbp)
cmpb $0x0, 0x5b8b5(%rip)     # 0x61394
jne 0x5b12
leaq 0x4e722(%rip), %rdi     # 0x5420a
movb $0x0, %al
callq 0x5060
movsbl 0x5b896(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x5b10
movq -0x1028(%rbp), %rdi
leaq 0x4e701(%rip), %rsi     # 0x5420a
movb $0x0, %al
callq 0x5470
jmp 0x5b12
callq 0x51a0
movq %rax, -0x1030(%rbp)
leaq -0x420(%rbp), %rdi
movq -0x1028(%rbp), %rsi
callq 0x7590
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x1034(%rbp)
callq 0x51a0
subq -0x1030(%rbp), %rax
movq %rax, -0x1030(%rbp)
cmpl $0x0, -0x1034(%rbp)
jne 0x5b64
movl $0x0, -0xc(%rbp)
jmp 0x6883
movl -0x10(%rbp), %edi
movq -0x18(%rbp), %rsi
movq -0x1028(%rbp), %rdx
callq 0x86f0
cmpb $0x0, 0x5b816(%rip)     # 0x61394
jne 0x5bf8
movsbl 0x5c08a(%rip), %esi     # 0x61c11
movl 0x5c087(%rip), %edx     # 0x61c14
movl 0x5c085(%rip), %ecx     # 0x61c18
movl 0x5c082(%rip), %r8d     # 0x61c1c
movsbl 0x5c07e(%rip), %r9d     # 0x61c20
leaq 0x4e677(%rip), %rdi     # 0x54220
movb $0x0, %al
callq 0x5060
movsbl 0x5b7d5(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x5bf6
movq -0x1028(%rbp), %rdi
movsbl 0x5c047(%rip), %edx     # 0x61c11
movl 0x5c044(%rip), %ecx     # 0x61c14
movl 0x5c041(%rip), %r8d     # 0x61c18
movl 0x5c03e(%rip), %r9d     # 0x61c1c
movsbl 0x5c03b(%rip), %eax     # 0x61c20
leaq 0x4e634(%rip), %rsi     # 0x54220
movl %eax, (%rsp)
movb $0x0, %al
callq 0x5470
jmp 0x5bf8
leaq 0x5b759(%rip), %rdi     # 0x61358
callq 0x10750
movq $0x0, -0x1040(%rbp)
movq $0x0, -0x1048(%rbp)
movsbl 0x5bba3(%rip), %eax     # 0x617c4
cmpl $0x0, %eax
jne 0x6441
movq $0x0, -0x1050(%rbp)
movsbl 0x5b75a(%rip), %eax     # 0x61396
decl %eax
movl %eax, %ecx
movq %rcx, -0x1088(%rbp)
subl $0xc, %eax
ja 0x5fc4
movq -0x1088(%rbp), %rax
leaq 0x4e3ca(%rip), %rcx     # 0x54028
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x90, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x1090(%rbp)
leaq 0x5b6d3(%rip), %rsi     # 0x61358
callq 0x1e660
jmp 0x5c8c
movq -0x1090(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x1090(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0x90, %esi
callq 0x5310
jmp 0x6890
movl $0xd0, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x1098(%rbp)
leaq 0x5b673(%rip), %rsi     # 0x61358
callq 0x3d840
jmp 0x5cec
movq -0x1098(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x1098(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0xd0, %esi
callq 0x5310
jmp 0x6890
movl $0xa8, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x10a0(%rbp)
leaq 0x5b613(%rip), %rsi     # 0x61358
callq 0x47550
jmp 0x5d4c
movq -0x10a0(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x10a0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0xa8, %esi
callq 0x5310
jmp 0x6890
movl $0x98, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x10a8(%rbp)
leaq 0x5b5b3(%rip), %rsi     # 0x61358
callq 0x2cfa0
jmp 0x5dac
movq -0x10a8(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x10a8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0x98, %esi
callq 0x5310
jmp 0x6890
movl $0xa0, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x10b0(%rbp)
leaq 0x5b553(%rip), %rsi     # 0x61358
callq 0x2fea0
jmp 0x5e0c
movq -0x10b0(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x10b0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0xa0, %esi
callq 0x5310
jmp 0x6890
movl $0xa0, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x10b8(%rbp)
leaq 0x5b4f3(%rip), %rsi     # 0x61358
callq 0x35eb0
jmp 0x5e6c
movq -0x10b8(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x10b8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0xa0, %esi
callq 0x5310
jmp 0x6890
movl $0x98, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x10c0(%rbp)
leaq 0x5b493(%rip), %rsi     # 0x61358
callq 0x32c80
jmp 0x5ecc
movq -0x10c0(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x10c0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0x98, %esi
callq 0x5310
jmp 0x6890
movl $0xa8, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x10c8(%rbp)
leaq 0x5b433(%rip), %rsi     # 0x61358
callq 0x396f0
jmp 0x5f2c
movq -0x10c8(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x10c8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0xa8, %esi
callq 0x5310
jmp 0x6890
movl $0xa0, %edi
callq 0x5300
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x10d0(%rbp)
leaq 0x5b3d3(%rip), %rsi     # 0x61358
callq 0x50660
jmp 0x5f8c
movq -0x10d0(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x5fc4
movq -0x10d0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1058(%rbp)
movl %eax, -0x105c(%rbp)
movl $0xa0, %esi
callq 0x5310
jmp 0x6890
callq 0x51a0
movq %rax, -0x1040(%rbp)
movq -0x1050(%rbp), %rdi
movq (%rdi), %rax
callq *0x48(%rax)
callq 0x51a0
subq -0x1040(%rbp), %rax
movq %rax, -0x1040(%rbp)
movq -0x1050(%rbp), %rdi
leaq -0x820(%rbp), %rsi
movq (%rdi), %rax
callq *0x40(%rax)
cmpl $0x0, 0x5b3a5(%rip)     # 0x613b0
jg 0x601a
cmpl $0x0, 0x5b3a4(%rip)     # 0x613b8
jle 0x641b
movl $0x7, %edi
movl $0x8, %esi
callq 0x5190
movq %rax, -0x1068(%rbp)
testb $0x1, 0x5bca5(%rip)     # 0x61cdc
je 0x6081
movslq 0x5bbd8(%rip), %rdi     # 0x61c18
movl $0x4, %esi
callq 0x5190
movq %rax, 0x5bc9f(%rip)     # 0x61cf0
movslq 0x5bbc0(%rip), %rdi     # 0x61c18
movl $0x8, %esi
callq 0x5190
movq %rax, 0x5bc77(%rip)     # 0x61ce0
movslq 0x5bba8(%rip), %rdi     # 0x61c18
movl $0x8, %esi
callq 0x5190
movq %rax, 0x5bc67(%rip)     # 0x61ce8
callq 0x51a0
movq %rax, -0x1048(%rbp)
movq -0x1068(%rbp), %rdi
leaq -0x1020(%rbp), %rsi
movq 0x5bb26(%rip), %rdx     # 0x61bc8
movq 0x5bb27(%rip), %rcx     # 0x61bd0
movq 0x5bb28(%rip), %r8      # 0x61bd8
movq 0x5bb29(%rip), %r9      # 0x61be0
movq 0x5bb2a(%rip), %r11     # 0x61be8
movq 0x5bb2b(%rip), %r10     # 0x61bf0
leaq -0x1050(%rbp), %rax
xorl %ebx, %ebx
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
movl $0x1, 0x18(%rsp)
movq $0x0, 0x20(%rsp)
callq 0x224d0
callq 0x51a0
subq -0x1048(%rbp), %rax
movq %rax, -0x1048(%rbp)
cmpl $0x0, 0x5b2a4(%rip)     # 0x613b0
jle 0x6323
movq -0x1068(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x10d8(%rbp)
movq -0x1068(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x10e8(%rbp)
movq -0x1050(%rbp), %rdi
callq 0x23820
shll %eax
cvtsi2sd %eax, %xmm1
movq -0x1068(%rbp), %rax
movsd (%rax), %xmm0
addsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x10e0(%rbp)
movq -0x1050(%rbp), %rdi
callq 0x23820
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x10f0(%rbp)
cvtsi2sdl 0x5ba82(%rip), %xmm0 # 0x61c08
callq 0xe2e0
movsd -0x10f0(%rbp), %xmm3
movsd -0x10e8(%rbp), %xmm1
movsd -0x10e0(%rbp), %xmm2
movaps %xmm0, %xmm5
movsd -0x10d8(%rbp), %xmm0
movq -0x1068(%rbp), %rax
movsd 0x4de4b(%rip), %xmm4    # 0x54008
mulsd (%rax), %xmm4
mulsd %xmm5, %xmm3
addsd %xmm4, %xmm3
movq -0x1068(%rbp), %rax
movsd 0x10(%rax), %xmm4
movq -0x1068(%rbp), %rax
movsd 0x18(%rax), %xmm5
movq -0x1068(%rbp), %rax
movsd 0x20(%rax), %xmm6
movq -0x1068(%rbp), %rax
movsd 0x28(%rax), %xmm7
leaq 0x4e04f(%rip), %rdi     # 0x5424f
movb $0x8, %al
callq 0x5060
movsbl 0x5b17e(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x6321
movq -0x1028(%rbp), %rax
movq %rax, -0x1110(%rbp)
movq -0x1068(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x10f8(%rbp)
movq -0x1068(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x1108(%rbp)
movq -0x1050(%rbp), %rdi
callq 0x23820
shll %eax
cvtsi2sd %eax, %xmm1
movq -0x1068(%rbp), %rax
movsd (%rax), %xmm0
addsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x1100(%rbp)
movq -0x1050(%rbp), %rdi
callq 0x23820
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x1118(%rbp)
cvtsi2sdl 0x5b96f(%rip), %xmm0 # 0x61c08
callq 0xe2e0
movsd -0x1118(%rbp), %xmm3
movq -0x1110(%rbp), %rdi
movsd -0x1108(%rbp), %xmm1
movsd -0x1100(%rbp), %xmm2
movaps %xmm0, %xmm5
movsd -0x10f8(%rbp), %xmm0
movq -0x1068(%rbp), %rax
movsd 0x4dd31(%rip), %xmm4    # 0x54008
mulsd (%rax), %xmm4
mulsd %xmm5, %xmm3
addsd %xmm4, %xmm3
movq -0x1068(%rbp), %rax
movsd 0x10(%rax), %xmm4
movq -0x1068(%rbp), %rax
movsd 0x18(%rax), %xmm5
movq -0x1068(%rbp), %rax
movsd 0x20(%rax), %xmm6
movq -0x1068(%rbp), %rax
movsd 0x28(%rax), %xmm7
leaq 0x4df35(%rip), %rsi     # 0x5424f
movb $0x8, %al
callq 0x5470
jmp 0x6323
movq -0x1068(%rbp), %rdi
callq 0x53b0
testb $0x1, 0x5b9a6(%rip)     # 0x61cdc
je 0x6419
movl $0x0, -0x106c(%rbp)
movl -0x106c(%rbp), %eax
cmpl 0x5b8c6(%rip), %eax     # 0x61c18
jge 0x63f5
movl -0x106c(%rbp), %esi
movq 0x5b97b(%rip), %rax     # 0x61ce0
movslq -0x106c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x5b970(%rip), %rax     # 0x61ce8
movslq -0x106c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
leaq 0x4df23(%rip), %rdi     # 0x542ae
movb $0x2, %al
callq 0x5060
movsbl 0x5aff3(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x63df
movq -0x1028(%rbp), %rdi
movl -0x106c(%rbp), %edx
movq 0x5b92e(%rip), %rax     # 0x61ce0
movslq -0x106c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x5b923(%rip), %rax     # 0x61ce8
movslq -0x106c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
leaq 0x4ded6(%rip), %rsi     # 0x542ae
movb $0x2, %al
callq 0x5470
jmp 0x63e1
movl -0x106c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x106c(%rbp)
jmp 0x6346
movq 0x5b8f4(%rip), %rdi     # 0x61cf0
callq 0x53b0
movq 0x5b8d8(%rip), %rdi     # 0x61ce0
callq 0x53b0
movq 0x5b8d4(%rip), %rdi     # 0x61ce8
callq 0x53b0
jmp 0x641b
movq -0x1050(%rbp), %rax
movq %rax, -0x1120(%rbp)
cmpq $0x0, %rax
je 0x643c
movq -0x1120(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
jmp 0x676d
movl $0x7, %edi
movl $0x8, %esi
callq 0x5190
movq %rax, -0x1078(%rbp)
movq $0x0, -0x1080(%rbp)
movsbl 0x5b35c(%rip), %eax     # 0x617c5
movl %eax, -0x1124(%rbp)
subl $0x67, %eax
je 0x6493
jmp 0x6476
movl -0x1124(%rbp), %eax
subl $0x69, %eax
je 0x64cc
jmp 0x6483
movl -0x1124(%rbp), %eax
subl $0x6e, %eax
je 0x6505
jmp 0x653e
movq -0x1078(%rbp), %rdi
leaq -0x1020(%rbp), %rsi
leaq -0x820(%rbp), %rdx
movq -0x1028(%rbp), %r9
leaq -0x1040(%rbp), %rcx
leaq -0x1048(%rbp), %r8
callq 0x9420
movsd %xmm0, -0x1080(%rbp)
jmp 0x6540
movq -0x1078(%rbp), %rdi
leaq -0x1020(%rbp), %rsi
leaq -0x820(%rbp), %rdx
movq -0x1028(%rbp), %r9
leaq -0x1040(%rbp), %rcx
leaq -0x1048(%rbp), %r8
callq 0x9fc0
movsd %xmm0, -0x1080(%rbp)
jmp 0x6540
movq -0x1078(%rbp), %rdi
leaq -0x1020(%rbp), %rsi
leaq -0x820(%rbp), %rdx
movq -0x1028(%rbp), %r9
leaq -0x1040(%rbp), %rcx
leaq -0x1048(%rbp), %r8
callq 0xaaa0
movsd %xmm0, -0x1080(%rbp)
jmp 0x6540
jmp 0x6540
movsbl 0x5b27d(%rip), %eax     # 0x617c4
movl %eax, -0x1144(%rbp)
movq -0x1078(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x1130(%rbp)
movq -0x1078(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x1140(%rbp)
movsd -0x1080(%rbp), %xmm0
movq -0x1078(%rbp), %rax
movsd 0x4da7d(%rip), %xmm1    # 0x54008
mulsd (%rax), %xmm1
addsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x1138(%rbp)
movsd -0x1080(%rbp), %xmm0
movsd %xmm0, -0x1150(%rbp)
cvtsi2sdl 0x5b651(%rip), %xmm0 # 0x61c08
callq 0xe2e0
movsd -0x1150(%rbp), %xmm3
movl -0x1144(%rbp), %esi
movsd -0x1140(%rbp), %xmm1
movsd -0x1138(%rbp), %xmm2
movaps %xmm0, %xmm5
movsd -0x1130(%rbp), %xmm0
movq -0x1078(%rbp), %rax
movsd 0x4da14(%rip), %xmm4    # 0x54008
mulsd (%rax), %xmm4
mulsd %xmm5, %xmm3
addsd %xmm4, %xmm3
movq -0x1078(%rbp), %rax
movsd 0x10(%rax), %xmm4
movq -0x1078(%rbp), %rax
movsd 0x18(%rax), %xmm5
movq -0x1078(%rbp), %rax
movsd 0x20(%rax), %xmm6
movq -0x1078(%rbp), %rax
movsd 0x28(%rax), %xmm7
leaq 0x4dc94(%rip), %rdi     # 0x542cb
movb $0x8, %al
callq 0x5060
movsbl 0x5ad47(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x6761
movq -0x1028(%rbp), %rax
movq %rax, -0x1178(%rbp)
movsbl 0x5b161(%rip), %eax     # 0x617c4
movl %eax, -0x116c(%rbp)
movq -0x1078(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x1158(%rbp)
movq -0x1078(%rbp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x1168(%rbp)
movsd -0x1080(%rbp), %xmm0
movq -0x1078(%rbp), %rax
movsd 0x4d961(%rip), %xmm1    # 0x54008
mulsd (%rax), %xmm1
addsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x1160(%rbp)
movsd -0x1080(%rbp), %xmm0
movsd %xmm0, -0x1180(%rbp)
cvtsi2sdl 0x5b535(%rip), %xmm0 # 0x61c08
callq 0xe2e0
movsd -0x1180(%rbp), %xmm3
movq -0x1178(%rbp), %rdi
movl -0x116c(%rbp), %edx
movsd -0x1168(%rbp), %xmm1
movsd -0x1160(%rbp), %xmm2
movaps %xmm0, %xmm5
movsd -0x1158(%rbp), %xmm0
movq -0x1078(%rbp), %rax
movsd 0x4d8f1(%rip), %xmm4    # 0x54008
mulsd (%rax), %xmm4
mulsd %xmm5, %xmm3
addsd %xmm4, %xmm3
movq -0x1078(%rbp), %rax
movsd 0x10(%rax), %xmm4
movq -0x1078(%rbp), %rax
movsd 0x18(%rax), %xmm5
movq -0x1078(%rbp), %rax
movsd 0x20(%rax), %xmm6
movq -0x1078(%rbp), %rax
movsd 0x28(%rax), %xmm7
leaq 0x4db71(%rip), %rsi     # 0x542cb
movb $0x8, %al
callq 0x5470
movq -0x1078(%rbp), %rdi
callq 0x53b0
leaq 0x5abe4(%rip), %rdi     # 0x61358
callq 0x10030
callq 0x51a0
subq -0x20(%rbp), %rax
movl $0xf4240, %ecx          # imm = 0xF4240
cqto
idivq %rcx
cvtsi2sd %rax, %xmm0
cvtsi2sdq -0x1030(%rbp), %xmm1
movsd 0x4d86e(%rip), %xmm2    # 0x54010
divsd %xmm2, %xmm1
cvtsi2sdq -0x1040(%rbp), %xmm2
movsd 0x4d859(%rip), %xmm3    # 0x54010
divsd %xmm3, %xmm2
cvtsi2sdq -0x1048(%rbp), %xmm3
movsd 0x4d844(%rip), %xmm4    # 0x54010
divsd %xmm4, %xmm3
leaq 0x4db5f(%rip), %rdi     # 0x54336
movb $0x4, %al
callq 0x5060
movsbl 0x5aba7(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x6864
movq -0x1028(%rbp), %rax
movq %rax, -0x1188(%rbp)
callq 0x51a0
movq -0x1188(%rbp), %rdi
subq -0x20(%rbp), %rax
movl $0xf4240, %ecx          # imm = 0xF4240
cqto
idivq %rcx
cvtsi2sd %rax, %xmm0
cvtsi2sdq -0x1030(%rbp), %xmm1
movsd 0x4d7e8(%rip), %xmm2    # 0x54010
divsd %xmm2, %xmm1
cvtsi2sdq -0x1040(%rbp), %xmm2
movsd 0x4d7d3(%rip), %xmm3    # 0x54010
divsd %xmm3, %xmm2
cvtsi2sdq -0x1048(%rbp), %xmm3
movsd 0x4d7be(%rip), %xmm4    # 0x54010
divsd %xmm4, %xmm3
leaq 0x4dad9(%rip), %rsi     # 0x54336
movb $0x4, %al
callq 0x5470
movsbl 0x5ab21(%rip), %eax     # 0x6138c
cmpl $0x1, %eax
jne 0x687c
movq -0x1028(%rbp), %rdi
callq 0x52f0
movl $0x0, -0xc(%rbp)
movl -0xc(%rbp), %eax
addq $0x11a8, %rsp           # imm = 0x11A8
popq %rbx
popq %rbp
retq
movq -0x1058(%rbp), %rdi
callq 0x5570
nopl (%rax)