// File: lemire[P]runningmaxmin/./runningmaxmin.h
// Function: GilKimmel::GilKimmel(std::vector<double, std::allocator<double>>&, int)
GilKimmel(std::vector<floattype> & array, int width)
        : maxvalues(array.size() - width + 1),
          minvalues(array.size() - width + 1) {
        std::vector<floattype> R(array.size() + 1);
        std::vector<floattype> S(array.size() + 1);
        computePrefixSuffixMax(R, S, array,
                               width); // implements the cut in the middle trick
        for (int j = 0; j < static_cast<int>(array.size()) - width + 1;
             j += width) {
            const int endofblock =
                std::min(j + width, static_cast<int>(array.size()) - width + 1);
            int begin = j;
            int end = endofblock;
            int midpoint = (end - begin + 1) / 2 + begin;
            while (midpoint != end) {
                if (S[midpoint + width - 1] <= R[midpoint]) {
                    begin = midpoint;
                    midpoint = (end - begin + 1) / 2 + begin;
                } else {
                    end = midpoint;
                    midpoint = (end - begin + 1) / 2 + begin;
                }
            }
            for (int jj = j; jj < midpoint; ++jj) {
                maxvalues[jj] = R[jj];
            }
            for (int jj = midpoint; jj < endofblock; ++jj) {
                maxvalues[jj] = S[jj + width - 1];
            }
        }
        computePrefixSuffixMin(R, S, array,
                               width); // implements the cut in the middle trick
        for (int j = 0; j < static_cast<int>(array.size()) - width + 1;
             j += width) {
            const int endofblock =
                std::min(j + width, static_cast<int>(array.size()) - width + 1);
            int begin = j;
            int end = endofblock;
            int midpoint = (end - begin + 1) / 2 + begin;
            while (midpoint != end) {
                if (S[midpoint + width - 1] >= R[midpoint]) {
                    begin = midpoint;
                    midpoint = (end - begin + 1) / 2 + begin;
                } else {
                    end = midpoint;
                    midpoint = (end - begin + 1) / 2 + begin;
                }
            }
            for (int jj = j; jj < midpoint; ++jj) {
                minvalues[jj] = R[jj];
            }
            for (int jj = midpoint; jj < endofblock; ++jj) {
                minvalues[jj] = S[jj + width - 1];
            }
        }
    }

