// File: /workspace/github_cpp_makefile_star2_O2/bobverity[P]MavericK/readIn.cpp
// Function: checkOptions(globals&)
void checkOptions(globals &globals) {
    
    /*
     The following checks are carried out (in this order):
     - fixLabels_on=true if producing any Qmatrix output
     - popCol_on=true if producing Qmatrix_pop files
     - admix_on=true if
        - producing Qmatrix_gene files
        - producing ML admixture freqs
     - outputQmatrix_?_on=true if outputQmatrixError_?_on=true
     - mainRepeats>1 if producing QmatrixError files
     - EMalgorithm_on=true if
        - producing model comp stats
        - producing ML output
     - (Kmax-Kmin)>=2 and mainRepeats>1 if outputEvanno_on=true
     - if using exhaustive approach, check that number of partitions required to sum over is reasonable. Otherwise throw warning
     - ensure that alpha and alphaPropSD vectors are of length 1 or (Kmax-Kmin+1). If former then duplicate value as needed.
     */
    
    // force fixLabels_on=true if producing any Qmatrix output
    if (!globals.fixLabels_on && (globals.outputQmatrix_ind_on || globals.outputQmatrix_pop_on || globals.outputQmatrix_gene_on)) {
        cerrAndLog("\nError: the label switching problem must be solved in order to produce Qmatrix output. Either set fixLabels_on to true, or turn off all Qmatrix output.\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force popCol_on=true if producing Qmatrix_pop files
    if (!globals.popCol_on && globals.outputQmatrix_pop_on) {
        cerrAndLog("\nError: unable to produce population level Qmatrix, as population data not currently being used. Either read in population data (by setting popCol_on to true), or stop producing population level Qmatrix output (by setting outputQmatrix_pop_on to false and outputQmatrixError_pop_on to false).\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force admix_on=true if producing Qmatrix_gene files
    if (!globals.admix_on && globals.outputQmatrix_gene_on) {
        cerrAndLog("\nError: admixture model must be turned on in order to produce gene level Qmatrix. Either switch to the admixture model (by setting admix_on to true) or stop producing gene level Qmatrix output (by setting outputQmatrix_gene_on and outputQmatrixError_gene_on to false).\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force admix_on=true if producing maximum likelihood admixture frequencies
    if (!globals.admix_on && globals.outputMaxLike_admixFreqs_on) {
        cerrAndLog("\nError: admixture model must be turned on in order to produce maximum likelihood admixture frequency output. Either switch to the admixture model (by setting admix_on to true) or stop producing maximum likelihood admixture frequency output (by setting outputMaxLike_admixFreqs_on to false).\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force outputQmatrix_?_on=true if outputQmatrixError_?_on=true for all Qmatrix types
    if ((globals.outputQmatrixError_ind_on && !globals.outputQmatrix_ind_on) || (globals.outputQmatrixError_pop_on && !globals.outputQmatrix_pop_on) || (globals.outputQmatrixError_gene_on && !globals.outputQmatrix_gene_on)) {
        cerrAndLog("\nError: if outputQmatrixError options are turned on then the corresponding outputQmatrix options must also be turned on.\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force mainRepeats>1 if outputQmatrixError_?_on=true for all Qmatrix types
    if (globals.mainRepeats==1 && (globals.outputQmatrixError_ind_on || globals.outputQmatrixError_pop_on || globals.outputQmatrixError_gene_on)) {
        cerrAndLog("\nError: mainRepeats must be greater than 1 when any outputQmatrixError options are turned on.\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force EMalgorithm_on=true if producing model comparison statistics
    if (!globals.EMalgorithm_on && globals.outputComparisonStatistics_on) {
        cerrAndLog("\nError: EM algorithm must be turned on in order to compute model comparison statistics. Either turn on the EM algorithm (by setting EMalgorithm_on to true) or stop producing model comparison statistics (by setting outputComparisonStatistics_on to false).\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force EMalgorithm_on=true if producing maximum likelihood output
    if (!globals.EMalgorithm_on && (globals.outputMaxLike_alleleFreqs_on || globals.outputMaxLike_admixFreqs_on)) {
        cerrAndLog("\nError: EM algorithm must be turned on in order to produce maximum likelihood output files. Either turn on the EM algorithm (by setting EMalgorithm_on to true) or stop producing maximum likelihood output (by setting outputMaxLike_alleleFreqs_on and outputMaxLike_admixFreqs_on to false).\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // force (Kmax-Kmin)>=2 and mainRepeats>1 if outputEvanno_on=true
    if ((globals.Kmax-globals.Kmin)<2 && globals.outputEvanno_on) {
        cerrAndLog("\nError: Kmax must be at least 2 greater than Kmin when calculating Evanno's delta K.\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    if (globals.mainRepeats==1 && globals.outputEvanno_on) {
        cerrAndLog("\nError: mainRepeats must be greater than 1 when calculating Evanno's delta K.\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    // if using exhaustive approach, check that number of partitions required to sum over is reasonable. Otherwise throw warning
    if (globals.exhaustive_on && !globals.suppressWarning1_on) {
        
        // calculate number of partitions. Number of ways of splitting n elements into i groups is given by the Stirling number of the second kind {n, i}. Number of ways of splitting n elements into UP TO K groups is given by sum_{i=1}^k {n, i}. Calculate this for all K that will be explored under current settings. The total number of partitions (in log space) is given by log_partitions.
        double log_partitions = log(double(0));
        for (int K=globals.Kmin; K<=globals.Kmax; K++) {
            vector<double> StirlingNumbers = globals.admix_on ? StirlingSecond(sum(globals.ploidy_vec)*globals.loci) : StirlingSecond(globals.n);
            for (int i=0; (i<K) & (i<int(StirlingNumbers.size())); i++) {
                log_partitions = logSum(log_partitions,StirlingNumbers[i]);
            }
        }
        
        // if very large then error
        if (log_partitions>180) {
            cerrAndLog("\nWarning: for this combination of data and parameters the number of partitions explored in the exhaustive approach is greater than the number of protons in the observable universe, and the program is unlikely to finish within your lifetime. Either turn off the exhaustive approach, or to override this warning and continue with the analysis insert the optional parameter \"suppressWarning1_on\" with value \"true\" in the parameters file.\n", globals.outputLog_on, globals.outputLog_fileStream);
            exit(1);
        }
        if (log_partitions>log(double(1e7))) {
            cerrAndLog("\nWarning: for this combination of data and parameters the number of partitions explored in the exhaustive approach is extremely large (greater than 1e7 in total), and the program may take a very long time to execute. Either turn off the exhaustive approach, or to override this warning and continue with the analysis insert the optional parameter \"suppressWarning1_on\" with value \"true\" in the parameters file.\n", globals.outputLog_on, globals.outputLog_fileStream);
            exit(1);
        }
        
    }
    
    // ensure that alpha and alphaPropSD vectors are of length 1 or (Kmax-Kmin+1). If former then duplicate value as needed.
    if (int(globals.alpha.size())==1) {
        globals.alpha = vector<double>(globals.Kmax-globals.Kmin+1, globals.alpha[0]);
    } else if (int(globals.alpha.size())!=(globals.Kmax-globals.Kmin+1)) {
        cerrAndLog("\nWarning: alpha must contain either a single value to apply to all K, or a comma-separated list of values of length (Kmax-Kmin+1) to apply to each K individually.\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
    if (int(globals.alphaPropSD.size())==1) {
        globals.alphaPropSD = vector<double>(globals.Kmax-globals.Kmin+1, globals.alphaPropSD[0]);
    } else if (int(globals.alphaPropSD.size())!=(globals.Kmax-globals.Kmin+1)) {
        cerrAndLog("\nWarning: alphaPropSD must contain either a single value to apply to all K, or a comma-separated list of values of length (Kmax-Kmin+1).\n", globals.outputLog_on, globals.outputLog_fileStream);
        exit(1);
    }
    
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1f0, %rsp            # imm = 0x1F0
movq %rdi, %rbx
cmpb $0x0, 0x2c4f(%rdi)
jne 0x2110a
cmpb $0x0, 0x2c3e(%rbx)
jne 0x213e8
cmpb $0x0, 0x2c3f(%rbx)
jne 0x213e8
cmpb $0x1, 0x2c40(%rbx)
je 0x213e8
cmpb $0x0, 0x2ba1(%rbx)
jne 0x21120
cmpb $0x1, 0x2c3f(%rbx)
je 0x214f8
cmpb $0x0, 0x2bd0(%rbx)
jne 0x21143
cmpb $0x1, 0x2c40(%rbx)
je 0x2153c
cmpb $0x1, 0x2c4c(%rbx)
je 0x21580
movb 0x2c41(%rbx), %al
cmpb $0x1, %al
jne 0x2115a
cmpb $0x1, 0x2c3e(%rbx)
jne 0x2142c
movb 0x2c42(%rbx), %dl
cmpb $0x1, %dl
jne 0x21172
cmpb $0x1, 0x2c3f(%rbx)
jne 0x2142c
movb 0x2c43(%rbx), %sil
cmpb $0x1, %sil
jne 0x2118c
cmpb $0x0, 0x2c40(%rbx)
je 0x2142c
movl 0x2c0c(%rbx), %ecx
cmpl $0x1, %ecx
setne %dil
orb %dl, %al
orb %sil, %al
xorb $0x1, %al
orb %dil, %al
je 0x21470
cmpb $0x0, 0x2c30(%rbx)
jne 0x211d9
cmpb $0x1, 0x2c49(%rbx)
je 0x215c4
cmpb $0x0, 0x2c4b(%rbx)
jne 0x214b4
cmpb $0x1, 0x2c4c(%rbx)
je 0x214b4
movl 0x2bcc(%rbx), %eax
movl %eax, %edx
subl 0x2bc8(%rbx), %edx
cmpl $0x1, %edx
jg 0x211f9
cmpb $0x1, 0x2c4a(%rbx)
je 0x21608
cmpl $0x1, %ecx
jne 0x2120b
cmpb $0x1, 0x2c4a(%rbx)
je 0x2164c
cmpb $0x1, 0x2c08(%rbx)
jne 0x212f0
cmpb $0x0, 0x2c4e(%rbx)
jne 0x212f0
xorpd %xmm0, %xmm0
callq 0x32d0
movslq 0x2bc8(%rbx), %r12
leaq 0x2cd0(%rbx), %r14
leaq 0x10(%rsp), %r15
movslq 0x2bcc(%rbx), %rax
cmpq %rax, %r12
jg 0x212d4
cmpb $0x1, 0x2bd0(%rbx)
movsd %xmm0, 0x28(%rsp)
jne 0x21273
movq %r14, %rdi
callq 0x50fb
movl %eax, %esi
imull 0x2d1c(%rbx), %esi
jmp 0x21279
movl 0x2d18(%rbx), %esi
movq %r15, %rdi
callq 0x15420
xorl %r13d, %r13d
movsd 0x28(%rsp), %xmm0
cmpq %r12, %r13
jge 0x212b8
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rcx
subq %rax, %rcx
shrq $0x3, %rcx
movslq %ecx, %rcx
cmpq %rcx, %r13
jge 0x212b8
movsd (%rax,%r13,8), %xmm1
callq 0x14ce5
incq %r13
jmp 0x2128a
movq %r15, %rdi
movsd %xmm0, 0x28(%rsp)
callq 0x51a2
movsd 0x28(%rsp), %xmm0
incq %r12
jmp 0x21241
ucomisd 0x6b8c(%rip), %xmm0     # 0x27e68
ja 0x21703
ucomisd 0x6b86(%rip), %xmm0     # 0x27e70
ja 0x21744
movabsq $0x7fffffff8, %r12      # imm = 0x7FFFFFFF8
movq 0x2bd8(%rbx), %rdx
movq 0x2be0(%rbx), %rcx
subq %rdx, %rcx
movq %rcx, %rsi
andq %r12, %rsi
cmpq $0x8, %rsi
jne 0x21350
leaq 0x2bd8(%rbx), %r14
subl 0x2bc8(%rbx), %eax
incl %eax
movslq %eax, %rsi
leaq 0x10(%rsp), %r15
leaq 0xf(%rsp), %rcx
movq %r15, %rdi
callq 0x5120
movq %r14, %rdi
movq %r15, %rsi
callq 0x55b8
movq %r15, %rdi
callq 0x51a2
jmp 0x21364
shrq $0x3, %rcx
subl 0x2bc8(%rbx), %eax
incl %eax
cmpl %ecx, %eax
jne 0x21690
movq 0x2bf0(%rbx), %rdx
movq 0x2bf8(%rbx), %rax
subq %rdx, %rax
andq %rax, %r12
cmpq $0x8, %r12
jne 0x213bd
leaq 0x2bf0(%rbx), %r14
movl 0x2bcc(%rbx), %eax
subl 0x2bc8(%rbx), %eax
incl %eax
movslq %eax, %rsi
leaq 0x10(%rsp), %rbx
leaq 0xf(%rsp), %rcx
movq %rbx, %rdi
callq 0x5120
movq %r14, %rdi
movq %rbx, %rsi
callq 0x55b8
movq %rbx, %rdi
callq 0x51a2
jmp 0x213d7
shrq $0x3, %rax
movl 0x2bcc(%rbx), %ecx
subl 0x2bc8(%rbx), %ecx
incl %ecx
cmpl %eax, %ecx
jne 0x216cb
addq $0x1f0, %rsp            # imm = 0x1F0
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0x76b5(%rip), %rsi      # 0x28aa4
leaq 0x1d0(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x1d0(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x1d0(%rsp), %rdi
jmp 0x2177a
leaq 0x7a62(%rip), %rsi      # 0x28e95
leaq 0x150(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x150(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x150(%rsp), %rdi
jmp 0x2177a
leaq 0x7a98(%rip), %rsi      # 0x28f0f
leaq 0x130(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x130(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x130(%rsp), %rdi
jmp 0x2177a
leaq 0x7bb3(%rip), %rsi      # 0x2906e
leaq 0xf0(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0xf0(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0xf0(%rsp), %rdi
jmp 0x2177a
leaq 0x763e(%rip), %rsi      # 0x28b3d
leaq 0x1b0(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x1b0(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x1b0(%rsp), %rdi
jmp 0x2177a
leaq 0x7720(%rip), %rsi      # 0x28c63
leaq 0x190(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x190(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x190(%rsp), %rdi
jmp 0x2177a
leaq 0x77ea(%rip), %rsi      # 0x28d71
leaq 0x170(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x170(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x170(%rsp), %rdi
jmp 0x2177a
leaq 0x79a3(%rip), %rsi      # 0x28f6e
leaq 0x110(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x110(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x110(%rsp), %rdi
jmp 0x2177a
leaq 0x7b80(%rip), %rsi      # 0x2918f
leaq 0xd0(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0xd0(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0xd0(%rsp), %rdi
jmp 0x2177a
leaq 0x7b92(%rip), %rsi      # 0x291e5
leaq 0xb0(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0xb0(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0xb0(%rsp), %rdi
jmp 0x2177a
leaq 0x7eed(%rip), %rsi      # 0x29584
leaq 0x50(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x50(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x50(%rsp), %rdi
jmp 0x2177a
leaq 0x7f56(%rip), %rsi      # 0x29628
leaq 0x30(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x30(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x30(%rsp), %rdi
jmp 0x2177a
leaq 0x7b2a(%rip), %rsi      # 0x29234
leaq 0x90(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x90(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x90(%rsp), %rdi
jmp 0x2177a
leaq 0x7c9d(%rip), %rsi      # 0x293e8
leaq 0x70(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x3130
movzbl 0x2c3c(%rbx), %esi
addq $0x970, %rbx            # imm = 0x970
leaq 0x70(%rsp), %rdi
movq %rbx, %rdx
callq 0x176c7
leaq 0x70(%rsp), %rdi
callq 0x3170
pushq $0x1
popq %rdi
callq 0x33e0
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0x90(%rsp), %rdi
jmp 0x2185b
jmp 0x21868
jmp 0x21868
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0xb0(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0xd0(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0x110(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0x170(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0x190(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0x1b0(%rsp), %rdi
jmp 0x2185b
jmp 0x21868
jmp 0x21868
jmp 0x21868
jmp 0x21868
movq %rax, %rbx
leaq 0xf0(%rsp), %rdi
jmp 0x2185b
jmp 0x21868
movq %rax, %rbx
leaq 0x130(%rsp), %rdi
jmp 0x2185b
jmp 0x21868
jmp 0x21868
jmp 0x21868
movq %rax, %rbx
leaq 0x150(%rsp), %rdi
jmp 0x2185b
movq %rax, %rbx
leaq 0x1d0(%rsp), %rdi
callq 0x3170
jmp 0x2187a
jmp 0x21868
jmp 0x21868
jmp 0x21868
movq %rax, %rbx
jmp 0x2187a
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x51a2
movq %rbx, %rdi
callq 0x35a0