// File: /workspace/github_cpp_makefile_star2_O2/reddragon[P]packed-memory-array/impl1.cpp
// Function: PackedMemoryArray<int>::expand_PMA(int)
void PackedMemoryArray<E>::expand_PMA(E e) {
    // Create a new store
    std::vector<E> new_store;
    new_store.resize(store.size() * 2);
    std::vector<bool> new_exists;
    new_exists.resize((int)ceil(s+1));
    
    int count = 0, i;
    // Insert all elements less than e
    for(i = 0; i < (int)store.size(); i++) 
        if(ELEM_EXISTS_AT(i)) {
            if(store[i] > e)
                break;
            new_exists[count] = 1;
            new_store[count++] = store[i];
        }
    
    // Insert the element we wanted
    new_exists[count] = 1;
    new_store[count++] = e;
    
    // Insert rest of the elements
    for(; i < (int)store.size(); i++) 
        if(ELEM_EXISTS_AT(i)) {
            new_exists[count] = 1;
            new_store[count++] = store[i];
        }

    // Replace the existing store and bitmask
    store = new_store;
    exists = new_exists;
 
    // Increment the number of elements in the PMA
    s++;
    
    // std::cout << "Old smallest window size: " << segment_size << std::endl;
    // Recalculate l and segment_size
    int log2n = __builtin_popcount(store.size()-1);
    if(log2n & (log2n-1)) {
        // log2n is not a power of 2, round it up to the nearest power of 2.
        segment_size = 1<<((int)floor(log2(log2n<<1)));
    }
    else {
        // log2n is a power of 2, so, all is fine.
        segment_size = 1<<log2n;
    }
    l = log2n - log2(segment_size);
    // std::cout << "New smallest window size: " << segment_size << std::endl;

    // Now rebalance the entire PMA 
    rebalance(0, l);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %esi, %ebp
movq %rdi, %rbx
xorpd %xmm0, %xmm0
movq %rsp, %rdi
movapd %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
movq 0x8(%rbx), %rsi
subq (%rbx), %rsi
sarq %rsi
callq 0x1508
leaq 0x20(%rsp), %rdi
andq $0x0, (%rdi)
andl $0x0, 0x8(%rdi)
andq $0x0, 0x10(%rdi)
andl $0x0, 0x18(%rdi)
andq $0x0, 0x20(%rdi)
movl 0x58(%rbx), %eax
incl %eax
movslq %eax, %rsi
xorl %r12d, %r12d
xorl %edx, %edx
callq 0x153a
leaq 0x18(%rbx), %r14
xorl %r15d, %r15d
movq 0x8(%rbx), %rax
subq (%rbx), %rax
shrq $0x2, %rax
cltq
movslq %r12d, %r13
cmpq %rax, %r15
jge 0x2192
movq %r14, %rdi
movq %r15, %rsi
callq 0x1e08
testq %rdx, (%rax)
je 0x218d
movq (%rbx), %rax
cmpl %ebp, (%rax,%r15,4)
jg 0x2192
leaq 0x20(%rsp), %rdi
movq %r13, %rsi
callq 0x1e08
orq %rdx, (%rax)
movq (%rbx), %rax
movl (%rax,%r15,4), %eax
leal 0x1(%r13), %r12d
movq (%rsp), %rcx
movl %eax, (%rcx,%r13,4)
incq %r15
jmp 0x213c
movl %ebp, %r12d
leaq 0x20(%rsp), %rdi
movq %r13, %rsi
callq 0x1e08
orq %rdx, (%rax)
leal 0x1(%r13), %ebp
movq (%rsp), %rax
movl %r12d, (%rax,%r13,4)
leaq 0x20(%rsp), %r12
movq 0x8(%rbx), %rax
subq (%rbx), %rax
shrq $0x2, %rax
cltq
cmpq %rax, %r15
jge 0x2201
movq %r14, %rdi
movq %r15, %rsi
callq 0x1e08
testq %rdx, (%rax)
je 0x21fc
movslq %ebp, %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x1e08
orq %rdx, (%rax)
movq (%rbx), %rax
movl (%rax,%r15,4), %eax
leal 0x1(%r13), %ebp
movq (%rsp), %rcx
movl %eax, (%rcx,%r13,4)
incq %r15
jmp 0x21b6
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x258c
leaq 0x20(%rsp), %rsi
movq %r14, %rdi
callq 0x2656
incl 0x58(%rbx)
movq 0x8(%rbx), %rax
subq (%rbx), %rax
shrq $0x2, %rax
decl %eax
movl %eax, %ecx
shrl %ecx
andl $0x55555555, %ecx       # imm = 0x55555555
subl %ecx, %eax
movl $0x33333333, %ecx       # imm = 0x33333333
movl %eax, %edx
andl %ecx, %edx
shrl $0x2, %eax
andl %ecx, %eax
addl %edx, %eax
movl %eax, %ecx
shrl $0x4, %ecx
addl %eax, %ecx
andl $0xf0f0f0f, %ecx        # imm = 0xF0F0F0F
imull $0x1010101, %ecx, %r14d # imm = 0x1010101
shrl $0x18, %r14d
leal -0x1(%r14), %eax
movl %r14d, %ecx
testl %eax, %r14d
je 0x227f
leal (%r14,%r14), %eax
cvtsi2sd %eax, %xmm0
callq 0x1170
callq 0x1150
cvttsd2si %xmm0, %ecx
pushq $0x1
popq %rax
shll %cl, %eax
movl %eax, 0x5c(%rbx)
cvtsi2sd %r14d, %xmm0
movsd %xmm0, 0x18(%rsp)
cvtsi2sd %eax, %xmm0
callq 0x1170
movsd 0x18(%rsp), %xmm1
subsd %xmm0, %xmm1
cvttsd2si %xmm1, %edx
movl %edx, 0x54(%rbx)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x26ec
leaq 0x20(%rsp), %rdi
callq 0x15ca
movq %rsp, %rdi
callq 0x1e36
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x22ea
jmp 0x22ea
jmp 0x22ea
movq %rax, %rbx
jmp 0x22f7
jmp 0x22ea
jmp 0x22ea
jmp 0x22ea
jmp 0x22ea
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x15ca
movq %rsp, %rdi
callq 0x1e36
movq %rbx, %rdi
callq 0x1160
nop