// Assembly:
subq $0x158, %rsp            # imm = 0x158
movq %rdi, 0x150(%rsp)
movq %rsi, 0x148(%rsp)
movl %edx, 0x144(%rsp)
movq 0x150(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x77c0
movq 0x88(%rsp), %rax
leaq 0xedae(%rip), %rcx      # 0x13c90
addq $0x10, %rcx
movq %rcx, (%rax)
addq $0x8, %rax
movq %rax, 0x90(%rsp)
movq 0x148(%rsp), %rdi
callq 0x3410
movslq 0x144(%rsp), %rcx
subq %rcx, %rax
incq %rax
movq %rax, 0x98(%rsp)
leaq 0x143(%rsp), %rdi
movq %rdi, 0xa0(%rsp)
callq 0x74c0
movq 0x90(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq 0xa0(%rsp), %rdx
callq 0x74d0
jmp 0x4f4c
leaq 0x143(%rsp), %rdi
callq 0x7550
movq 0x88(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x70(%rsp)
movq 0x148(%rsp), %rdi
callq 0x3410
movslq 0x144(%rsp), %rcx
subq %rcx, %rax
incq %rax
movq %rax, 0x78(%rsp)
leaq 0x133(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x74c0
movq 0x70(%rsp), %rdi
movq 0x78(%rsp), %rsi
movq 0x80(%rsp), %rdx
callq 0x74d0
jmp 0x4fb8
leaq 0x133(%rsp), %rdi
callq 0x7550
movq 0x148(%rsp), %rdi
callq 0x3410
incq %rax
movq %rax, 0x60(%rsp)
leaq 0x117(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x74c0
movq 0x60(%rsp), %rsi
movq 0x68(%rsp), %rdx
leaq 0x118(%rsp), %rdi
callq 0x74d0
jmp 0x5005
leaq 0x117(%rsp), %rdi
callq 0x7550
movq 0x148(%rsp), %rdi
callq 0x3410
incq %rax
movq %rax, 0x50(%rsp)
leaq 0xf7(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x74c0
movq 0x50(%rsp), %rsi
movq 0x58(%rsp), %rdx
leaq 0xf8(%rsp), %rdi
callq 0x74d0
jmp 0x5052
leaq 0xf7(%rsp), %rdi
callq 0x7550
movq 0x88(%rsp), %rdi
movq 0x148(%rsp), %rcx
movl 0x144(%rsp), %r8d
leaq 0x118(%rsp), %rsi
leaq 0xf8(%rsp), %rdx
callq 0x94b0
jmp 0x508e
movl $0x0, 0xf0(%rsp)
movl 0xf0(%rsp), %eax
movl %eax, 0x4c(%rsp)
movq 0x148(%rsp), %rdi
callq 0x3410
movq %rax, %rcx
movl 0x4c(%rsp), %eax
subl 0x144(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x5415
movl 0xf0(%rsp), %eax
movl 0x144(%rsp), %ecx
addl %ecx, %eax
movl %eax, 0xe8(%rsp)
movq 0x148(%rsp), %rdi
callq 0x3410
movl 0x144(%rsp), %ecx
subl %ecx, %eax
incl %eax
movl %eax, 0xe4(%rsp)
leaq 0xe8(%rsp), %rdi
leaq 0xe4(%rsp), %rsi
callq 0x99f0
movq %rax, 0x40(%rsp)
jmp 0x511c
movq 0x40(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xec(%rsp)
movl 0xf0(%rsp), %eax
movl %eax, 0xe0(%rsp)
movl 0xec(%rsp), %eax
movl %eax, 0xdc(%rsp)
movl 0xdc(%rsp), %eax
subl 0xe0(%rsp), %eax
addl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0xe0(%rsp), %eax
movl %eax, 0xd8(%rsp)
movl 0xd8(%rsp), %eax
cmpl 0xdc(%rsp), %eax
je 0x5307
movl 0xd8(%rsp), %eax
addl 0x144(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rsi
leaq 0xf8(%rsp), %rdi
callq 0x3430
vmovsd (%rax), %xmm0
vmovsd %xmm0, 0x38(%rsp)
movslq 0xd8(%rsp), %rsi
leaq 0x118(%rsp), %rdi
callq 0x3430
vmovsd 0x38(%rsp), %xmm1
vmovsd (%rax), %xmm0
vucomisd %xmm1, %xmm0
jb 0x52cd
movl 0xd8(%rsp), %eax
movl %eax, 0xe0(%rsp)
movl 0xdc(%rsp), %eax
subl 0xe0(%rsp), %eax
addl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0xe0(%rsp), %eax
movl %eax, 0xd8(%rsp)
jmp 0x5302
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0x143(%rsp), %rdi
callq 0x7550
jmp 0x5746
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0x133(%rsp), %rdi
callq 0x7550
jmp 0x5739
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0x117(%rsp), %rdi
callq 0x7550
jmp 0x572f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0xf7(%rsp), %rdi
callq 0x7550
jmp 0x5722
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0xf8(%rsp), %rdi
callq 0x7660
jmp 0x5722
movl 0xd8(%rsp), %eax
movl %eax, 0xdc(%rsp)
movl 0xdc(%rsp), %eax
subl 0xe0(%rsp), %eax
addl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0xe0(%rsp), %eax
movl %eax, 0xd8(%rsp)
jmp 0x516d
movl 0xf0(%rsp), %eax
movl %eax, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
cmpl 0xd8(%rsp), %eax
jge 0x537a
movslq 0xd4(%rsp), %rsi
leaq 0x118(%rsp), %rdi
callq 0x3430
movq 0x88(%rsp), %rdi
vmovsd (%rax), %xmm0
vmovsd %xmm0, 0x30(%rsp)
addq $0x8, %rdi
movslq 0xd4(%rsp), %rsi
callq 0x3430
vmovsd 0x30(%rsp), %xmm0
vmovsd %xmm0, (%rax)
movl 0xd4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd4(%rsp)
jmp 0x5315
movl 0xd8(%rsp), %eax
movl %eax, 0xd0(%rsp)
movl 0xd0(%rsp), %eax
cmpl 0xec(%rsp), %eax
jge 0x53f9
movl 0xd0(%rsp), %eax
addl 0x144(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rsi
leaq 0xf8(%rsp), %rdi
callq 0x3430
movq 0x88(%rsp), %rdi
vmovsd (%rax), %xmm0
vmovsd %xmm0, 0x28(%rsp)
addq $0x8, %rdi
movslq 0xd0(%rsp), %rsi
callq 0x3430
vmovsd 0x28(%rsp), %xmm0
vmovsd %xmm0, (%rax)
movl 0xd0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd0(%rsp)
jmp 0x5388
jmp 0x53fb
movl 0x144(%rsp), %eax
addl 0xf0(%rsp), %eax
movl %eax, 0xf0(%rsp)
jmp 0x5099
movq 0x88(%rsp), %rdi
movq 0x148(%rsp), %rcx
movl 0x144(%rsp), %r8d
leaq 0x118(%rsp), %rsi
leaq 0xf8(%rsp), %rdx
callq 0x9a30
jmp 0x5444
movl $0x0, 0xcc(%rsp)
movl 0xcc(%rsp), %eax
movl %eax, 0x24(%rsp)
movq 0x148(%rsp), %rdi
callq 0x3410
movq %rax, %rcx
movl 0x24(%rsp), %eax
subl 0x144(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x5700
movl 0xcc(%rsp), %eax
movl 0x144(%rsp), %ecx
addl %ecx, %eax
movl %eax, 0xc4(%rsp)
movq 0x148(%rsp), %rdi
callq 0x3410
movl 0x144(%rsp), %ecx
subl %ecx, %eax
incl %eax
movl %eax, 0xc0(%rsp)
leaq 0xc4(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x99f0
movq %rax, 0x18(%rsp)
jmp 0x54d2
movq 0x18(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xc8(%rsp)
movl 0xcc(%rsp), %eax
movl %eax, 0xbc(%rsp)
movl 0xc8(%rsp), %eax
movl %eax, 0xb8(%rsp)
movl 0xb8(%rsp), %eax
subl 0xbc(%rsp), %eax
addl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0xbc(%rsp), %eax
movl %eax, 0xb4(%rsp)
movl 0xb4(%rsp), %eax
cmpl 0xb8(%rsp), %eax
je 0x55f4
movl 0xb4(%rsp), %eax
addl 0x144(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rsi
leaq 0xf8(%rsp), %rdi
callq 0x3430
vmovsd (%rax), %xmm0
vmovsd %xmm0, 0x10(%rsp)
movslq 0xb4(%rsp), %rsi
leaq 0x118(%rsp), %rdi
callq 0x3430
vmovsd 0x10(%rsp), %xmm0
vucomisd (%rax), %xmm0
jb 0x55ba
movl 0xb4(%rsp), %eax
movl %eax, 0xbc(%rsp)
movl 0xb8(%rsp), %eax
subl 0xbc(%rsp), %eax
addl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0xbc(%rsp), %eax
movl %eax, 0xb4(%rsp)
jmp 0x55ef
movl 0xb4(%rsp), %eax
movl %eax, 0xb8(%rsp)
movl 0xb8(%rsp), %eax
subl 0xbc(%rsp), %eax
addl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0xbc(%rsp), %eax
movl %eax, 0xb4(%rsp)
jmp 0x5523
movl 0xcc(%rsp), %eax
movl %eax, 0xb0(%rsp)
movl 0xb0(%rsp), %eax
cmpl 0xb4(%rsp), %eax
jge 0x5667
movslq 0xb0(%rsp), %rsi
leaq 0x118(%rsp), %rdi
callq 0x3430
movq 0x88(%rsp), %rdi
vmovsd (%rax), %xmm0
vmovsd %xmm0, 0x8(%rsp)
addq $0x20, %rdi
movslq 0xb0(%rsp), %rsi
callq 0x3430
vmovsd 0x8(%rsp), %xmm0
vmovsd %xmm0, (%rax)
movl 0xb0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb0(%rsp)
jmp 0x5602
movl 0xb4(%rsp), %eax
movl %eax, 0xac(%rsp)
movl 0xac(%rsp), %eax
cmpl 0xc8(%rsp), %eax
jge 0x56e4
movl 0xac(%rsp), %eax
addl 0x144(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rsi
leaq 0xf8(%rsp), %rdi
callq 0x3430
movq 0x88(%rsp), %rdi
vmovsd (%rax), %xmm0
vmovsd %xmm0, (%rsp)
addq $0x20, %rdi
movslq 0xac(%rsp), %rsi
callq 0x3430
vmovsd (%rsp), %xmm0
vmovsd %xmm0, (%rax)
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x5675
jmp 0x56e6
movl 0x144(%rsp), %eax
addl 0xcc(%rsp), %eax
movl %eax, 0xcc(%rsp)
jmp 0x544f
leaq 0xf8(%rsp), %rdi
callq 0x7660
leaq 0x118(%rsp), %rdi
callq 0x7660
addq $0x158, %rsp            # imm = 0x158
retq
leaq 0x118(%rsp), %rdi
callq 0x7660
movq 0x70(%rsp), %rdi
callq 0x7660
movq 0x90(%rsp), %rdi
callq 0x7660
movq 0x88(%rsp), %rdi
callq 0x7830
movq 0x138(%rsp), %rdi
callq 0x2160