// File: /workspace/github_cpp_makefile_star2_O1/garrettsickles[P]hgt2png/hgt2png.cpp
// Function: main
int main(int argc, char** argv)
{
    /*
     * Arguement Parsing
     */
    if (argc < 6 || argc > 8 || argc == 7)
    {
        std::printf(HGT2PNG_USAGE_TEXT);
        std::printf("%d\n", argc);
        return 0;
    }

    const auto width = std::atoi(argv[4]);
    const auto height = std::atoi(argv[5]);
    const auto rows = argc == 8 ? std::atoi(argv[6]) : 1;
    const auto cols = argc == 8 ? std::atoi(argv[7]) : 1;
    const auto pixel_count = static_cast<std::size_t>(width * height);

    /*
     * Read in the HGT (.hgt) file
     * 
     * Check that the file opened properly
     */
    char* hgt_filename = argv[2];
    CFile hgt_file = CFile(std::fopen(hgt_filename, "rb"), [](FILE* f)->void { std::fclose(f); });
    if (!hgt_file.get())
    {
        std::printf("Could not open file \"%s\", Exiting...\n", hgt_filename);
        return 1;
    }

    /*
     * Extract the number of samples in the HGT raster
     */
    FSEEK64(hgt_file.get(), 0, SEEK_END);
    const auto hgt_size = FTELL64(hgt_file.get());
    FSEEK64(hgt_file.get(), 0, SEEK_SET);
    std::printf
    (
        "File: \"%s\" (%" PRId64 " bytes)\nSize: %d(w) x %d(h) pixels (%lu samples)\n",
        hgt_filename, hgt_size, width, height, pixel_count
    );

    /*
     * Verify the subdivisions
     */
    if (cols < 1 || rows < 1)
    {
        std::printf("Both row and column must be greater than or equal to 1, Exiting...\n");
        return 1;
    }
    if (cols > 1 && (width - 1) % cols)
    {
        std::printf("One less than the width of %d is not evenly divisible by %d, Exiting...\n", width, cols);
        return 1;
    }
    if (rows > 1 && (height - 1) % rows)
    {
        std::printf("One less than the height of %d is not evenly divisible by %d, Exiting...\n", height, rows);
        return 1;
    }
    const auto subwidth = (width / cols) + (cols > 1 ? 1 : 0);
    const auto subheight = (height / rows) + (rows > 1 ? 1 : 0);

    /*
     * Verify the size of the HGT raster
     */
    const auto data_size   = static_cast<decltype(hgt_size)>(pixel_count * sizeof(std::int16_t));
    if (hgt_size != data_size)
    {
        std::printf("Actual size %" PRId64 ", Expected %" PRId64 ", Exiting...\n", hgt_size, data_size);
        return 1;
    }

    /*
     * Extract the location of the 1 degree raster from the filename
     */
    int  ll[2]       = { -1, -1 };
    char hemi[2]     = {  0,  0 };
    char* last_slash = std::strrchr(argv[2], DIRECTORY_DELIM);
    char* file_name  = last_slash ? last_slash + 1 : hgt_filename;
    std::sscanf(file_name, "%c%2d%c%3d.hgt", &hemi[0], &ll[0], &hemi[1], &ll[1]);
    std::string base_name = std::string(argv[3]) + file_name;
    base_name.erase(base_name.find_last_of("."), std::string::npos);
    
    /*
     * Verify the filename raster coordinates
     */
    const bool valid_hemi[2] = { hemi[0] == 'N' || hemi[0] == 'S', hemi[1] == 'W' || hemi[1] == 'E' };
    if (!valid_hemi[0] || !valid_hemi[1])
    {
        std::printf("Inavlid hemisphere \"%c\" in \"%s\", Exiting...\n", valid_hemi[0] ? hemi[1] : hemi[0], file_name);
        return 1;
    }
    std::printf("Bounds: (%d%c, %d%c) to (%d%c, %d%c)\n",
        ll[0], hemi[0], ll[1], hemi[1], ll[0] + 1, hemi[0], ll[1] + 1, hemi[1]
    );

    /*
     * Extract the raster into memory
     */
    std::vector<std::uint8_t> raster(data_size);
    const auto read_size = std::fread(raster.data(), data_size, 1, hgt_file.get());
    if (read_size != 1)
    {
        std::printf("Read size %" PRId64 ", Expected 1, Exiting...\n", read_size);
        return 1;
    }
    
    /*
     * Swap the byte order from Big to Little Endian
     * if the platform is Little Endian
     */
    if (is_little_endian())
    {
        std::uint8_t swp = 0;
        for (auto i = 0; i < data_size; i += sizeof(std::int16_t))
        {
            swp = raster[i];
            raster[i] = raster[i+1];
            raster[i+1] = swp;
        }
    }

    /*
     * Convert the raster to unsigned 16 bit and
     * accumulate the range of the raster
     */
    int minimum = 32768;
    int maximum = -32768;
    int invalid = 0;

    std::int32_t temp;
    std::int16_t* svalue = nullptr;
    for (auto i = 0; i < data_size; i += sizeof(std::int16_t))
    {
        svalue = reinterpret_cast<std::int16_t*>(raster.data() + i);
        temp = static_cast<std::int32_t>(*svalue);
        if (temp < minimum)
        {
            if (temp != -32768) minimum = temp;
            else invalid++;
        } 
        else if (temp > maximum)
        {
            maximum = temp;
        }
    }
    std::printf("Range: [%d, %d] meters\nMissing: %d pixels\n", minimum, maximum, invalid);

    /*
     *
     */
    double toscale = 0.0;
    const double minf = static_cast<double>(minimum);
    const double deltaf = static_cast<double>(maximum) - minf;

    /*
     * Absolute Mode
     */
    if (argv[1][0] == 'a')
    {
        std::uint16_t* uvalue = nullptr;
        for (auto i = 0; i < data_size; i += sizeof(std::int16_t))
        {
            svalue = reinterpret_cast<std::int16_t*>(raster.data() + i);
            uvalue = reinterpret_cast<std::uint16_t*>(raster.data() + i);
            *uvalue = *svalue == -32768 ? 0xFFFF : static_cast<std::uint16_t>(static_cast<double>(*svalue) + 32767.0);
        }
    }

    /*
     * Relative Mode, By default('r')
     */
    else
    {
        /*
         * Scale the raster to the range such that the minimum height
         * encodes to 0 and the maximum height encodes to 65534
         */
        svalue = nullptr;
        std::uint16_t* uvalue = nullptr;
        for (auto i = 0; i < data_size; i += sizeof(std::int16_t))
        {
            svalue = reinterpret_cast<std::int16_t*>(raster.data() + i);
            uvalue = reinterpret_cast<std::uint16_t*>(raster.data() + i);
            toscale = static_cast<double>(*svalue);
            *uvalue = *svalue == -32768 ? 0xFFFF : static_cast<std::uint16_t>((toscale - minf) * 65534.0 / deltaf);
        }
    }

    /*
     * Swap the byte order from Little to Big Endian
     * if the platform is Little Endian
     */
    if (is_little_endian())
    {
        std::uint8_t swp = 0;
        for (auto i = 0; i < data_size; i += sizeof(std::int16_t))
        {
            swp = raster[i];
            raster[i] = raster[i+1];
            raster[i+1] = swp;
        }
    }

    /*
     * Calculate the physical dimensions of each subraster in radians
     */
    const double upx = deg_to_rad(1.0 / static_cast<double>(subwidth - 1));
    const double upy = deg_to_rad(1.0 / static_cast<double>(subheight - 1));

    /*
     * Write the PNG to a data buffer
     */
    std::vector<std::uint8_t> png_data;
    std::vector<std::uint8_t*> png_rows(subheight);
    size_t total_png_size = 0;

    int row_offset = 0;
    int col_offset = 0;
    for (auto row_index = 0; row_index < rows; row_index++)
    {
        for (auto col_index = 0; col_index < cols; col_index++)
        {
            /*
             * Setup the PNG info
             */
            png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
            png_infop   info = png_create_info_struct(png);
            png_set_IHDR(png, info,
                static_cast<png_uint_32>(subwidth),
                static_cast<png_uint_32>(subheight),
                sizeof(std::uint16_t) * 8,
                PNG_COLOR_TYPE_GRAY,
                PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_DEFAULT,
                PNG_FILTER_TYPE_DEFAULT
            );

            /*
             * Set the 'sCAL' (Physical Scale)
             * 
             * The dimensions of each pixel in radians
             */
            png_set_sCAL(png, info, 2, upx, upy);

            /*
             * Set the 'pCAL' (Pixel Calibration)
             * 
             * The 1st order function mapping the encoded PNG values to the physical values
             */
            auto decription = std::string("SRTM-HGT");
            auto units = std::string("m");
            auto p0 = std::to_string(minf);
            auto p1 = std::to_string(deltaf);
            png_charp params[2] = { &p0.at(0), &p1.at(0)};
            png_set_pCAL(png, info, &decription.at(0), -32767, 32767, 0, 2, &units.at(0), params);

            /*
             * Setup a vector of pointers to the beginning of each row
             */
            for (auto row_abs = row_offset; row_abs < (row_offset + subheight); row_abs++)
            {
                png_rows[row_abs - row_offset] =
                    raster.data() +
                    row_abs * width * sizeof(std::uint16_t) +
                    (col_offset - 1) * sizeof(std::uint16_t);
            }
                

            /*
             * Write the PNG to a buffer
             */
            png_set_rows(png, info, png_rows.data());
            png_set_write_fn(png, &(png_data), libpng_write_stdvector, NULL);
            png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
            png_destroy_write_struct(&png, &info);
            const auto png_size = png_data.size();

            /*
             * Write the PNG buffer out to file
             */
            std::string subname =
                base_name + "." +
                std::to_string(row_offset) + "." + std::to_string(col_offset) + ".png";
            CFile png_file = CFile(std::fopen(subname.c_str(), "wb"), [](FILE* f)->void { std::fclose(f); });
            if (!hgt_file.get())
            {
                std::printf("Could not open file \"%s\", Exiting...\n", subname.c_str());
                return 1;
            }
            const auto write_size = std::fwrite(png_data.data(), png_data.size(), 1, png_file.get());
            png_data.clear();
            
            /*
             * Verify the file write
             */
            if (write_size != 1)
            {
                std::printf("Write size %" PRId64 ", Expected 1, Exiting...\n", write_size);
                return 1;
            }

            total_png_size += png_size;
            col_offset += (subheight - 1);      
        }
        col_offset = 0;
        row_offset += (subwidth - 1);
    }

    /*
     * Show some statistics
     */
    std::printf("Output: Compression: %.2lf%% of original size\n",
        static_cast<double>(total_png_size) / static_cast<double>(data_size) * 100.0
    );
    
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2c8, %rsp            # imm = 0x2C8
movl %edi, %ebx
leal -0x9(%rbx), %eax
cmpl $-0x3, %eax
setae %al
cmpl $0x7, %edi
setne %cl
testb %al, %cl
jne 0x2444
leaq 0x1fb6(%rip), %rdi      # 0x43de
callq 0x21f0
leaq 0x1c1c(%rip), %rdi      # 0x4050
xorl %ebp, %ebp
movl %ebx, %esi
xorl %eax, %eax
callq 0x2030
jmp 0x26ef
movq %rsi, %r12
movq 0x20(%rsi), %rdi
callq 0x2200
movl %eax, %r14d
movq 0x28(%r12), %rdi
callq 0x2200
movl %eax, %r15d
movl $0x1, %ebp
movl $0x1, %r13d
cmpl $0x8, %ebx
jne 0x247d
movq 0x30(%r12), %rdi
callq 0x2200
movl %eax, %r13d
cmpl $0x8, %ebx
jne 0x248e
movq 0x38(%r12), %rdi
callq 0x2200
movl %eax, %ebp
movq %r12, 0x18(%rsp)
movq 0x10(%r12), %r12
leaq 0x1bb5(%rip), %rsi      # 0x4054
movq %r12, %rdi
callq 0x21a0
movq %rax, %rbx
testq %rax, %rax
je 0x255b
movl %ebp, 0x2c(%rsp)
movq %rbx, %rbp
movl %r13d, 0x14(%rsp)
movl %r15d, %eax
imull %r14d, %eax
movl %eax, 0x40(%rsp)
movslq %eax, %rbx
movq %rbp, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x20c0
movq %rbp, %rdi
callq 0x21b0
movl %r15d, %r13d
movq %rax, %r15
movq %rbp, 0x8(%rsp)
movq %rbp, %rdi
movl 0x2c(%rsp), %ebp
xorl %esi, %esi
xorl %edx, %edx
callq 0x20c0
leaq 0x1b77(%rip), %rdi      # 0x407d
movq %r12, 0xa0(%rsp)
movq %r12, %rsi
movq %r15, 0x48(%rsp)
movq %r15, %rdx
movq %r14, 0x30(%rsp)
movl %r14d, %ecx
movl %r13d, %r8d
movq %rbx, 0x80(%rsp)
movq %rbx, %r9
xorl %eax, %eax
callq 0x2030
testl %ebp, %ebp
setle %al
cmpl $0x0, 0x14(%rsp)
setle %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x2576
leaq 0x1e4a(%rip), %rdi      # 0x439b
callq 0x21f0
jmp 0x26d8
leaq 0x1af5(%rip), %rdi      # 0x4057
movq %r12, %rsi
xorl %eax, %eax
callq 0x2030
movl $0x1, %ebp
jmp 0x26e2
cmpl $0x2, %ebp
movq 0x30(%rsp), %rsi
jl 0x2595
leal -0x1(%rsi), %eax
cltd
idivl %ebp
testl %edx, %edx
je 0x2595
leaq 0x1b2d(%rip), %rdi      # 0x40be
movl %ebp, %edx
jmp 0x25b6
movl 0x14(%rsp), %ecx
cmpl $0x2, %ecx
jl 0x25c2
movl %r13d, %eax
decl %eax
cltd
idivl %ecx
testl %edx, %edx
je 0x25c2
leaq 0x1b56(%rip), %rdi      # 0x4107
movl %r13d, %esi
movl %ecx, %edx
xorl %eax, %eax
callq 0x2030
jmp 0x26d8
cmpl $0x2, %ecx
setge %r8b
cmpl $0x2, %ebp
setge %dil
movl %esi, %eax
cltd
idivl %ebp
movq %rax, 0x98(%rsp)
movl %r13d, %eax
cltd
idivl %ecx
movq 0x80(%rsp), %r13
addq %r13, %r13
movq 0x48(%rsp), %rsi
cmpq %r13, %rsi
jne 0x26c7
movb %r8b, 0x48(%rsp)
movb %dil, 0x4(%rsp)
movq %rax, 0x38(%rsp)
leaq 0xe4(%rsp), %rbx
movq $-0x1, -0x4(%rbx)
leaq 0x7(%rsp), %rbp
movw $0x0, -0x1(%rbp)
movq 0x18(%rsp), %r14
movq 0x10(%r14), %rdi
movl $0x2f, %esi
callq 0x2170
leaq 0x1(%rax), %r15
testq %rax, %rax
cmoveq 0xa0(%rsp), %r15
leaq 0x1b2c(%rip), %rsi      # 0x417c
leaq 0x6(%rsp), %rdx
leaq 0xe0(%rsp), %rcx
movq %r15, %rdi
movq %rbp, %r8
movq %rbx, %r9
xorl %eax, %eax
callq 0x2140
movq 0x18(%r14), %rsi
leaq 0xc0(%rsp), %rdi
leaq 0x1e8(%rsp), %rdx
callq 0x2090
leaq 0xc0(%rsp), %rdi
movq %r15, %rsi
callq 0x2260
leaq 0x1a8(%rsp), %r12
movq %r12, -0x10(%r12)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x2703
movq %rdx, 0x198(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x1a8(%rsp)
jmp 0x270d
leaq 0x1a83(%rip), %rdi      # 0x4151
movq %r13, %rdx
xorl %eax, %eax
callq 0x2030
movl $0x1, %ebp
movq 0x8(%rsp), %rbx
testq %rbx, %rbx
je 0x26ef
movq %rbx, %rdi
callq 0x2150
movl %ebp, %eax
addq $0x2c8, %rsp            # imm = 0x2C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movupd (%rcx), %xmm0
movupd %xmm0, (%r12)
movq 0x8(%rax), %rdx
movq %rdx, 0x1a0(%rsp)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
leaq 0xd0(%rsp), %rbp
movq -0x10(%rbp), %rdi
cmpq %rbp, %rdi
je 0x273e
callq 0x2120
leaq 0x1c97(%rip), %rsi      # 0x43dc
leaq 0x198(%rsp), %rbx
movl $0x1, %ecx
movq %rbx, %rdi
movq $-0x1, %rdx
callq 0x2290
movq 0x8(%rbx), %rcx
cmpq %rax, %rcx
jb 0x3545
movq %rax, 0x1a0(%rsp)
movq 0x198(%rsp), %rcx
movb $0x0, (%rcx,%rax)
movzbl 0x6(%rsp), %esi
cmpl $0x53, %esi
sete %al
cmpl $0x4e, %esi
sete %cl
movsbl %sil, %edx
movsbl 0x7(%rsp), %r8d
cmpl $0x53, %esi
je 0x27ab
cmpl $0x4e, %esi
jne 0x28ed
cmpb $0x45, %r8b
je 0x27be
movzbl %r8b, %esi
cmpl $0x57, %esi
jne 0x28ed
movl 0xe0(%rsp), %esi
movl 0xe4(%rsp), %ecx
leal 0x1(%rsi), %r9d
leal 0x1(%rcx), %r10d
subq $0x8, %rsp
leaq 0x19d9(%rip), %rdi      # 0x41b8
xorl %eax, %eax
pushq %r8
pushq %r10
pushq %rdx
callq 0x2030
addq $0x20, %rsp
leaq 0xa8(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
movq %r13, %rsi
callq 0x3740
movq 0xa8(%rsp), %rdi
movl $0x1, %edx
movq %r13, %rsi
movq 0x8(%rsp), %rcx
callq 0x21c0
cmpq $0x1, %rax
jne 0x2915
xorl %r10d, %r10d
movb 0x48(%rsp), %al
movb %al, %r10b
movabsq $0x200000000, %rbx      # imm = 0x200000000
movl $0x8000, %r12d          # imm = 0x8000
movl $0xffff8000, %r15d      # imm = 0xFFFF8000
movl 0x40(%rsp), %r9d
testl %r9d, %r9d
jle 0x2935
movl $0x2, %eax
xorl %ecx, %ecx
movq 0xa8(%rsp), %rdx
movb (%rdx,%rcx), %sil
leal -0x1(%rax), %edi
movslq %edi, %rdi
movb (%rdx,%rdi), %r8b
movb %r8b, (%rdx,%rcx)
movq 0xa8(%rsp), %rcx
movb %sil, (%rcx,%rdi)
movslq %eax, %rcx
addl $0x2, %eax
cmpq %rcx, %r13
jg 0x2860
testl %r9d, %r9d
jle 0x2935
movl $0xffff8000, %r15d      # imm = 0xFFFF8000
xorl %eax, %eax
movl $0x8000, %r12d          # imm = 0x8000
movq 0xa8(%rsp), %rdx
xorl %ecx, %ecx
movswl (%rdx,%rax), %esi
cmpl %esi, %r12d
jle 0x28d4
xorl %edi, %edi
cmpl $0xffff8000, %esi       # imm = 0xFFFF8000
sete %dil
addl %edi, %ecx
movl %esi, %edi
negw %di
cmovnol %esi, %r12d
jmp 0x28db
cmpl %esi, %r15d
cmovlel %esi, %r15d
shlq $0x20, %rax
addq %rbx, %rax
sarq $0x20, %rax
cmpq %r13, %rax
jl 0x28b2
jmp 0x2937
orb %al, %cl
cmovnel %r8d, %edx
leaq 0x1891(%rip), %rdi      # 0x418b
movl %edx, %esi
movq %r15, %rdx
xorl %eax, %eax
callq 0x2030
movl $0x1, %ebp
movq 0x8(%rsp), %rbx
jmp 0x351a
leaq 0x18c2(%rip), %rdi      # 0x41de
movq %rax, %rsi
xorl %eax, %eax
callq 0x2030
movl $0x1, %ebp
movq 0x8(%rsp), %rbx
jmp 0x3508
xorl %ecx, %ecx
movq 0x38(%rsp), %rax
addl %r10d, %eax
movq %rax, 0x38(%rsp)
leaq 0x18ba(%rip), %rdi      # 0x4205
movl %r12d, %esi
movl %r15d, %edx
xorl %eax, %eax
callq 0x2030
cvtsi2sd %r12d, %xmm0
cvtsi2sd %r15d, %xmm1
movsd %xmm0, 0x1c0(%rsp)
subsd %xmm0, %xmm1
movsd %xmm1, 0x1b8(%rsp)
movq 0x18(%rsp), %rax
movq 0x8(%rax), %rax
cmpb $0x61, (%rax)
jne 0x29b9
movl 0x40(%rsp), %edi
testl %edi, %edi
movq 0x38(%rsp), %r15
jle 0x2a60
movq 0xa8(%rsp), %rax
xorl %ecx, %ecx
addw $0x7fff, (%rax,%rcx)    # imm = 0x7FFF
shlq $0x20, %rcx
addq %rbx, %rcx
sarq $0x20, %rcx
cmpq %r13, %rcx
jl 0x29a1
jmp 0x2a24
movl 0x40(%rsp), %edi
testl %edi, %edi
movq 0x38(%rsp), %r15
jle 0x2a60
movq 0xa8(%rsp), %rax
xorl %ecx, %ecx
movsd 0x163c(%rip), %xmm0     # 0x4018
movzwl (%rax,%rcx), %esi
movw $0xffff, %dx            # imm = 0xFFFF
cmpl $0x8000, %esi           # imm = 0x8000
je 0x2a10
movswl %si, %edx
xorps %xmm1, %xmm1
cvtsi2sd %edx, %xmm1
subsd 0x1c0(%rsp), %xmm1
mulsd %xmm0, %xmm1
divsd 0x1b8(%rsp), %xmm1
cvttsd2si %xmm1, %edx
movw %dx, (%rax,%rcx)
shlq $0x20, %rcx
addq %rbx, %rcx
sarq $0x20, %rcx
cmpq %r13, %rcx
jl 0x29dc
testl %edi, %edi
jle 0x2a60
movl $0x2, %eax
xorl %ecx, %ecx
movq 0xa8(%rsp), %rdx
movb (%rdx,%rcx), %sil
leal -0x1(%rax), %edi
movslq %edi, %rdi
movb (%rdx,%rdi), %r8b
movb %r8b, (%rdx,%rcx)
movq 0xa8(%rsp), %rcx
movb %sil, (%rcx,%rdi)
movslq %eax, %rcx
addl $0x2, %eax
cmpq %rcx, %r13
jg 0x2a2f
movq %r13, 0x80(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x60(%rsp)
movq $0x0, 0x70(%rsp)
movslq %r15d, %rsi
leaq 0x298(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
movq %rsi, 0x238(%rsp)
callq 0x37a0
xorl %eax, %eax
movb 0x4(%rsp), %cl
movb %cl, %al
movq 0x98(%rsp), %r14
addl %eax, %r14d
movq %r14, 0x98(%rsp)
leal -0x1(%r14), %eax
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd 0x1557(%rip), %xmm3     # 0x4020
movapd %xmm3, %xmm4
divsd %xmm0, %xmm4
movsd 0x152f(%rip), %xmm0     # 0x4008
mulsd %xmm0, %xmm4
movsd 0x152b(%rip), %xmm1     # 0x4010
leal -0x1(%r15), %ecx
movl %ecx, 0xf0(%rsp)
cvtsi2sd %ecx, %xmm2
divsd %xmm1, %xmm4
movsd %xmm4, 0x240(%rsp)
divsd %xmm2, %xmm3
mulsd %xmm0, %xmm3
divsd %xmm1, %xmm3
movsd %xmm3, 0x248(%rsp)
movslq %eax, %rcx
movslq 0x30(%rsp), %rdx
movl 0x2c(%rsp), %eax
cmpl $0x2, %eax
movl $0x1, %esi
movl $0x1, %edi
cmovgel %eax, %edi
movl %edi, 0xf4(%rsp)
movl 0x14(%rsp), %eax
cmpl $0x2, %eax
cmovgel %eax, %esi
movl %esi, 0xe8(%rsp)
leaq (%rdx,%rdx), %r13
movq %rcx, 0x230(%rsp)
imulq %rcx, %rdx
addq %rdx, %rdx
movq %rdx, 0x228(%rsp)
movb $0x1, 0x5(%rsp)
movq 0x3467(%rip), %r14      # 0x5fd8
movq $0x0, 0x88(%rsp)
xorl %r12d, %r12d
movl $0x0, 0x5c(%rsp)
xorl %eax, %eax
movq $0x0, 0x90(%rsp)
movl %eax, 0xec(%rsp)
movq 0x238(%rsp), %rax
leaq (%r12,%rax), %rbx
movl %r12d, %eax
negl %eax
cmovsl %r12d, %eax
movl %eax, 0x30(%rsp)
movl %r12d, %eax
shrl $0x1f, %eax
movq %rax, 0x250(%rsp)
movb $0x1, 0x4(%rsp)
xorl %eax, %eax
movq $0x0, 0x18(%rsp)
movl %eax, 0x48(%rsp)
leaq 0x1651(%rip), %rdi      # 0x4230
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x2060
movq %rax, 0x20(%rsp)
movq %rax, %rdi
callq 0x2230
movq %rax, 0x50(%rsp)
movq 0x20(%rsp), %rdi
subq $0x8, %rsp
movq %rax, %rsi
movq 0xa0(%rsp), %rdx
movl %r15d, %ecx
movl $0x10, %r8d
xorl %r9d, %r9d
xorl %eax, %eax
pushq %rax
pushq %rax
pushq %rax
callq 0x2220
addq $0x20, %rsp
movq 0x20(%rsp), %rdi
movq 0x50(%rsp), %rsi
movl $0x2, %edx
movsd 0x240(%rsp), %xmm0
movsd 0x248(%rsp), %xmm1
callq 0x2050
movq %rbp, 0xc0(%rsp)
movabsq $0x5447482d4d545253, %rax # imm = 0x5447482D4D545253
movq %rax, 0xd0(%rsp)
movq $0x8, 0xc8(%rsp)
movb $0x0, 0xd8(%rsp)
leaq 0x1f8(%rsp), %rax
movq %rax, 0x1e8(%rsp)
movw $0x6d, 0x1f8(%rsp)
movq $0x1, 0x1f0(%rsp)
movl $0x148, %edx            # imm = 0x148
leaq 0x278(%rsp), %rdi
movq %r14, %rsi
leaq 0x15db(%rip), %rbp      # 0x4296
movq %rbp, %rcx
movsd 0x1c0(%rsp), %xmm0
movb $0x1, %al
callq 0x382a
movl $0x148, %edx            # imm = 0x148
leaq 0x258(%rsp), %rdi
movq %r14, %rsi
movq %rbp, %rcx
movsd 0x1b8(%rsp), %xmm0
movb $0x1, %al
callq 0x382a
movq 0x280(%rsp), %rdx
testq %rdx, %rdx
je 0x3535
movq 0x278(%rsp), %rax
movq %rax, 0x2b0(%rsp)
movq 0x260(%rsp), %rdx
testq %rdx, %rdx
je 0x3535
movq 0x258(%rsp), %rax
movq %rax, 0x2b8(%rsp)
movq 0xc8(%rsp), %rdx
testq %rdx, %rdx
je 0x3535
movq 0x1f0(%rsp), %rdx
testq %rdx, %rdx
je 0x3535
movq 0x20(%rsp), %rdi
movq 0x50(%rsp), %rsi
movq 0xc0(%rsp), %rdx
subq $0x8, %rsp
movl $0xffff8001, %ecx       # imm = 0xFFFF8001
movl $0x7fff, %r8d           # imm = 0x7FFF
xorl %r9d, %r9d
leaq 0x2b8(%rsp), %rax
pushq %rax
pushq 0x1f8(%rsp)
pushq $0x2
callq 0x20e0
addq $0x20, %rsp
testl %r15d, %r15d
jle 0x2dd9
movq 0x18(%rsp), %rax
decl %eax
cltq
movq 0x88(%rsp), %rcx
leaq (%rcx,%rax,2), %rax
xorl %ecx, %ecx
movq 0xa8(%rsp), %rdx
addq %rax, %rdx
movq 0x298(%rsp), %rsi
movq %rdx, (%rsi,%rcx,8)
addq %r13, %rax
leaq (%r12,%rcx), %rdx
incq %rdx
incq %rcx
cmpq %rbx, %rdx
jl 0x2db0
movq 0x20(%rsp), %rdi
movq 0x50(%rsp), %rsi
movq 0x298(%rsp), %rdx
callq 0x21e0
movq 0x20(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq -0xa31(%rip), %rdx      # 0x23d0
xorl %ecx, %ecx
callq 0x2280
movq 0x20(%rsp), %rdi
movq 0x50(%rsp), %rsi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x2070
leaq 0x20(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x20f0
movq 0x60(%rsp), %rbp
movq 0x68(%rsp), %rax
movq %rax, 0xa0(%rsp)
leaq 0x148(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x198(%rsp), %rsi
movq 0x1a0(%rsp), %rdx
addq %rsi, %rdx
leaq 0x138(%rsp), %r14
movq %r14, %rdi
callq 0x38dc
movq %r14, %rdi
leaq 0x1563(%rip), %rsi      # 0x43dc
callq 0x2260
leaq 0x168(%rsp), %r15
movl $0x1, %r14d
cmpl $0xa, 0x30(%rsp)
jb 0x2edb
movl $0x4, %r14d
movl 0x30(%rsp), %eax
cmpl $0x63, %eax
jbe 0x2ed2
cmpl $0x3e7, %eax            # imm = 0x3E7
jbe 0x2ed8
cmpl $0x2710, %eax           # imm = 0x2710
jb 0x2edb
movl %eax, %ecx
movl $0xd1b71759, %edx       # imm = 0xD1B71759
imulq %rdx, %rcx
shrq $0x2d, %rcx
addl $0x4, %r14d
cmpl $0x1869f, %eax          # imm = 0x1869F
movl %ecx, %eax
ja 0x2e9d
addl $-0x3, %r14d
jmp 0x2edb
addl $-0x2, %r14d
jmp 0x2edb
decl %r14d
movq %rbp, 0x40(%rsp)
movq 0x250(%rsp), %rbp
leal (%r14,%rbp), %esi
leaq 0x128(%rsp), %rax
movq %rax, 0x118(%rsp)
leaq 0x118(%rsp), %rdi
movl $0x2d, %edx
callq 0x2190
movq 0x118(%rsp), %rdi
addq %rbp, %rdi
movl %r14d, %esi
movl 0x30(%rsp), %edx
callq 0x396c
movq 0x138(%rsp), %rcx
movl $0xf, %esi
leaq 0x148(%rsp), %rax
cmpq %rax, %rcx
je 0x2f47
movq 0x148(%rsp), %rsi
movq 0x140(%rsp), %r8
movq 0x120(%rsp), %rdx
leaq (%rdx,%r8), %rax
cmpq %rsi, %rax
leaq 0x188(%rsp), %r14
jbe 0x2f8c
movl $0xf, %esi
leaq 0x128(%rsp), %rdi
cmpq %rdi, 0x118(%rsp)
je 0x2f87
movq 0x128(%rsp), %rsi
cmpq %rsi, %rax
jbe 0x2fa3
movq 0x118(%rsp), %rsi
leaq 0x138(%rsp), %rdi
callq 0x2040
jmp 0x2fb4
leaq 0x118(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2180
movq %r15, 0x158(%rsp)
movq (%rax), %rdx
leaq 0x10(%rax), %rcx
cmpq %rcx, %rdx
je 0x2fdd
movq %rdx, 0x158(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x168(%rsp)
jmp 0x2fe6
movupd (%rcx), %xmm0
movupd %xmm0, (%r15)
movq %rax, %rdx
addq $0x8, %rdx
movq 0x8(%rax), %rsi
movq %rsi, 0x160(%rsp)
movq %rcx, (%rax)
movq $0x0, (%rdx)
movb $0x0, (%rcx)
leaq 0x158(%rsp), %rdi
leaq 0x13c7(%rip), %rsi      # 0x43dc
callq 0x2260
movq %r14, 0x178(%rsp)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x3046
movq %rdx, 0x178(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x188(%rsp)
jmp 0x304f
movupd (%rcx), %xmm0
movupd %xmm0, (%r14)
movq 0x8(%rax), %rdx
movq %rdx, 0x180(%rsp)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
movq 0x18(%rsp), %rax
movl %eax, %r14d
negl %r14d
cmovsl %eax, %r14d
movl $0x1, %ebp
cmpl $0xa, %r14d
jb 0x30c6
movl $0x4, %ebp
movl %r14d, %eax
cmpl $0x63, %eax
jbe 0x30bf
cmpl $0x3e7, %eax            # imm = 0x3E7
jbe 0x30c4
cmpl $0x2710, %eax           # imm = 0x2710
jb 0x30c6
movl %eax, %ecx
movl $0xd1b71759, %edx       # imm = 0xD1B71759
imulq %rdx, %rcx
shrq $0x2d, %rcx
addl $0x4, %ebp
cmpl $0x1869f, %eax          # imm = 0x1869F
movl %ecx, %eax
ja 0x308c
addl $-0x3, %ebp
jmp 0x30c6
addl $-0x2, %ebp
jmp 0x30c6
decl %ebp
movq 0x18(%rsp), %r15
shrl $0x1f, %r15d
leal (%r15,%rbp), %esi
leaq 0x108(%rsp), %rax
movq %rax, 0xf8(%rsp)
leaq 0xf8(%rsp), %rdi
movl $0x2d, %edx
callq 0x2190
movl %r15d, %edi
addq 0xf8(%rsp), %rdi
movl %ebp, %esi
movl %r14d, %edx
callq 0x396c
movq 0x178(%rsp), %rcx
movl $0xf, %esi
leaq 0x188(%rsp), %r14
cmpq %r14, %rcx
je 0x312c
movq 0x188(%rsp), %rsi
movq 0x180(%rsp), %r8
movq 0x100(%rsp), %rdx
leaq (%rdx,%r8), %rax
cmpq %rsi, %rax
movq 0x38(%rsp), %r15
leaq 0x1d8(%rsp), %rbp
jbe 0x3176
movl $0xf, %esi
leaq 0x108(%rsp), %rdi
cmpq %rdi, 0xf8(%rsp)
je 0x3171
movq 0x108(%rsp), %rsi
cmpq %rsi, %rax
jbe 0x318d
movq 0xf8(%rsp), %rsi
leaq 0x178(%rsp), %rdi
callq 0x2040
jmp 0x319e
leaq 0xf8(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2180
movq %rbp, 0x1c8(%rsp)
movq (%rax), %rdx
leaq 0x10(%rax), %rcx
cmpq %rcx, %rdx
je 0x31c7
movq %rdx, 0x1c8(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x1d8(%rsp)
jmp 0x31d0
movupd (%rcx), %xmm0
movupd %xmm0, (%rbp)
movq %rax, %rdx
addq $0x8, %rdx
movq 0x8(%rax), %rsi
movq %rsi, 0x1d0(%rsp)
movq %rcx, (%rax)
movq $0x0, (%rdx)
movb $0x0, (%rcx)
leaq 0x1c8(%rsp), %rdi
leaq 0x1038(%rip), %rsi      # 0x4237
callq 0x2260
leaq 0x218(%rsp), %rsi
movq %rsi, 0x208(%rsp)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x3238
movq %rdx, 0x208(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x218(%rsp)
jmp 0x3240
movupd (%rcx), %xmm0
movupd %xmm0, (%rsi)
movq 0x8(%rax), %rdx
movq %rdx, 0x210(%rsp)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
movq 0x1c8(%rsp), %rdi
cmpq %rbp, %rdi
je 0x326d
callq 0x2120
movq 0xf8(%rsp), %rdi
leaq 0x108(%rsp), %rax
cmpq %rax, %rdi
je 0x3287
callq 0x2120
movq 0x178(%rsp), %rdi
cmpq %r14, %rdi
je 0x3299
callq 0x2120
movq 0x158(%rsp), %rdi
leaq 0x168(%rsp), %rax
cmpq %rax, %rdi
je 0x32b3
callq 0x2120
movq 0x118(%rsp), %rdi
leaq 0x128(%rsp), %rax
cmpq %rax, %rdi
je 0x32cd
callq 0x2120
movq 0x138(%rsp), %rdi
leaq 0x148(%rsp), %rax
cmpq %rax, %rdi
je 0x32e7
callq 0x2120
movq 0x208(%rsp), %rdi
leaq 0xf46(%rip), %rsi       # 0x423c
callq 0x21a0
movq %rax, %rbp
movq 0x60(%rsp), %rdi
movq 0x68(%rsp), %rsi
subq %rdi, %rsi
movl $0x1, %edx
movq %rax, %rcx
callq 0x2270
movq %rax, %r14
movq 0x60(%rsp), %rax
cmpq %rax, 0x68(%rsp)
je 0x332c
movq %rax, 0x68(%rsp)
cmpq $0x1, %r14
jne 0x3362
movq 0x90(%rsp), %rax
addq 0xa0(%rsp), %rax
subq 0x40(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x18(%rsp), %rax
addl 0xf0(%rsp), %eax
movq %rax, 0x18(%rsp)
jmp 0x337b
leaq 0xed6(%rip), %rdi       # 0x423f
movq %r14, %rsi
xorl %eax, %eax
callq 0x2030
movl $0x1, 0x5c(%rsp)
leaq 0x218(%rsp), %rax
testq %rbp, %rbp
je 0x3398
movq %rbp, %rdi
callq 0x2150
leaq 0x218(%rsp), %rax
movq 0x208(%rsp), %rdi
cmpq %rax, %rdi
je 0x33aa
callq 0x2120
movq 0x258(%rsp), %rdi
leaq 0x268(%rsp), %rax
cmpq %rax, %rdi
leaq 0xd0(%rsp), %rbp
je 0x33cc
callq 0x2120
movq 0x278(%rsp), %rdi
leaq 0x288(%rsp), %rax
cmpq %rax, %rdi
je 0x33e6
callq 0x2120
movq 0x1e8(%rsp), %rdi
leaq 0x1f8(%rsp), %rax
cmpq %rax, %rdi
je 0x3400
callq 0x2120
movq 0xc0(%rsp), %rdi
cmpq %rbp, %rdi
je 0x3412
callq 0x2120
cmpq $0x1, %r14
movq 0x2bbb(%rip), %r14      # 0x5fd8
movl 0x48(%rsp), %eax
jne 0x343b
incl %eax
cmpl 0x2c(%rsp), %eax
setl 0x4(%rsp)
cmpl 0xf4(%rsp), %eax
jne 0x2bd4
testb $0x1, 0x4(%rsp)
movl 0xec(%rsp), %eax
jne 0x3485
addq 0x230(%rsp), %r12
incl %eax
cmpl 0x14(%rsp), %eax
setl 0x5(%rsp)
movl %eax, %ecx
movq 0x88(%rsp), %rax
addq 0x228(%rsp), %rax
movq %rax, 0x88(%rsp)
movl %ecx, %eax
cmpl 0xe8(%rsp), %ecx
jne 0x2b96
testb $0x1, 0x5(%rsp)
movl 0x5c(%rsp), %ebp
jne 0x34da
movsd 0x90(%rsp), %xmm1
unpcklps 0xb90(%rip), %xmm1      # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0xb98(%rip), %xmm1      # 0x4040
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
cvtsi2sdq 0x80(%rsp), %xmm2
addsd %xmm1, %xmm0
divsd %xmm2, %xmm0
mulsd 0xb5e(%rip), %xmm0      # 0x4028
leaq 0xd96(%rip), %rdi       # 0x4267
movb $0x1, %al
callq 0x2030
xorl %ebp, %ebp
movq 0x298(%rsp), %rdi
testq %rdi, %rdi
movq 0x8(%rsp), %rbx
leaq 0x1a8(%rsp), %r12
je 0x34f9
callq 0x2120
movq 0x60(%rsp), %rdi
testq %rdi, %rdi
je 0x3508
callq 0x2120
movq 0xa8(%rsp), %rdi
testq %rdi, %rdi
je 0x351a
callq 0x2120
movq 0x198(%rsp), %rdi
cmpq %r12, %rdi
je 0x26e2
callq 0x2120
jmp 0x26e2
leaq 0xe1b(%rip), %rdi       # 0x4357
xorl %esi, %esi
xorl %eax, %eax
callq 0x21d0
leaq 0xda3(%rip), %rdi       # 0x42ef
leaq 0xd88(%rip), %rsi       # 0x42db
movq %rax, %rdx
xorl %eax, %eax
callq 0x21d0
movq %rax, %rbx
jmp 0x36f2
jmp 0x3567
movq %rax, %rbx
jmp 0x3713
movq %rax, %rbx
leaq 0xd0(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x372d
jmp 0x3728
movq %rax, %rbx
jmp 0x372d
movq %rax, %rbx
movq 0x1c8(%rsp), %rdi
cmpq %rbp, %rdi
je 0x35b8
callq 0x2120
jmp 0x35b8
movq %rax, %rbx
jmp 0x35d2
movq %rax, %rbx
jmp 0x360b
movq %rax, %rbx
movq 0xf8(%rsp), %rdi
leaq 0x108(%rsp), %rax
cmpq %rax, %rdi
je 0x35d2
callq 0x2120
movq 0x178(%rsp), %rdi
leaq 0x188(%rsp), %rax
cmpq %rax, %rdi
je 0x35f1
callq 0x2120
jmp 0x35f1
movq %rax, %rbx
movq 0x158(%rsp), %rdi
leaq 0x168(%rsp), %rax
cmpq %rax, %rdi
je 0x360b
callq 0x2120
movq 0x118(%rsp), %rdi
leaq 0x128(%rsp), %rax
cmpq %rax, %rdi
je 0x362a
callq 0x2120
jmp 0x362a
movq %rax, %rbx
movq 0x138(%rsp), %rdi
leaq 0x148(%rsp), %rax
cmpq %rax, %rdi
je 0x3678
callq 0x2120
jmp 0x3678
movq %rax, %rbx
movq 0x138(%rsp), %rdi
leaq 0x148(%rsp), %rax
cmpq %rax, %rdi
je 0x3678
jmp 0x363f
movq %rax, %rbx
jmp 0x36ac
jmp 0x366e
jmp 0x3675
movq %rax, %rbx
jmp 0x3692
movq %rax, %rbx
jmp 0x36e0
jmp 0x3675
movq %rax, %rbx
movq 0x258(%rsp), %rdi
leaq 0x268(%rsp), %rax
cmpq %rax, %rdi
je 0x3692
callq 0x2120
movq 0x278(%rsp), %rdi
leaq 0x288(%rsp), %rax
cmpq %rax, %rdi
je 0x36ac
callq 0x2120
movq 0x1e8(%rsp), %rdi
leaq 0x1f8(%rsp), %rax
cmpq %rax, %rdi
je 0x36c6
callq 0x2120
movq 0xc0(%rsp), %rdi
leaq 0xd0(%rsp), %rax
cmpq %rax, %rdi
je 0x36e0
callq 0x2120
movq 0x298(%rsp), %rdi
testq %rdi, %rdi
je 0x36f2
callq 0x2120
movq 0x60(%rsp), %rdi
testq %rdi, %rdi
je 0x3701
callq 0x2120
movq 0xa8(%rsp), %rdi
testq %rdi, %rdi
je 0x3713
callq 0x2120
movq 0x198(%rsp), %rdi
leaq 0x1a8(%rsp), %rax
cmpq %rax, %rdi
je 0x372d
callq 0x2120
movq 0x8(%rsp), %rdi
callq 0x2150
movq %rbx, %rdi
callq 0x2240
nop