// File: reddragon[P]packed-memory-array/impl2.cpp
// Function: PMA::insert(int)
void
    insert(int v) {
        /*
        if ((this->nelems + 2) * 2 > this->impl.size()) {
            // resize array
            this->resize(2 * this->impl.size());
        }
        */

        int i = lower_bound(v);
        if (i == this->impl.size()) {
            --i;
        }
        assert(i > -1);
        assert(i < this->impl.size());

        // Check in a window of size 'w'
        int w = chunk_size;
        int level = 0;
        int l = this->left_interval_boundary(i, w);

        // Number of elements in current window. We just need sz to be
        // less than w -- we don't need the exact value of 'sz' here.
        int sz = w - 1;

        bool in_limit = false;

        // If the current chunk has space, then the last element will
        // be unused (with significant probability). First check that
        // as a quick check.
        if (this->present[l + this->chunk_size - 1]) {
            get_interval_stats(l, level, in_limit, sz);
        }

        if (sz < w) {
            // There is some space in this interval. We can just
            // shuffle elements and insert.
            this->insert_merge(l, v);
        } else {
            // No space in this interval. Find an interval above this
            // interval that is within limits, re-balance, and
            // re-start insertion.
            in_limit = false;
            while (!in_limit) {
                w *= 2;
                level += 1;
                // assert(level <= this->nlevels);
                if (level > this->nlevels) {
                    // Root node is out of balance. Resize array.
                    this->resize(2 * this->impl.size());
                    this->insert(v);
                    return;
                }

                l = this->left_interval_boundary(i, w);
                get_interval_stats(l, level, in_limit, sz);
                dprintf("level: %d, this->nlevels: %d, in_limit: %d, sz: %d\n", level, this->nlevels, in_limit, sz);
            }
            this->rebalance_interval(l, level);
            this->insert(v);
        }

    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x48(%rbp)
movl -0xc(%rbp), %esi
callq 0x19c0
movq -0x48(%rbp), %rdi
movl %eax, -0x10(%rbp)
movslq -0x10(%rbp), %rax
movq %rax, -0x40(%rbp)
callq 0x1a90
movq %rax, %rcx
movq -0x40(%rbp), %rax
cmpq %rcx, %rax
jne 0x1588
movl -0x10(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x10(%rbp)
cmpl $-0x1, -0x10(%rbp)
jle 0x1590
jmp 0x15af
leaq 0x5acb(%rip), %rdi      # 0x7062
leaq 0x5acb(%rip), %rsi      # 0x7069
movl $0x128, %edx            # imm = 0x128
leaq 0x5ac9(%rip), %rcx      # 0x7073
callq 0x1090
movq -0x48(%rbp), %rdi
movslq -0x10(%rbp), %rax
movq %rax, -0x50(%rbp)
callq 0x1a90
movq %rax, %rcx
movq -0x50(%rbp), %rax
cmpq %rcx, %rax
jae 0x15ce
jmp 0x15ed
leaq 0x5ab4(%rip), %rdi      # 0x7089
leaq 0x5a8d(%rip), %rsi      # 0x7069
movl $0x129, %edx            # imm = 0x129
leaq 0x5a8b(%rip), %rcx      # 0x7073
callq 0x1090
movq -0x48(%rbp), %rdi
movl 0x48(%rdi), %eax
movl %eax, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x10(%rbp), %esi
movl -0x14(%rbp), %edx
callq 0x1ab0
movq -0x48(%rbp), %rcx
movl %eax, -0x1c(%rbp)
movl -0x14(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x20(%rbp)
movb $0x0, -0x21(%rbp)
movq %rcx, %rdi
addq $0x20, %rdi
movl -0x1c(%rbp), %eax
addl 0x48(%rcx), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x1b70
movq %rax, -0x38(%rbp)
movq %rdx, -0x30(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x1bd0
testb $0x1, %al
jne 0x164c
jmp 0x1663
movq -0x48(%rbp), %rdi
movl -0x1c(%rbp), %esi
movl -0x18(%rbp), %edx
leaq -0x21(%rbp), %rcx
leaq -0x20(%rbp), %r8
callq 0x1c00
movl -0x20(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x167f
movq -0x48(%rbp), %rdi
movl -0x1c(%rbp), %esi
movl -0xc(%rbp), %edx
callq 0x1ce0
jmp 0x1716
movb $0x0, -0x21(%rbp)
movb -0x21(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x168e
jmp 0x16fb
movq -0x48(%rbp), %rcx
movl -0x14(%rbp), %eax
shll %eax
movl %eax, -0x14(%rbp)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl 0x50(%rcx), %eax
jle 0x16d0
movq -0x48(%rbp), %rdi
callq 0x1a90
movq -0x48(%rbp), %rdi
shlq %rax
movl %eax, %esi
callq 0x1ef0
movq -0x48(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x1540
jmp 0x1716
movq -0x48(%rbp), %rdi
movl -0x10(%rbp), %esi
movl -0x14(%rbp), %edx
callq 0x1ab0
movq -0x48(%rbp), %rdi
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %esi
movl -0x18(%rbp), %edx
leaq -0x21(%rbp), %rcx
leaq -0x20(%rbp), %r8
callq 0x1c00
jmp 0x1683
movq -0x48(%rbp), %rdi
movl -0x1c(%rbp), %esi
movl -0x18(%rbp), %edx
callq 0x2220
movq -0x48(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x1540
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax)