// File: brc7[P]DiversitySampling/targets/samplerace.cpp
// Function: main
int main(int argc, char **argv){

    if (argc < 4){
        std::clog<<"Usage: "<<std::endl; 
        std::clog<<"samplerace <tau> <format> <input> <output>"; 
        std::clog<<" [--range race_range] [--reps race_reps] [--hashes n_minhashes] [-k kmer_size]"<<std::endl; 
        std::clog<<"Positional arguments: "<<std::endl; 
        std::clog<<"tau: floating point RACE sampling threshold. Roughly determines how many samples you will store. You may specify this in scientific notation (i.e. 10e-6)"<<std::endl; 
        std::clog<<"format: Either PE, SE, or I for paired-end, single-end, and interleaved paired reads"<<std::endl; 
        std::clog<<"input: path to input data file (.fastq or .fasta extension). For PE format, specify two files."<<std::endl; 
        std::clog<<"output: path to output sample file (same extension as input). For PE format, specify two files."<<std::endl; 
        
        std::clog<<"Optional arguments: "<<std::endl; 
        std::clog<<"[--range race_range]: (Optional, default 10000) Hash range for each ACE (B)"<<std::endl;
        std::clog<<"[--reps race_reps]: (Optional, default 10) Number of ACE repetitions (R)"<<std::endl;
        std::clog<<"[--hashes n_minhashes]: (Optional, default 1) Number of MinHashes for each ACE (n)"<<std::endl;
        std::clog<<"[--k kmer_size]: (Optional, default 16) Size of each MinHash k-mer (k)"<<std::endl;

        std::clog<<std::endl<<"Example usage:"<<std::endl; 
        std::clog<<"samplerace 15.0 PE data/input-1.fastq data/input-2.fastq data/output-1.fastq data/output-2.fastq --range 100 --reps 50 --hashes 3 --k 5"<<std::endl; 
        std::clog<<"samplerace 10e-6 SE data/input.fastq data/output.fastq --range 100 --reps 5 --hashes 1 --k 33"<<std::endl; 
        std::clog<<"samplerace 0.1 SE data/input.fasta data/output.fasta --range 100000 --k 20"<<std::endl; 
        return -1; 
    }


    // POSITIONAL ARGUMENTS
    double tau = std::stod(argv[1]);
    int format; // ENUM: 1 = unpaired, 2 = interleaved, 3 = paired
    if (std::strcmp("SE",argv[2]) == 0){
        format = 1;
    } else if (std::strcmp("I",argv[2]) == 0){
        format = 2; 
    } else if (std::strcmp("PE",argv[2]) == 0){
        format = 3; 
        if (argc < 7){
            std::cerr<<"For paired-end reads, please specify the input and output files as:"<<std::endl; 
            std::cerr<<"input1.fastq input2.fastq output1.fastq output2.fastq"<<std::endl; 
            return -1; 
        }
    } else {
        std::cerr<<"Invalid format, please specify either SE, PE, or I"<<std::endl; 
        return -1;
    }

    // open the correct file streams given the format
    std::ifstream datastream1;
    std::ofstream samplestream1;
    std::ifstream datastream2;
    std::ofstream samplestream2;

    if (format != 3){
        datastream1.open(argv[3]);
        samplestream1.open(argv[4]);
    } else {
        datastream1.open(argv[3]);
        datastream2.open(argv[4]);
        samplestream1.open(argv[5]);
        samplestream2.open(argv[6]);
    }

    // determine file extension
    std::string filename(argv[3]); 
    std::string file_extension = "";
    size_t idx = filename.rfind('.',filename.length()); 
    if (file_extension == "fq"){
        file_extension = "fastq"; 
    }
    if (idx != std::string::npos){
        file_extension = filename.substr(idx+1, filename.length() - idx); 
    } else {
        std::cerr<<"Input file does not appear to have any file extension."<<std::endl; 
        return -1; 
    }
    if (file_extension != "fasta" && file_extension != "fastq"){
        std::cerr<<"Unknown file extension: "<<file_extension<<std::endl; 
        std::cerr<<"Please specify either a file with the .fasta or .fastq extension."<<std::endl; 
        return -1; 
    }

    // OPTIONAL ARGUMENTS
    int race_range = 10000;
    int race_repetitions = 10;
    int hash_power = 1;
    int kmer_k = 16;

    for (int i = 0; i < argc; ++i){
        if (std::strcmp("--range",argv[i]) == 0){
            if ((i+1) < argc){
                race_range = std::stoi(argv[i+1]);
            } else {
                std::cerr<<"Invalid argument for optional parameter --range"<<std::endl; 
                return -1;
            }
        }
        if (std::strcmp("--reps",argv[i]) == 0){
            if ((i+1) < argc){
                race_repetitions = std::stoi(argv[i+1]);
            } else {
                std::cerr<<"Invalid argument for optional parameter --reps"<<std::endl; 
                return -1;
            }
        }
        if (std::strcmp("--hashes",argv[i]) == 0){
            if ((i+1) < argc){
                hash_power = std::stoi(argv[i+1]);
            } else {
                std::cerr<<"Invalid argument for optional parameter --hashes"<<std::endl; 
                return -1;
            }
        }
        if (std::strcmp("--k",argv[i]) == 0){
            if ((i+1) < argc){
                kmer_k = std::stoi(argv[i+1]);
            } else {
                std::cerr<<"Invalid argument for optional parameter --k"<<std::endl; 
                return -1;
            }
        }
    }

    // Check if arguments are valid
    if (tau <= 0){ std::cerr<<"Invalid value for parameter <tau>"<<std::endl; return -1; }
    if (race_range <= 0){ std::cerr<<"Invalid value for optional parameter --range"<<std::endl; return -1; }
    if (race_repetitions <= 0){ std::cerr<<"Invalid value for optional parameter --reps"<<std::endl; return -1; }
    if (hash_power <= 0){ std::cerr<<"Invalid value for optional parameter --hashes"<<std::endl; return -1; }
    if (kmer_k <= 0){ std::cerr<<"Invalid value for optional parameter --k"<<std::endl; return -1; }

    // done parsing information. Begin RACE algorithm: 

    // buffer for sequences and fasta/fastq chunks
    std::string sequence;
    std::string chunk1;
    std::string chunk2;

    // set up the hash function that will be used to hash input sequences
    SequenceMinHash hash = SequenceMinHash(race_repetitions*hash_power);
    int* raw_hashes = new int[race_repetitions*hash_power]; 
    int* rehashes = new int[race_repetitions];

    RACE sketch = RACE(race_repetitions,race_range); 

    do{
        bool success = false; 
        int c = datastream1.peek(); 
        if (c == EOF) {
            if (datastream1.eof()){
                continue; 
            }
        }

        switch(format){
            case 1: // 1 = unpaired
            success = SequenceFeaturesSE(datastream1, sequence, chunk1, file_extension);
            break; 
            case 2: // 2 = interleaved
            success = SequenceFeaturesI(datastream1, sequence, chunk1, file_extension); 
            break; 
            case 3: // 3 = paired
            success = SequenceFeaturesPE(datastream1, datastream2, sequence, chunk1, chunk2, file_extension);
            break; 
        }
        if (!success) continue;

        hash.getHash(kmer_k, sequence, raw_hashes); 
        // now that we have the sequence and label
        // feed the sequence into the RACE structure
        // first rehash so that the arrays can fit into RACE
        rehash(raw_hashes, rehashes, race_repetitions, hash_power);
        // then simultaneously query and add 
        double KDE = sketch.query_and_add(rehashes); 
        // note: KDE is on a scale from [0,N] not the normalized interval [0,1]
        if (KDE < tau){
            // then keep this sample
            
            switch(format){
                case 1: // 1 = unpaired
                samplestream1 << chunk1; 
                break; 
                case 2: // 2 = interleaved
                samplestream1 << chunk1; 
                break; 
                case 3: // 3 = paired
                samplestream1 << chunk1; 
                samplestream2 << chunk2; 
                break; 
            }
        }
    }
    while(datastream1);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xbf0, %rsp            # imm = 0xBF0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x4, -0x8(%rbp)
jge 0x4051
movq 0x519e(%rip), %rdi      # 0x8fa8
leaq 0x23af(%rip), %rsi      # 0x61c0
callq 0x21b0
movq %rax, %rdi
movq 0x5198(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x517c(%rip), %rdi      # 0x8fa8
leaq 0x2395(%rip), %rsi      # 0x61c8
callq 0x21b0
movq 0x5169(%rip), %rdi      # 0x8fa8
leaq 0x23ad(%rip), %rsi      # 0x61f3
callq 0x21b0
movq %rax, %rdi
movq 0x5163(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x5147(%rip), %rdi      # 0x8fa8
leaq 0x23da(%rip), %rsi      # 0x6242
callq 0x21b0
movq %rax, %rdi
movq 0x5141(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x5125(%rip), %rdi      # 0x8fa8
leaq 0x23cf(%rip), %rsi      # 0x6259
callq 0x21b0
movq %rax, %rdi
movq 0x511f(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x5103(%rip), %rdi      # 0x8fa8
leaq 0x2447(%rip), %rsi      # 0x62f3
callq 0x21b0
movq %rax, %rdi
movq 0x50fd(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x50e1(%rip), %rdi      # 0x8fa8
leaq 0x247a(%rip), %rsi      # 0x6348
callq 0x21b0
movq %rax, %rdi
movq 0x50db(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x50bf(%rip), %rdi      # 0x8fa8
leaq 0x24b7(%rip), %rsi      # 0x63a7
callq 0x21b0
movq %rax, %rdi
movq 0x50b9(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x509d(%rip), %rdi      # 0x8fa8
leaq 0x24f5(%rip), %rsi      # 0x6407
callq 0x21b0
movq %rax, %rdi
movq 0x5097(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x507b(%rip), %rdi      # 0x8fa8
leaq 0x24e8(%rip), %rsi      # 0x641c
callq 0x21b0
movq %rax, %rdi
movq 0x5075(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x5059(%rip), %rdi      # 0x8fa8
leaq 0x2512(%rip), %rsi      # 0x6468
callq 0x21b0
movq %rax, %rdi
movq 0x5053(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x5037(%rip), %rdi      # 0x8fa8
leaq 0x2539(%rip), %rsi      # 0x64b1
callq 0x21b0
movq %rax, %rdi
movq 0x5031(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x5015(%rip), %rdi      # 0x8fa8
leaq 0x256a(%rip), %rsi      # 0x6504
callq 0x21b0
movq %rax, %rdi
movq 0x500f(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x4ff3(%rip), %rdi      # 0x8fa8
movq 0x4ffc(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq %rax, %rdi
leaq 0x2580(%rip), %rsi      # 0x654b
callq 0x21b0
movq %rax, %rdi
movq 0x4fde(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x4fc2(%rip), %rdi      # 0x8fa8
leaq 0x256d(%rip), %rsi      # 0x655a
callq 0x21b0
movq %rax, %rdi
movq 0x4fbc(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x4fa0(%rip), %rdi      # 0x8fa8
leaq 0x25d3(%rip), %rsi      # 0x65e2
callq 0x21b0
movq %rax, %rdi
movq 0x4f9a(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x4f7e(%rip), %rdi      # 0x8fa8
leaq 0x260f(%rip), %rsi      # 0x6640
callq 0x21b0
movq %rax, %rdi
movq 0x4f78(%rip), %rsi      # 0x8fb8
callq 0x21d0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x51b2
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0xaa8(%rbp)
leaq -0x39(%rbp), %rdi
movq %rdi, -0xaa0(%rbp)
callq 0x23a0
movq -0xaa8(%rbp), %rsi
movq -0xaa0(%rbp), %rdx
leaq -0x38(%rbp), %rdi
callq 0x5280
jmp 0x4089
xorl %eax, %eax
movl %eax, %esi
leaq -0x38(%rbp), %rdi
callq 0x5240
movsd %xmm0, -0xab0(%rbp)
jmp 0x40a0
leaq -0x38(%rbp), %rdi
callq 0x2120
leaq -0x39(%rbp), %rdi
callq 0x21f0
movsd -0xab0(%rbp), %xmm0
movsd %xmm0, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0x25bd(%rip), %rdi      # 0x668b
callq 0x2300
cmpl $0x0, %eax
jne 0x4115
movl $0x1, -0x50(%rbp)
jmp 0x41e4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x4107
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x2120
leaq -0x39(%rbp), %rdi
callq 0x21f0
jmp 0x5236
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0x2618(%rip), %rdi      # 0x673c
callq 0x2300
cmpl $0x0, %eax
jne 0x413a
movl $0x2, -0x50(%rbp)
jmp 0x41e2
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0x2545(%rip), %rdi      # 0x668e
callq 0x2300
cmpl $0x0, %eax
jne 0x41b2
movl $0x3, -0x50(%rbp)
cmpl $0x7, -0x8(%rbp)
jge 0x41b0
movq 0x4e89(%rip), %rdi      # 0x8ff0
leaq 0x2523(%rip), %rsi      # 0x6691
callq 0x21b0
movq %rax, %rdi
movq 0x4e3b(%rip), %rsi      # 0x8fb8
callq 0x21d0
movq 0x4e67(%rip), %rdi      # 0x8ff0
leaq 0x2545(%rip), %rsi      # 0x66d5
callq 0x21b0
movq %rax, %rdi
movq 0x4e19(%rip), %rsi      # 0x8fb8
callq 0x21d0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x51b2
jmp 0x41e0
movq 0x4e37(%rip), %rdi      # 0x8ff0
leaq 0x254b(%rip), %rsi      # 0x670b
callq 0x21b0
movq %rax, %rdi
movq 0x4de9(%rip), %rsi      # 0x8fb8
callq 0x21d0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x51b2
jmp 0x41e2
jmp 0x41e4
leaq -0x258(%rbp), %rdi
callq 0x2220
leaq -0x458(%rbp), %rdi
callq 0x2370
jmp 0x41fe
leaq -0x660(%rbp), %rdi
callq 0x2220
jmp 0x420c
leaq -0x860(%rbp), %rdi
callq 0x2370
jmp 0x421a
cmpl $0x3, -0x50(%rbp)
je 0x429f
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
leaq -0x258(%rbp), %rdi
movl $0x8, %edx
callq 0x2130
jmp 0x423b
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rsi
leaq -0x458(%rbp), %rdi
movl $0x10, %edx
callq 0x2050
jmp 0x4256
jmp 0x430d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x522a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x521e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x5212
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x5206
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
leaq -0x258(%rbp), %rdi
movl $0x8, %edx
callq 0x2130
jmp 0x42ba
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rsi
leaq -0x660(%rbp), %rdi
movl $0x8, %edx
callq 0x2130
jmp 0x42d5
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rsi
leaq -0x458(%rbp), %rdi
movl $0x10, %edx
callq 0x2050
jmp 0x42f0
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rsi
leaq -0x860(%rbp), %rdi
movl $0x10, %edx
callq 0x2050
jmp 0x430b
jmp 0x430d
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0xac0(%rbp)
leaq -0x881(%rbp), %rdi
movq %rdi, -0xab8(%rbp)
callq 0x23a0
movq -0xac0(%rbp), %rsi
movq -0xab8(%rbp), %rdx
leaq -0x880(%rbp), %rdi
callq 0x5280
jmp 0x434b
leaq -0x881(%rbp), %rdi
callq 0x21f0
leaq -0x8a9(%rbp), %rdi
movq %rdi, -0xac8(%rbp)
callq 0x23a0
movq -0xac8(%rbp), %rdx
leaq 0x1d3f(%rip), %rsi      # 0x60b7
leaq -0x8a8(%rbp), %rdi
callq 0x5280
jmp 0x4386
leaq -0x8a9(%rbp), %rdi
callq 0x21f0
leaq -0x880(%rbp), %rdi
movq %rdi, -0xad8(%rbp)
callq 0x2340
movq -0xad8(%rbp), %rdi
movq %rax, %rdx
movl $0x2e, %esi
callq 0x23e0
movq %rax, -0x8b8(%rbp)
leaq 0x2377(%rip), %rsi      # 0x673e
leaq -0x8a8(%rbp), %rdi
callq 0x31a0
movb %al, -0xac9(%rbp)
jmp 0x43db
movb -0xac9(%rbp), %al
testb $0x1, %al
jne 0x43e7
jmp 0x4449
leaq 0x2317(%rip), %rsi      # 0x6705
leaq -0x8a8(%rbp), %rdi
callq 0x22e0
jmp 0x43fc
jmp 0x4449
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x881(%rbp), %rdi
callq 0x21f0
jmp 0x5206
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x8a9(%rbp), %rdi
callq 0x21f0
jmp 0x51fa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x51ee
cmpq $-0x1, -0x8b8(%rbp)
je 0x44c1
movq -0x8b8(%rbp), %rax
incq %rax
movq %rax, -0xae0(%rbp)
leaq -0x880(%rbp), %rdi
movq %rdi, -0xae8(%rbp)
callq 0x2340
movq -0xae8(%rbp), %rsi
movq -0xae0(%rbp), %rdx
movq %rax, %rcx
movq -0x8b8(%rbp), %rax
subq %rax, %rcx
leaq -0x8d8(%rbp), %rdi
callq 0x21c0
jmp 0x44a0
leaq -0x8a8(%rbp), %rdi
leaq -0x8d8(%rbp), %rsi
callq 0x2260
leaq -0x8d8(%rbp), %rdi
callq 0x2120
jmp 0x4508
movq 0x4b28(%rip), %rdi      # 0x8ff0
leaq 0x2272(%rip), %rsi      # 0x6741
callq 0x21b0
movq %rax, -0xaf0(%rbp)
jmp 0x44dd
movq -0xaf0(%rbp), %rdi
movq 0x4acd(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x44f2
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
leaq 0x1af5(%rip), %rsi      # 0x6004
leaq -0x8a8(%rbp), %rdi
callq 0x5330
movb %al, -0xaf1(%rbp)
jmp 0x4523
movb -0xaf1(%rbp), %al
testb $0x1, %al
jne 0x4532
jmp 0x45f0
leaq 0x21cc(%rip), %rsi      # 0x6705
leaq -0x8a8(%rbp), %rdi
callq 0x5330
movb %al, -0xaf2(%rbp)
jmp 0x454d
movb -0xaf2(%rbp), %al
testb $0x1, %al
jne 0x455c
jmp 0x45f0
movq 0x4a8d(%rip), %rdi      # 0x8ff0
leaq 0x220e(%rip), %rsi      # 0x6778
callq 0x21b0
movq %rax, -0xb00(%rbp)
jmp 0x4578
movq -0xb00(%rbp), %rdi
leaq -0x8a8(%rbp), %rsi
callq 0x2190
movq %rax, -0xb08(%rbp)
jmp 0x4594
movq -0xb08(%rbp), %rdi
movq 0x4a16(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x45a9
movq 0x4a40(%rip), %rdi      # 0x8ff0
leaq 0x21da(%rip), %rsi      # 0x6791
callq 0x21b0
movq %rax, -0xb10(%rbp)
jmp 0x45c5
movq -0xb10(%rbp), %rdi
movq 0x49e5(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x45da
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
movl $0x2710, -0x8e0(%rbp)   # imm = 0x2710
movl $0xa, -0x8e4(%rbp)
movl $0x1, -0x8e8(%rbp)
movl $0x10, -0x8ec(%rbp)
movl $0x0, -0x8f0(%rbp)
movl -0x8f0(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x4b43
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x228f(%rip), %rdi      # 0x68d6
callq 0x2300
cmpl $0x0, %eax
jne 0x4770
movl -0x8f0(%rbp), %eax
addl $0x1, %eax
cmpl -0x8(%rbp), %eax
jge 0x4727
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0xb20(%rbp)
leaq -0x911(%rbp), %rdi
movq %rdi, -0xb18(%rbp)
callq 0x23a0
movq -0xb20(%rbp), %rsi
movq -0xb18(%rbp), %rdx
leaq -0x910(%rbp), %rdi
callq 0x5280
jmp 0x46ad
xorl %eax, %eax
movl %eax, %esi
leaq -0x910(%rbp), %rdi
movl $0xa, %edx
callq 0x5360
movl %eax, -0xb24(%rbp)
jmp 0x46ca
movl -0xb24(%rbp), %eax
movl %eax, -0x8e0(%rbp)
leaq -0x910(%rbp), %rdi
callq 0x2120
leaq -0x911(%rbp), %rdi
callq 0x21f0
jmp 0x476e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x4716
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x910(%rbp), %rdi
callq 0x2120
leaq -0x911(%rbp), %rdi
callq 0x21f0
jmp 0x51ee
movq 0x48c2(%rip), %rdi      # 0x8ff0
leaq 0x209e(%rip), %rsi      # 0x67d3
callq 0x21b0
movq %rax, -0xb30(%rbp)
jmp 0x4743
movq -0xb30(%rbp), %rdi
movq 0x4867(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4758
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
jmp 0x4770
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x217d(%rip), %rdi      # 0x6903
callq 0x2300
cmpl $0x0, %eax
jne 0x48af
movl -0x8f0(%rbp), %eax
addl $0x1, %eax
cmpl -0x8(%rbp), %eax
jge 0x4866
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0xb40(%rbp)
leaq -0x939(%rbp), %rdi
movq %rdi, -0xb38(%rbp)
callq 0x23a0
movq -0xb40(%rbp), %rsi
movq -0xb38(%rbp), %rdx
leaq -0x938(%rbp), %rdi
callq 0x5280
jmp 0x47ec
xorl %eax, %eax
movl %eax, %esi
leaq -0x938(%rbp), %rdi
movl $0xa, %edx
callq 0x5360
movl %eax, -0xb44(%rbp)
jmp 0x4809
movl -0xb44(%rbp), %eax
movl %eax, -0x8e4(%rbp)
leaq -0x938(%rbp), %rdi
callq 0x2120
leaq -0x939(%rbp), %rdi
callq 0x21f0
jmp 0x48ad
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x4855
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x938(%rbp), %rdi
callq 0x2120
leaq -0x939(%rbp), %rdi
callq 0x21f0
jmp 0x51ee
movq 0x4783(%rip), %rdi      # 0x8ff0
leaq 0x1f8f(%rip), %rsi      # 0x6803
callq 0x21b0
movq %rax, -0xb50(%rbp)
jmp 0x4882
movq -0xb50(%rbp), %rdi
movq 0x4728(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4897
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
jmp 0x48af
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x206a(%rip), %rdi      # 0x692f
callq 0x2300
cmpl $0x0, %eax
jne 0x49ee
movl -0x8f0(%rbp), %eax
addl $0x1, %eax
cmpl -0x8(%rbp), %eax
jge 0x49a5
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0xb60(%rbp)
leaq -0x961(%rbp), %rdi
movq %rdi, -0xb58(%rbp)
callq 0x23a0
movq -0xb60(%rbp), %rsi
movq -0xb58(%rbp), %rdx
leaq -0x960(%rbp), %rdi
callq 0x5280
jmp 0x492b
xorl %eax, %eax
movl %eax, %esi
leaq -0x960(%rbp), %rdi
movl $0xa, %edx
callq 0x5360
movl %eax, -0xb64(%rbp)
jmp 0x4948
movl -0xb64(%rbp), %eax
movl %eax, -0x8e8(%rbp)
leaq -0x960(%rbp), %rdi
callq 0x2120
leaq -0x961(%rbp), %rdi
callq 0x21f0
jmp 0x49ec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x4994
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x960(%rbp), %rdi
callq 0x2120
leaq -0x961(%rbp), %rdi
callq 0x21f0
jmp 0x51ee
movq 0x4644(%rip), %rdi      # 0x8ff0
leaq 0x1e7f(%rip), %rsi      # 0x6832
callq 0x21b0
movq %rax, -0xb70(%rbp)
jmp 0x49c1
movq -0xb70(%rbp), %rdi
movq 0x45e9(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x49d6
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
jmp 0x49ee
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x1f59(%rip), %rdi      # 0x695d
callq 0x2300
cmpl $0x0, %eax
jne 0x4b2d
movl -0x8f0(%rbp), %eax
addl $0x1, %eax
cmpl -0x8(%rbp), %eax
jge 0x4ae4
movq -0x10(%rbp), %rax
movslq -0x8f0(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0xb80(%rbp)
leaq -0x989(%rbp), %rdi
movq %rdi, -0xb78(%rbp)
callq 0x23a0
movq -0xb80(%rbp), %rsi
movq -0xb78(%rbp), %rdx
leaq -0x988(%rbp), %rdi
callq 0x5280
jmp 0x4a6a
xorl %eax, %eax
movl %eax, %esi
leaq -0x988(%rbp), %rdi
movl $0xa, %edx
callq 0x5360
movl %eax, -0xb84(%rbp)
jmp 0x4a87
movl -0xb84(%rbp), %eax
movl %eax, -0x8ec(%rbp)
leaq -0x988(%rbp), %rdi
callq 0x2120
leaq -0x989(%rbp), %rdi
callq 0x21f0
jmp 0x4b2b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x4ad3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x988(%rbp), %rdi
callq 0x2120
leaq -0x989(%rbp), %rdi
callq 0x21f0
jmp 0x51ee
movq 0x4505(%rip), %rdi      # 0x8ff0
leaq 0x1d71(%rip), %rsi      # 0x6863
callq 0x21b0
movq %rax, -0xb90(%rbp)
jmp 0x4b00
movq -0xb90(%rbp), %rdi
movq 0x44aa(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4b15
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
jmp 0x4b2d
jmp 0x4b2f
movl -0x8f0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8f0(%rbp)
jmp 0x4622
xorps %xmm0, %xmm0
ucomisd -0x18(%rbp), %xmm0
jb 0x4b94
movq 0x449c(%rip), %rdi      # 0x8ff0
leaq 0x1d34(%rip), %rsi      # 0x688f
callq 0x21b0
movq %rax, -0xb98(%rbp)
jmp 0x4b69
movq -0xb98(%rbp), %rdi
movq 0x4441(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4b7e
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
cmpl $0x0, -0x8e0(%rbp)
jg 0x4be4
movq 0x444c(%rip), %rdi      # 0x8ff0
leaq 0x1d06(%rip), %rsi      # 0x68b1
callq 0x21b0
movq %rax, -0xba0(%rbp)
jmp 0x4bb9
movq -0xba0(%rbp), %rdi
movq 0x43f1(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4bce
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
cmpl $0x0, -0x8e4(%rbp)
jg 0x4c34
movq 0x43fc(%rip), %rdi      # 0x8ff0
leaq 0x1ce3(%rip), %rsi      # 0x68de
callq 0x21b0
movq %rax, -0xba8(%rbp)
jmp 0x4c09
movq -0xba8(%rbp), %rdi
movq 0x43a1(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4c1e
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
cmpl $0x0, -0x8e8(%rbp)
jg 0x4c84
movq 0x43ac(%rip), %rdi      # 0x8ff0
leaq 0x1cbf(%rip), %rsi      # 0x690a
callq 0x21b0
movq %rax, -0xbb0(%rbp)
jmp 0x4c59
movq -0xbb0(%rbp), %rdi
movq 0x4351(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4c6e
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
cmpl $0x0, -0x8ec(%rbp)
jg 0x4cd4
movq 0x435c(%rip), %rdi      # 0x8ff0
leaq 0x1c9d(%rip), %rsi      # 0x6938
callq 0x21b0
movq %rax, -0xbb8(%rbp)
jmp 0x4ca9
movq -0xbb8(%rbp), %rdi
movq 0x4301(%rip), %rsi      # 0x8fb8
callq 0x21d0
jmp 0x4cbe
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x8dc(%rbp)
jmp 0x516a
leaq -0x9b0(%rbp), %rdi
callq 0x22f0
leaq -0x9d0(%rbp), %rdi
callq 0x22f0
leaq -0x9f0(%rbp), %rdi
callq 0x22f0
movl -0x8e4(%rbp), %esi
movl -0x8e8(%rbp), %eax
imull %eax, %esi
leaq -0x9f4(%rbp), %rdi
callq 0x2640
jmp 0x4d15
movl -0x8e4(%rbp), %eax
movl -0x8e8(%rbp), %ecx
imull %ecx, %eax
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x2030
movq %rax, -0xbc0(%rbp)
jmp 0x4d4a
movq -0xbc0(%rbp), %rax
movq %rax, -0xa00(%rbp)
movslq -0x8e4(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x2030
movq %rax, -0xbc8(%rbp)
jmp 0x4d83
movq -0xbc8(%rbp), %rax
movq %rax, -0xa08(%rbp)
movslq -0x8e4(%rbp), %rsi
movslq -0x8e0(%rbp), %rdx
leaq -0xa28(%rbp), %rdi
callq 0x3360
jmp 0x4dad
jmp 0x4daf
movb $0x0, -0xa29(%rbp)
leaq -0x258(%rbp), %rdi
callq 0x20b0
movl %eax, -0xbcc(%rbp)
jmp 0x4dca
movl -0xbcc(%rbp), %eax
movl %eax, -0xa30(%rbp)
cmpl $-0x1, -0xa30(%rbp)
jne 0x4e34
movq -0x258(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x258(%rbp,%rax), %rdi
callq 0x23c0
movb %al, -0xbcd(%rbp)
jmp 0x4dff
movb -0xbcd(%rbp), %al
testb $0x1, %al
jne 0x4e0b
jmp 0x4e32
jmp 0x5100
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x51ca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x51be
jmp 0x4e34
movl -0x50(%rbp), %eax
movl %eax, -0xbd4(%rbp)
subl $0x1, %eax
je 0x4e69
jmp 0x4e44
movl -0xbd4(%rbp), %eax
subl $0x2, %eax
je 0x4ee3
jmp 0x4e55
movl -0xbd4(%rbp), %eax
subl $0x3, %eax
je 0x4f5d
jmp 0x4fe2
leaq -0xa50(%rbp), %rdi
leaq -0x8a8(%rbp), %rsi
callq 0x20e0
jmp 0x4e7e
leaq -0x258(%rbp), %rdi
leaq -0x9b0(%rbp), %rsi
leaq -0x9d0(%rbp), %rdx
leaq -0xa50(%rbp), %rcx
callq 0x2cf0
movb %al, -0xbd5(%rbp)
jmp 0x4ea7
movb -0xbd5(%rbp), %al
andb $0x1, %al
movb %al, -0xa29(%rbp)
leaq -0xa50(%rbp), %rdi
callq 0x2120
jmp 0x4fe2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0xa50(%rbp), %rdi
callq 0x2120
jmp 0x51be
leaq -0xa70(%rbp), %rdi
leaq -0x8a8(%rbp), %rsi
callq 0x20e0
jmp 0x4ef8
leaq -0x258(%rbp), %rdi
leaq -0x9b0(%rbp), %rsi
leaq -0x9d0(%rbp), %rdx
leaq -0xa70(%rbp), %rcx
callq 0x2fc0
movb %al, -0xbd6(%rbp)
jmp 0x4f21
movb -0xbd6(%rbp), %al
andb $0x1, %al
movb %al, -0xa29(%rbp)
leaq -0xa70(%rbp), %rdi
callq 0x2120
jmp 0x4fe2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0xa70(%rbp), %rdi
callq 0x2120
jmp 0x51be
leaq -0xa90(%rbp), %rdi
leaq -0x8a8(%rbp), %rsi
callq 0x20e0
jmp 0x4f72
leaq -0x258(%rbp), %rdi
leaq -0x660(%rbp), %rsi
leaq -0x9b0(%rbp), %rdx
leaq -0x9d0(%rbp), %rcx
leaq -0x9f0(%rbp), %r8
leaq -0xa90(%rbp), %r9
callq 0x2d90
movb %al, -0xbd7(%rbp)
jmp 0x4fa9
movb -0xbd7(%rbp), %al
andb $0x1, %al
movb %al, -0xa29(%rbp)
leaq -0xa90(%rbp), %rdi
callq 0x2120
jmp 0x4fe2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0xa90(%rbp), %rdi
callq 0x2120
jmp 0x51be
testb $0x1, -0xa29(%rbp)
jne 0x4ff0
jmp 0x5100
movslq -0x8ec(%rbp), %rsi
movq -0xa00(%rbp), %rcx
leaq -0x9f4(%rbp), %rdi
leaq -0x9b0(%rbp), %rdx
callq 0x2660
jmp 0x5013
movq -0xa00(%rbp), %rdi
movq -0xa08(%rbp), %rsi
movl -0x8e4(%rbp), %edx
movl -0x8e8(%rbp), %ecx
callq 0x32e0
jmp 0x5034
movq -0xa08(%rbp), %rsi
leaq -0xa28(%rbp), %rdi
callq 0x34a0
movsd %xmm0, -0xbe0(%rbp)
jmp 0x5051
movsd -0xbe0(%rbp), %xmm0
movsd %xmm0, -0xa98(%rbp)
movsd -0xa98(%rbp), %xmm1
movsd -0x18(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x50fe
movl -0x50(%rbp), %eax
movl %eax, -0xbe4(%rbp)
subl $0x1, %eax
je 0x50a2
jmp 0x5088
movl -0xbe4(%rbp), %eax
subl $0x2, %eax
je 0x50b9
jmp 0x5095
movl -0xbe4(%rbp), %eax
subl $0x3, %eax
je 0x50d0
jmp 0x50fc
leaq -0x458(%rbp), %rdi
leaq -0x9d0(%rbp), %rsi
callq 0x2190
jmp 0x50b7
jmp 0x50fc
leaq -0x458(%rbp), %rdi
leaq -0x9d0(%rbp), %rsi
callq 0x2190
jmp 0x50ce
jmp 0x50fc
leaq -0x458(%rbp), %rdi
leaq -0x9d0(%rbp), %rsi
callq 0x2190
jmp 0x50e5
leaq -0x860(%rbp), %rdi
leaq -0x9f0(%rbp), %rsi
callq 0x2190
jmp 0x50fa
jmp 0x50fc
jmp 0x50fe
jmp 0x5100
movq -0x258(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x258(%rbp,%rax), %rdi
callq 0x2280
movb %al, -0xbe5(%rbp)
jmp 0x5120
movb -0xbe5(%rbp), %al
testb $0x1, %al
jne 0x4daf
jmp 0x5130
leaq -0xa28(%rbp), %rdi
callq 0x33f0
leaq -0x9f0(%rbp), %rdi
callq 0x2120
leaq -0x9d0(%rbp), %rdi
callq 0x2120
leaq -0x9b0(%rbp), %rdi
callq 0x2120
movl $0x0, -0x8dc(%rbp)
leaq -0x8a8(%rbp), %rdi
callq 0x2120
leaq -0x880(%rbp), %rdi
callq 0x2120
leaq -0x860(%rbp), %rdi
callq 0x2330
leaq -0x660(%rbp), %rdi
callq 0x2080
leaq -0x458(%rbp), %rdi
callq 0x2330
leaq -0x258(%rbp), %rdi
callq 0x2080
movl -0x4(%rbp), %eax
addq $0xbf0, %rsp            # imm = 0xBF0
popq %rbp
retq
leaq -0xa28(%rbp), %rdi
callq 0x33f0
leaq -0x9f0(%rbp), %rdi
callq 0x2120
leaq -0x9d0(%rbp), %rdi
callq 0x2120
leaq -0x9b0(%rbp), %rdi
callq 0x2120
leaq -0x8a8(%rbp), %rdi
callq 0x2120
leaq -0x880(%rbp), %rdi
callq 0x2120
leaq -0x860(%rbp), %rdi
callq 0x2330
leaq -0x660(%rbp), %rdi
callq 0x2080
leaq -0x458(%rbp), %rdi
callq 0x2330
leaq -0x258(%rbp), %rdi
callq 0x2080
movq -0x48(%rbp), %rdi
callq 0x2390
nop