// File: reddragon[P]packed-memory-array/impl1.cpp
// Function: PackedMemoryArray<int>::rebalance(int, int)
void PackedMemoryArray<E>::rebalance(int index, int level) {
#ifndef OPTIMIZE 
    assert(level <= l);
#endif
    int c = CAPACITY_AT(level);
    // Move all the elements to one side
    int last = index + c - 1, count = 0;
    for(int i = last; i >= index; i--) {
        if(ELEM_EXISTS_AT(i)) {
            if(i != last) {
                // Copy the element to the leftmost position
                insert_element_at(store[i], last);
                // Delete the original copy of the element
                #ifndef OPTIMIZE
                    delete_element_at(i);
                #else
                    exists[i] = 0;
                #endif
               // Update the leftmost pointer, and count of elements moved
            }
            --last;
            count++;
        }
    }

    // Now copy
    double k = (c*1.0)/count, p = 0;
    int actual_index = last, correct_index;
    for(int i = 0; i < count; i++) {
        p += k;
        actual_index++;
        // Now insert the element at the right position
        correct_index = index + (int)p - 1;
        if (correct_index == actual_index)
            continue;
        if(actual_index != correct_index)
            insert_element_at(store[actual_index], correct_index);
        // Remove the left most copy
#ifndef OPTIMIZE
        delete_element_at(actual_index);
#else
        exists[actual_index] = 0;
#endif
    } 
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x78(%rbp)
movl 0x5c(%rax), %eax
movl -0x10(%rbp), %ecx
shll %cl, %eax
movl %eax, -0x14(%rbp)
movl -0xc(%rbp), %eax
addl -0x14(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x20(%rbp)
movl -0x20(%rbp), %eax
cmpl -0xc(%rbp), %eax
jl 0x5a6e
movq -0x78(%rbp), %rdi
addq $0x18, %rdi
movslq -0x20(%rbp), %rsi
callq 0x4750
movq %rax, -0x30(%rbp)
movq %rdx, -0x28(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x38e0
testb $0x1, %al
jne 0x5a05
jmp 0x5a5e
movl -0x20(%rbp), %eax
cmpl -0x18(%rbp), %eax
je 0x5a4c
movq -0x78(%rbp), %rdi
movslq -0x20(%rbp), %rsi
callq 0x4730
movq -0x78(%rbp), %rdi
movl (%rax), %esi
movl -0x18(%rbp), %edx
callq 0x18e0
movq -0x78(%rbp), %rdi
addq $0x18, %rdi
movslq -0x20(%rbp), %rsi
callq 0x4750
movq %rax, -0x40(%rbp)
movq %rdx, -0x38(%rbp)
leaq -0x40(%rbp), %rdi
xorl %esi, %esi
callq 0x3910
movl -0x18(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x18(%rbp)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x5a60
movl -0x20(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x59d1
cvtsi2sdl -0x14(%rbp), %xmm0
movsd 0x15a5(%rip), %xmm1     # 0x7020
mulsd %xmm1, %xmm0
cvtsi2sdl -0x1c(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x54(%rbp)
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x5b35
movsd -0x48(%rbp), %xmm0
addsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
movl -0xc(%rbp), %eax
cvttsd2si -0x50(%rbp), %ecx
addl %ecx, %eax
subl $0x1, %eax
movl %eax, -0x58(%rbp)
movl -0x58(%rbp), %eax
cmpl -0x54(%rbp), %eax
jne 0x5ae0
jmp 0x5b27
movl -0x54(%rbp), %eax
cmpl -0x58(%rbp), %eax
je 0x5b03
movq -0x78(%rbp), %rdi
movslq -0x54(%rbp), %rsi
callq 0x4730
movq -0x78(%rbp), %rdi
movl (%rax), %esi
movl -0x58(%rbp), %edx
callq 0x18e0
movq -0x78(%rbp), %rdi
addq $0x18, %rdi
movslq -0x54(%rbp), %rsi
callq 0x4750
movq %rax, -0x70(%rbp)
movq %rdx, -0x68(%rbp)
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
callq 0x3910
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x5aa2
addq $0x80, %rsp
popq %rbp
retq
nop