// File: cloudinary[P]fuif/encoding/encoding.cpp
// Function: bool fuif_encode<FileIO>(FileIO&, Image const&, fuif_options&)
bool fuif_encode(IO& realio, const Image &image, fuif_options &options) {
    if (image.error) return false;
    if (image.nb_frames < 2) realio.fputs("FUIF");  // bytes 1-4 are fixed magic
    else realio.fputs("FUAF");                      // animation has different magic
    int nb_channels = image.real_nb_channels;
    write_big_endian_varint(realio, nb_channels + '0');
    int bit_depth = 1, maxval = 1;
    while (maxval < image.maxval) { bit_depth++; maxval = maxval*2 + 1; }
    write_big_endian_varint(realio, bit_depth + '&');
    write_big_endian_varint(realio, image.w-1);
    write_big_endian_varint(realio, image.h-1);
    if (image.nb_frames > 1) {
        write_big_endian_varint(realio, image.nb_frames-2);
        write_big_endian_varint(realio, image.den-1);
        if (image.num.size() == 0) write_big_endian_varint(realio, 0);
        else for (int i=0; i<image.num.size(); i++) write_big_endian_varint(realio, image.num[i]);
        write_big_endian_varint(realio, image.loops);
    }
    write_big_endian_varint(realio, image.colormodel);

    write_big_endian_varint(realio, options.max_properties);

    v_printf(2,"Encoding %i-channel, %i-bit, %ix%i %s%s image.\n", nb_channels, bit_depth, image.w, image.h, colormodel_name(image.colormodel,nb_channels), colorprofile_name(image.colormodel));

    BlobIO io;

    if (nb_channels < 1) return true; // is there any use for a zero-channel image?


    // encode transforms
    int nb_transforms = image.transform.size();
    write_big_endian_varint(io,nb_transforms);
    for (int i=0; i<nb_transforms; i++) {
        int id = image.transform[i].ID;
        int nb_params = (image.transform[i].has_parameters() ? image.transform[i].parameters.size() : 0);
        write_big_endian_varint(io, (nb_params << 4) + id);
        for (int j=0; j<nb_params; j++) write_big_endian_varint(io, image.transform[i].parameters[j]);
    }

    nb_channels = image.channel.size();

    int responsive_offsets[5] = {-1, -1, -1, -1, -1}; //   LQIP, 1/16 1/8 1/4 1/2

    // encode channel data
    for (int i=0; i<nb_channels; i++) {
        if (! image.channel[i].w || ! image.channel[i].h ) continue; // skip empty channels
        int predictor = 0;
        if (options.predictor.size() > i) predictor = options.predictor[i]; else if (options.predictor.size() > 0) predictor = options.predictor.back(); else predictor = 0;
//        if (predictor < 0) predictor = find_best_predictor(image.channel[i]);

        int j=i;
        Tree tree;
        size_t header_pos;

        if (!options.compress) {
            if (!fuif_encode_channels<BlobIO, RacOut<BlobIO>, FinalPropertySymbolCoder<FUIFBitChancePass2, RacOut<BlobIO>, MAX_BIT_DEPTH>, false, false >(io, tree, options, predictor, i, j, image, header_pos)) return false;
            continue;
        }

        // do several channels at a time (keep going until we hit a new downscale truncation point)
        for (int s=1; s<5; s++) if (j > image.downscales[s] && j < image.downscales[s+1]) j = image.downscales[s+1];

        // needed for interleaved (which we don't use), and maybe a good idea in any case: only clump same-dimension channels
        for (int k=i+1; k<=j; k++) if (image.channel[i].w != image.channel[k].w || image.channel[i].h != image.channel[k].h) { j=k-1; break; }

        if (options.max_group > 0 && j > i + options.max_group - 1) j = i + options.max_group - 1;

        DummyIO dummyio;
        if (!fuif_encode_channels<DummyIO, RacDummy<DummyIO>, PropertySymbolCoder<FUIFBitChancePass1, RacDummy<DummyIO>, MAX_BIT_DEPTH>, true, true >(dummyio, tree, options, predictor, i, j, image, header_pos)) return false;
        size_t before=io.ftell();
        if (!fuif_encode_channels<BlobIO, RacOut<BlobIO>, FinalPropertySymbolCoder<FUIFBitChancePass2, RacOut<BlobIO>, MAX_BIT_DEPTH>, false, true >(io, tree, options, predictor, i, j, image, header_pos)) return false;
        size_t after=io.ftell();
        float bits = (after-header_pos)*8.0;
        float pixels = 0.0;
        float ubits = 0.0;
        for (int k=i; k<=j; k++) {
            float chpixels = image.channel[k].w*image.channel[k].h;
            float uncompressed_bpp = maniac::util::ilog2(image.channel[k].maxval-image.channel[k].minval)+1;
            pixels += chpixels;
            if (image.channel[k].maxval > image.channel[k].minval)
                ubits += chpixels*uncompressed_bpp;
        }
        if (ubits > 0.0) ubits += 16; // rac flush might add 2 bytes
        float bpp=bits/pixels;
        float ubpp=ubits/pixels;

        v_printf(4,"Encoded channel %i-%i (%ix%i %s, range %i..%i), %i+%i bytes [%i-%i] (%f bpp; uncompressed estimate: %f bpp; %.2f%% reduction)\n", i,j, image.channel[i].w, image.channel[i].h, ch_describe(image,i), image.channel[i].minval, image.channel[i].maxval, after-header_pos, header_pos-before, before,after,
                bpp, ubpp, 100.0-100.0*bpp/ubpp);

        if ( bits >= ubits ) {
            io.fseek(before,SEEK_SET);
            if (!fuif_encode_channels<BlobIO, RacOut<BlobIO>, FinalPropertySymbolCoder<FUIFBitChancePass2, RacOut<BlobIO>, MAX_BIT_DEPTH>, false, false >(io, tree, options, predictor, i, j, image, header_pos)) return false;
            after=io.ftell();
            float bpp=(after-header_pos)*8.0/pixels;
            v_printf(4,"Rolled back. Encoded channel %i-%i UNCOMPRESSED (%ix%i %s, range %i..%i), %i+%i bytes (%f bpp)\n", i, j, image.channel[i].w, image.channel[i].h, ch_describe(image,i), image.channel[i].minval, image.channel[i].maxval, after-header_pos, header_pos-before, bpp);
        }
        for (int s=0; s<5; s++) {
            if (image.downscales[s] >= i && image.downscales[s] <= j) responsive_offsets[s] = after;
        }
        i=j;
    }

    int relative_offset = 0;
    for (int s=0; s<5; s++) {
        v_printf(3,"Responsive truncation point for size 1/%i after channel %i, at post-header position %i\n",responsive_sizes[s],image.downscales[s],responsive_offsets[s]);
        if (responsive_offsets[s] < 0) responsive_offsets[s] = io.ftell();
        int offset = responsive_offsets[s] - relative_offset;
        write_big_endian_varint(realio, (offset+TRUNCATION_OFFSET_RESOLUTION-1)/TRUNCATION_OFFSET_RESOLUTION);
        relative_offset = responsive_offsets[s];
    }

    if (options.debug) options.heatmap.recompute_minmax();

    io.fseek(0,SEEK_SET);
    int c;
    while ( (c=io.get_c()) != io.EOS ) realio.fputc(c); // TODO: copy the memory buffer more efficiently
    return true;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x210, %rsp            # imm = 0x210
movq %rdi, 0x200(%rsp)
movq %rsi, 0x1f8(%rsp)
movq %rdx, 0x1f0(%rsp)
movq 0x1f8(%rsp), %rax
testb $0x1, 0xa8(%rax)
je 0x1f872
movb $0x0, 0x20f(%rsp)
jmp 0x20b28
movq 0x1f8(%rsp), %rax
cmpl $0x2, 0x38(%rax)
jge 0x1f896
movq 0x200(%rsp), %rdi
leaq 0x27be2(%rip), %rsi     # 0x47471
callq 0x20b50
jmp 0x1f8aa
movq 0x200(%rsp), %rdi
leaq 0x27bd1(%rip), %rsi     # 0x47476
callq 0x20b50
movq 0x1f8(%rsp), %rax
movl 0x68(%rax), %eax
movl %eax, 0x1ec(%rsp)
movq 0x200(%rsp), %rdi
movl 0x1ec(%rsp), %eax
addl $0x30, %eax
movslq %eax, %rsi
movl $0x1, %edx
callq 0x20b80
movl $0x1, 0x1e8(%rsp)
movl $0x1, 0x1e4(%rsp)
movl 0x1e4(%rsp), %eax
movq 0x1f8(%rsp), %rcx
cmpl 0x60(%rcx), %eax
jge 0x1f92b
movl 0x1e8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1e8(%rsp)
movl 0x1e4(%rsp), %eax
shll %eax
addl $0x1, %eax
movl %eax, 0x1e4(%rsp)
jmp 0x1f8f1
movq 0x200(%rsp), %rdi
movl 0x1e8(%rsp), %eax
addl $0x26, %eax
movslq %eax, %rsi
movl $0x1, %edx
callq 0x20b80
movq 0x200(%rsp), %rdi
movq 0x1f8(%rsp), %rax
movl 0x30(%rax), %eax
subl $0x1, %eax
movslq %eax, %rsi
movl $0x1, %edx
callq 0x20b80
movq 0x200(%rsp), %rdi
movq 0x1f8(%rsp), %rax
movl 0x34(%rax), %eax
subl $0x1, %eax
movslq %eax, %rsi
movl $0x1, %edx
callq 0x20b80
movq 0x1f8(%rsp), %rax
cmpl $0x1, 0x38(%rax)
jle 0x1faca
movq 0x200(%rsp), %rdi
movq 0x1f8(%rsp), %rax
movl 0x38(%rax), %eax
subl $0x2, %eax
movslq %eax, %rsi
movl $0x1, %edx
callq 0x20b80
movq 0x200(%rsp), %rdi
movq 0x1f8(%rsp), %rax
movl 0x3c(%rax), %eax
subl $0x1, %eax
movslq %eax, %rsi
movl $0x1, %edx
callq 0x20b80
movq 0x1f8(%rsp), %rdi
addq $0x40, %rdi
callq 0x4d50
cmpq $0x0, %rax
jne 0x1fa1a
movq 0x200(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0x1, %edx
callq 0x20b80
jmp 0x1faac
movl $0x0, 0x1e0(%rsp)
movslq 0x1e0(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0x40, %rdi
callq 0x4d50
movq %rax, %rcx
movq 0xf0(%rsp), %rax
cmpq %rcx, %rax
jae 0x1faaa
movq 0x200(%rsp), %rax
movq %rax, 0xe8(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0x40, %rdi
movslq 0x1e0(%rsp), %rsi
callq 0x13560
movq 0xe8(%rsp), %rdi
movslq (%rax), %rsi
movl $0x1, %edx
callq 0x20b80
movl 0x1e0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1e0(%rsp)
jmp 0x1fa25
jmp 0x1faac
movq 0x200(%rsp), %rdi
movq 0x1f8(%rsp), %rax
movslq 0x58(%rax), %rsi
movl $0x1, %edx
callq 0x20b80
movq 0x200(%rsp), %rdi
movq 0x1f8(%rsp), %rax
movslq 0x70(%rax), %rsi
movl $0x1, %edx
callq 0x20b80
movq 0x200(%rsp), %rdi
movq 0x1f0(%rsp), %rax
movslq 0x10(%rax), %rsi
movl $0x1, %edx
callq 0x20b80
movl 0x1ec(%rsp), %eax
movl %eax, 0xd0(%rsp)
movl 0x1e8(%rsp), %eax
movl %eax, 0xd4(%rsp)
movq 0x1f8(%rsp), %rax
movl 0x30(%rax), %eax
movl %eax, 0xd8(%rsp)
movq 0x1f8(%rsp), %rax
movl 0x34(%rax), %eax
movl %eax, 0xdc(%rsp)
movq 0x1f8(%rsp), %rax
movl 0x70(%rax), %edi
movl 0x1ec(%rsp), %esi
callq 0x41c0
movq %rax, 0xe0(%rsp)
movq 0x1f8(%rsp), %rax
movl 0x70(%rax), %edi
callq 0x4380
movl 0xd0(%rsp), %edx
movl 0xd4(%rsp), %ecx
movl 0xd8(%rsp), %r8d
movl 0xdc(%rsp), %r9d
movq 0xe0(%rsp), %r10
movl $0x2, %edi
leaq 0x278d4(%rip), %rsi     # 0x4747b
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
movb $0x0, %al
callq 0x3a770
leaq 0x1b8(%rsp), %rdi
callq 0x20c20
cmpl $0x1, 0x1ec(%rsp)
jge 0x1fbe6
movb $0x1, 0x20f(%rsp)
movl $0x1, 0x1b4(%rsp)
jmp 0x20b0a
movq 0x1f8(%rsp), %rdi
addq $0x18, %rdi
callq 0x4a70
movl %eax, 0x1b0(%rsp)
movslq 0x1b0(%rsp), %rsi
leaq 0x1b8(%rsp), %rdi
movl $0x1, %edx
callq 0x20c60
jmp 0x1fc1a
movl $0x0, 0x1a0(%rsp)
movl 0x1a0(%rsp), %eax
cmpl 0x1b0(%rsp), %eax
jge 0x1fdab
movq 0x1f8(%rsp), %rdi
addq $0x18, %rdi
movslq 0x1a0(%rsp), %rsi
callq 0x20d00
movl (%rax), %eax
movl %eax, 0x19c(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0x18, %rdi
movslq 0x1a0(%rsp), %rsi
callq 0x20d00
movq %rax, %rdi
callq 0x20d20
movb %al, 0xcf(%rsp)
jmp 0x1fc85
movb 0xcf(%rsp), %al
testb $0x1, %al
jne 0x1fc92
jmp 0x1fcc1
movq 0x1f8(%rsp), %rdi
addq $0x18, %rdi
movslq 0x1a0(%rsp), %rsi
callq 0x20d00
movq %rax, %rdi
addq $0x8, %rdi
callq 0x4d50
movq %rax, 0xc0(%rsp)
jmp 0x1fccd
xorl %eax, %eax
movq %rax, 0xc0(%rsp)
jmp 0x1fccd
movq 0xc0(%rsp), %rax
movl %eax, 0x198(%rsp)
movl 0x198(%rsp), %eax
shll $0x4, %eax
movl 0x19c(%rsp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
leaq 0x1b8(%rsp), %rdi
movl $0x1, %edx
callq 0x20c60
jmp 0x1fd06
movl $0x0, 0x194(%rsp)
movl 0x194(%rsp), %eax
cmpl 0x198(%rsp), %eax
jge 0x1fd93
movq 0x1f8(%rsp), %rdi
addq $0x18, %rdi
movslq 0x1a0(%rsp), %rsi
callq 0x20d00
movq %rax, %rdi
addq $0x8, %rdi
movslq 0x194(%rsp), %rsi
callq 0x13560
movslq (%rax), %rsi
leaq 0x1b8(%rsp), %rdi
movl $0x1, %edx
callq 0x20c60
jmp 0x1fd65
jmp 0x1fd67
movl 0x194(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x194(%rsp)
jmp 0x1fd11
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a8(%rsp)
movl %eax, 0x1a4(%rsp)
jmp 0x20b19
jmp 0x1fd95
movl 0x1a0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1a0(%rsp)
jmp 0x1fc25
movq 0x1f8(%rsp), %rdi
callq 0x4b80
movl %eax, 0x1ec(%rsp)
movq 0x274ea(%rip), %rax     # 0x472b0
movq %rax, 0x180(%rsp)
movq 0x274e3(%rip), %rax     # 0x472b8
movq %rax, 0x188(%rsp)
movl 0x274dd(%rip), %eax     # 0x472c0
movl %eax, 0x190(%rsp)
movl $0x0, 0x17c(%rsp)
movl 0x17c(%rsp), %eax
cmpl 0x1ec(%rsp), %eax
jge 0x2097f
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
cmpl $0x0, 0x18(%rax)
je 0x1fe3f
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
cmpl $0x0, 0x1c(%rax)
jne 0x1fe44
jmp 0x20969
movl $0x0, 0x178(%rsp)
movq 0x1f0(%rsp), %rdi
addq $0x28, %rdi
callq 0x4d50
movslq 0x17c(%rsp), %rcx
cmpq %rcx, %rax
jbe 0x1fe91
movq 0x1f0(%rsp), %rdi
addq $0x28, %rdi
movslq 0x17c(%rsp), %rsi
callq 0x12190
movl (%rax), %eax
movl %eax, 0x178(%rsp)
jmp 0x1fed1
movq 0x1f0(%rsp), %rdi
addq $0x28, %rdi
callq 0x4d50
cmpq $0x0, %rax
jbe 0x1fec4
movq 0x1f0(%rsp), %rdi
addq $0x28, %rdi
callq 0x12b00
movl (%rax), %eax
movl %eax, 0x178(%rsp)
jmp 0x1fecf
movl $0x0, 0x178(%rsp)
jmp 0x1fed1
movl 0x17c(%rsp), %eax
movl %eax, 0x174(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x20d80
jmp 0x1feee
movq 0x1f0(%rsp), %rax
testb $0x1, 0x1c(%rax)
jne 0x1ffb2
movq 0x1f0(%rsp), %rdx
movl 0x178(%rsp), %ecx
movl 0x17c(%rsp), %r8d
movl 0x174(%rsp), %r9d
movq 0x1f8(%rsp), %rsi
movq %rsp, %rax
leaq 0x150(%rsp), %rdi
movq %rdi, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x1b8(%rsp), %rdi
leaq 0x158(%rsp), %rsi
callq 0x20e10
movb %al, 0xbf(%rsp)
jmp 0x1ff57
movb 0xbf(%rsp), %al
testb $0x1, %al
jne 0x1ffa2
jmp 0x1ff64
movb $0x0, 0x20f(%rsp)
movl $0x1, 0x1b4(%rsp)
jmp 0x2093b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a8(%rsp)
movl %eax, 0x1a4(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x22e10
jmp 0x20b19
movl $0xf, 0x1b4(%rsp)
jmp 0x2093b
movl $0x1, 0x14c(%rsp)
cmpl $0x5, 0x14c(%rsp)
jge 0x2004b
movl 0x174(%rsp), %eax
movq 0x1f8(%rsp), %rcx
movslq 0x14c(%rsp), %rdx
cmpl 0x90(%rcx,%rdx,4), %eax
jle 0x20033
movl 0x174(%rsp), %eax
movq 0x1f8(%rsp), %rcx
movl 0x14c(%rsp), %edx
addl $0x1, %edx
movslq %edx, %rdx
cmpl 0x90(%rcx,%rdx,4), %eax
jge 0x20033
movq 0x1f8(%rsp), %rax
movl 0x14c(%rsp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl 0x90(%rax,%rcx,4), %eax
movl %eax, 0x174(%rsp)
jmp 0x20035
movl 0x14c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14c(%rsp)
jmp 0x1ffbd
movl 0x17c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x148(%rsp)
movl 0x148(%rsp), %eax
cmpl 0x174(%rsp), %eax
jg 0x20121
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movl 0x18(%rax), %eax
movl %eax, 0xb8(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x148(%rsp), %rsi
callq 0x13390
movq %rax, %rcx
movl 0xb8(%rsp), %eax
cmpl 0x18(%rcx), %eax
jne 0x200f6
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movl 0x1c(%rax), %eax
movl %eax, 0xb4(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x148(%rsp), %rsi
callq 0x13390
movq %rax, %rcx
movl 0xb4(%rsp), %eax
cmpl 0x1c(%rcx), %eax
je 0x20109
movl 0x148(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x174(%rsp)
jmp 0x20121
jmp 0x2010b
movl 0x148(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x148(%rsp)
jmp 0x2005c
movq 0x1f0(%rsp), %rax
cmpl $0x0, 0x20(%rax)
jle 0x2016b
movl 0x174(%rsp), %eax
movl 0x17c(%rsp), %ecx
movq 0x1f0(%rsp), %rdx
addl 0x20(%rdx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0x2016b
movl 0x17c(%rsp), %eax
movq 0x1f0(%rsp), %rcx
addl 0x20(%rcx), %eax
subl $0x1, %eax
movl %eax, 0x174(%rsp)
leaq 0x144(%rsp), %rdi
callq 0x216b0
jmp 0x2017a
movq 0x1f0(%rsp), %rdx
movl 0x178(%rsp), %ecx
movl 0x17c(%rsp), %r8d
movl 0x174(%rsp), %r9d
movq 0x1f8(%rsp), %rsi
movq %rsp, %rax
leaq 0x150(%rsp), %rdi
movq %rdi, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x144(%rsp), %rdi
leaq 0x158(%rsp), %rsi
callq 0x216d0
movb %al, 0xb3(%rsp)
jmp 0x201d1
movb 0xb3(%rsp), %al
testb $0x1, %al
jne 0x201f6
jmp 0x201de
movb $0x0, 0x20f(%rsp)
movl $0x1, 0x1b4(%rsp)
jmp 0x2093b
leaq 0x1b8(%rsp), %rdi
callq 0x221a0
movl %eax, 0xac(%rsp)
jmp 0x2020c
movl 0xac(%rsp), %eax
cltq
movq %rax, 0x138(%rsp)
movq 0x1f0(%rsp), %rdx
movl 0x178(%rsp), %ecx
movl 0x17c(%rsp), %r8d
movl 0x174(%rsp), %r9d
movq 0x1f8(%rsp), %rsi
movq %rsp, %rax
leaq 0x150(%rsp), %rdi
movq %rdi, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x1b8(%rsp), %rdi
leaq 0x158(%rsp), %rsi
callq 0x221b0
movb %al, 0xab(%rsp)
jmp 0x20274
movb 0xab(%rsp), %al
testb $0x1, %al
jne 0x20299
jmp 0x20281
movb $0x0, 0x20f(%rsp)
movl $0x1, 0x1b4(%rsp)
jmp 0x2093b
leaq 0x1b8(%rsp), %rdi
callq 0x221a0
movl %eax, 0xa4(%rsp)
jmp 0x202af
movl 0xa4(%rsp), %eax
cltq
movq %rax, 0x130(%rsp)
movq 0x130(%rsp), %rax
movq 0x150(%rsp), %rcx
subq %rcx, %rax
movq %rax, %xmm0
movaps 0x27051(%rip), %xmm1    # 0x47330
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x27055(%rip), %xmm1    # 0x47340
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd 0x27006(%rip), %xmm1    # 0x47308
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x12c(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, 0x128(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, 0x124(%rsp)
movl 0x17c(%rsp), %eax
movl %eax, 0x120(%rsp)
movl 0x120(%rsp), %eax
cmpl 0x174(%rsp), %eax
jg 0x204ab
movq 0x1f8(%rsp), %rdi
movslq 0x120(%rsp), %rsi
callq 0x13390
movl 0x18(%rax), %eax
movl %eax, 0x98(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x120(%rsp), %rsi
callq 0x13390
movq %rax, %rcx
movl 0x98(%rsp), %eax
movl 0x1c(%rcx), %ecx
imull %ecx, %eax
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x11c(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x120(%rsp), %rsi
callq 0x13390
movswl 0x22(%rax), %eax
movl %eax, 0x9c(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x120(%rsp), %rsi
callq 0x13390
movl 0x9c(%rsp), %edi
movswl 0x20(%rax), %eax
subl %eax, %edi
callq 0x1ebd0
movl %eax, 0xa0(%rsp)
jmp 0x203ee
movl 0xa0(%rsp), %eax
addl $0x1, %eax
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x118(%rsp)
movss 0x11c(%rsp), %xmm0
addss 0x128(%rsp), %xmm0
movss %xmm0, 0x128(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x120(%rsp), %rsi
callq 0x13390
movswl 0x22(%rax), %eax
movl %eax, 0x94(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x120(%rsp), %rsi
callq 0x13390
movq %rax, %rcx
movl 0x94(%rsp), %eax
movswl 0x20(%rcx), %ecx
cmpl %ecx, %eax
jle 0x20493
movss 0x11c(%rsp), %xmm0
movss 0x118(%rsp), %xmm2
movss 0x124(%rsp), %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x124(%rsp)
jmp 0x20495
movl 0x120(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x120(%rsp)
jmp 0x20339
movss 0x124(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x204db
movss 0x26e87(%rip), %xmm0    # 0x47350
addss 0x124(%rsp), %xmm0
movss %xmm0, 0x124(%rsp)
movss 0x12c(%rsp), %xmm0
movss 0x128(%rsp), %xmm1
divss %xmm1, %xmm0
movss %xmm0, 0x114(%rsp)
movss 0x124(%rsp), %xmm0
movss 0x128(%rsp), %xmm1
divss %xmm1, %xmm0
movss %xmm0, 0x110(%rsp)
movl 0x17c(%rsp), %eax
movl %eax, 0x84(%rsp)
movl 0x174(%rsp), %ecx
movl %ecx, 0x88(%rsp)
movq 0x1f8(%rsp), %rdi
movslq %eax, %rsi
callq 0x13390
movl 0x18(%rax), %eax
movl %eax, 0x8c(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movl 0x1c(%rax), %eax
movl %eax, 0x90(%rsp)
movq 0x1f8(%rsp), %rdi
movl 0x17c(%rsp), %esi
callq 0x1ec10
movq %rax, 0x78(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movswl 0x20(%rax), %eax
movl %eax, 0x74(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movl 0x74(%rsp), %edi
movq 0x78(%rsp), %rsi
movl 0x84(%rsp), %edx
movl 0x88(%rsp), %ecx
movl 0x8c(%rsp), %r8d
movl 0x90(%rsp), %r9d
movswl 0x22(%rax), %r10d
movq 0x130(%rsp), %r15
movq 0x150(%rsp), %rbx
movq %r15, %r11
subq %rbx, %r11
movq 0x138(%rsp), %r14
subq %r14, %rbx
movss 0x114(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movss 0x110(%rsp), %xmm1
cvtss2sd %xmm1, %xmm1
movsd 0x26ce8(%rip), %xmm2    # 0x47310
movaps %xmm0, %xmm3
mulsd %xmm2, %xmm3
divsd %xmm1, %xmm3
subsd %xmm3, %xmm2
movq %rsp, %rax
movq %r15, 0x30(%rax)
movq %r14, 0x28(%rax)
movq %rbx, 0x20(%rax)
movq %r11, 0x18(%rax)
movl %r10d, 0x10(%rax)
movl %edi, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x26e50(%rip), %rsi     # 0x474ab
movl $0x4, %edi
movb $0x3, %al
callq 0x3a770
jmp 0x20669
movss 0x12c(%rsp), %xmm0
ucomiss 0x124(%rsp), %xmm0
jb 0x2089f
movq 0x138(%rsp), %rsi
leaq 0x1b8(%rsp), %rdi
xorl %edx, %edx
callq 0x22d90
jmp 0x20699
movq 0x1f0(%rsp), %rdx
movl 0x178(%rsp), %ecx
movl 0x17c(%rsp), %r8d
movl 0x174(%rsp), %r9d
movq 0x1f8(%rsp), %rsi
movq %rsp, %rax
leaq 0x150(%rsp), %rdi
movq %rdi, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x1b8(%rsp), %rdi
leaq 0x158(%rsp), %rsi
callq 0x20e10
movb %al, 0x73(%rsp)
jmp 0x206ed
movb 0x73(%rsp), %al
testb $0x1, %al
jne 0x2070f
jmp 0x206f7
movb $0x0, 0x20f(%rsp)
movl $0x1, 0x1b4(%rsp)
jmp 0x2093b
leaq 0x1b8(%rsp), %rdi
callq 0x221a0
movl %eax, 0x6c(%rsp)
jmp 0x20722
movl 0x6c(%rsp), %eax
cltq
movq %rax, 0x130(%rsp)
movq 0x130(%rsp), %rax
movq 0x150(%rsp), %rcx
subq %rcx, %rax
movq %rax, %xmm0
movaps 0x26be1(%rip), %xmm1    # 0x47330
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x26be5(%rip), %xmm1    # 0x47340
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd 0x26b96(%rip), %xmm1    # 0x47308
mulsd %xmm1, %xmm0
movss 0x128(%rsp), %xmm1
cvtss2sd %xmm1, %xmm1
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x10c(%rsp)
movl 0x17c(%rsp), %eax
movl %eax, 0x5c(%rsp)
movl 0x174(%rsp), %ecx
movl %ecx, 0x60(%rsp)
movq 0x1f8(%rsp), %rdi
movslq %eax, %rsi
callq 0x13390
movl 0x18(%rax), %eax
movl %eax, 0x64(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movl 0x1c(%rax), %eax
movl %eax, 0x68(%rsp)
movq 0x1f8(%rsp), %rdi
movl 0x17c(%rsp), %esi
callq 0x1ec10
movq %rax, 0x50(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movswl 0x20(%rax), %eax
movl %eax, 0x4c(%rsp)
movq 0x1f8(%rsp), %rdi
movslq 0x17c(%rsp), %rsi
callq 0x13390
movl 0x4c(%rsp), %edi
movq 0x50(%rsp), %rsi
movl 0x5c(%rsp), %edx
movl 0x60(%rsp), %ecx
movl 0x64(%rsp), %r8d
movl 0x68(%rsp), %r9d
movswl 0x22(%rax), %r10d
movq 0x130(%rsp), %r11
movq 0x150(%rsp), %rbx
subq %rbx, %r11
movq 0x138(%rsp), %rax
subq %rax, %rbx
movss 0x10c(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movq %rsp, %rax
movq %rbx, 0x20(%rax)
movq %r11, 0x18(%rax)
movl %r10d, 0x10(%rax)
movl %edi, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x26c9b(%rip), %rsi     # 0x4752a
movl $0x4, %edi
movb $0x1, %al
callq 0x3a770
jmp 0x2089d
jmp 0x2089f
movl $0x0, 0x108(%rsp)
cmpl $0x5, 0x108(%rsp)
jge 0x20922
movq 0x1f8(%rsp), %rax
movslq 0x108(%rsp), %rcx
movl 0x90(%rax,%rcx,4), %eax
cmpl 0x17c(%rsp), %eax
jl 0x2090d
movq 0x1f8(%rsp), %rax
movslq 0x108(%rsp), %rcx
movl 0x90(%rax,%rcx,4), %eax
cmpl 0x174(%rsp), %eax
jg 0x2090d
movq 0x130(%rsp), %rax
movl %eax, %ecx
movslq 0x108(%rsp), %rax
movl %ecx, 0x180(%rsp,%rax,4)
jmp 0x2090f
movl 0x108(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x108(%rsp)
jmp 0x208aa
movl 0x174(%rsp), %eax
movl %eax, 0x17c(%rsp)
movl $0x0, 0x1b4(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x22e10
movl 0x1b4(%rsp), %eax
movl %eax, 0x48(%rsp)
testl %eax, %eax
je 0x20967
jmp 0x20959
movl 0x48(%rsp), %eax
subl $0xf, %eax
je 0x20969
jmp 0x20b0a
jmp 0x20969
movl 0x17c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x17c(%rsp)
jmp 0x1fdf5
movl $0x0, 0x104(%rsp)
movl $0x0, 0x100(%rsp)
cmpl $0x5, 0x100(%rsp)
jge 0x20a80
movslq 0x100(%rsp), %rax
leaq 0x2691e(%rip), %rcx     # 0x472d0
movl (%rcx,%rax,4), %edx
movq 0x1f8(%rsp), %rcx
movl 0x90(%rcx,%rax,4), %ecx
movl 0x180(%rsp,%rax,4), %r8d
leaq 0x26bb7(%rip), %rsi     # 0x4758a
xorl %eax, %eax
movl $0x3, %edi
callq 0x3a770
jmp 0x209e1
movslq 0x100(%rsp), %rax
cmpl $0x0, 0x180(%rsp,%rax,4)
jge 0x20a19
leaq 0x1b8(%rsp), %rdi
callq 0x221a0
movl %eax, 0x44(%rsp)
jmp 0x20a06
movl 0x44(%rsp), %ecx
movslq 0x100(%rsp), %rax
movl %ecx, 0x180(%rsp,%rax,4)
movslq 0x100(%rsp), %rax
movl 0x180(%rsp,%rax,4), %eax
movl 0x104(%rsp), %ecx
subl %ecx, %eax
movl %eax, 0xfc(%rsp)
movq 0x200(%rsp), %rdi
movslq 0xfc(%rsp), %rsi
movl $0x1, %edx
callq 0x20b80
jmp 0x20a54
movslq 0x100(%rsp), %rax
movl 0x180(%rsp,%rax,4), %eax
movl %eax, 0x104(%rsp)
movl 0x100(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x100(%rsp)
jmp 0x20995
movq 0x1f0(%rsp), %rax
testb $0x1, 0x24(%rax)
je 0x20aa3
movq 0x1f0(%rsp), %rdi
addq $0x40, %rdi
callq 0x22e20
jmp 0x20aa1
jmp 0x20aa3
xorl %edx, %edx
movl %edx, %esi
leaq 0x1b8(%rsp), %rdi
callq 0x22d90
jmp 0x20ab6
jmp 0x20ab8
leaq 0x1b8(%rsp), %rdi
callq 0x22ec0
movl %eax, 0x40(%rsp)
jmp 0x20acb
movl 0x40(%rsp), %eax
movl %eax, 0xf8(%rsp)
cmpl 0x1d8(%rsp), %eax
je 0x20af7
movq 0x200(%rsp), %rdi
movl 0xf8(%rsp), %esi
callq 0x22f10
jmp 0x20af5
jmp 0x20ab8
movb $0x1, 0x20f(%rsp)
movl $0x1, 0x1b4(%rsp)
leaq 0x1b8(%rsp), %rdi
callq 0x22f40
jmp 0x20b28
leaq 0x1b8(%rsp), %rdi
callq 0x22f40
jmp 0x20b3e
movb 0x20f(%rsp), %al
andb $0x1, %al
addq $0x210, %rsp            # imm = 0x210
popq %rbx
popq %r14
popq %r15
retq
movq 0x1a8(%rsp), %rdi
callq 0x36a0
nopl (%rax,%rax)