// File: /workspace/github_cpp_makefile_star2_O1/6851-2021[P]Cache-Oblivious-Data-Structures/static_search_trees/static_search_trees.cpp
// Function: co_static_search_tree::update(int, int, int, int, int, int)
int co_static_search_tree::update(int block_index, int height, int range_left, int og_height, int index, int value) {
    if (height == 1)
    {
        this->tree[block_index] = value;
        return value;
    }
    if(height == 2) {
        if(index < range_left + (1 << (og_height - 2))) {
            this->tree[block_index + 1] = value;
        } else {
            this->tree[block_index + 2] = value;
        }
        //merge
        this->tree[block_index] = max(this->tree[block_index + 1], this->tree[block_index + 2]);
        return this->tree[block_index];
    }
    if(height == 3) {
        return this->update_3_base_case(block_index, range_left, og_height, index, value);
    }   
    if(height == 4) {
        return this->update_4_base_case(block_index, range_left, og_height, index, value);
    }
    
    //update bottom tree
    int bottom_tree_height = bottom_tree_height_memo[height];

    int top_tree_height = height - bottom_tree_height;
    
    int top_tree_size = (1 << top_tree_height) - 1;

    int bottom_tree_og_height = og_height - top_tree_height;
    int bottom_tree_index = (index - range_left) >> (bottom_tree_og_height - 1);
    int bottom_tree_size = (1 << bottom_tree_height) - 1;

    int bottom_tree_block_index = block_index + top_tree_size + (bottom_tree_index << bottom_tree_height) - bottom_tree_index;
    int bottom_tree_range_left = range_left + (bottom_tree_index << (bottom_tree_og_height - 1));

    int child_value = this->update(bottom_tree_block_index, bottom_tree_height, bottom_tree_range_left, bottom_tree_og_height, index, value);


    //get adjacent child
    int adjacent_child_value;
    if(bottom_tree_index % 2 == 0) {
        adjacent_child_value = this->tree[bottom_tree_block_index + bottom_tree_size];
    } else {
        adjacent_child_value = this->tree[bottom_tree_block_index - bottom_tree_size];
    }

    //merge two children value
    int merged_value = max(child_value, adjacent_child_value);

    //update upper tree
    int final_value = this->update(block_index, top_tree_height, range_left, og_height, index, merged_value);

    return final_value;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %r8d, 0xc(%rsp)
movl %edx, %r13d
movl %esi, 0x8(%rsp)
movq %rdi, %rbx
movl 0x50(%rsp), %eax
movl %r9d, 0x14(%rsp)
movl %r9d, %r14d
movl %ecx, 0x10(%rsp)
subl %ecx, %r14d
leal -0x1(%r13), %ecx
cmpl $0x3, %ecx
jbe 0x14ac
movslq %r13d, %rcx
leaq 0x2c1d(%rip), %rdx      # 0x4040
movl (%rdx,%rcx,4), %edx
subl %edx, %r13d
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl %r13d, %ecx
shll %cl, %ebp
movl 0xc(%rsp), %ecx
movl %ecx, %r8d
subl %r13d, %r8d
leal -0x1(%r8), %esi
movl %r14d, %r12d
movl %esi, %ecx
sarl %cl, %r12d
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
movl %edx, %ecx
shll %cl, %r15d
notl %ebp
notl %r15d
addl 0x8(%rsp), %ebp
movl %r12d, %edi
shll %cl, %edi
subl %r12d, %ebp
addl %edi, %ebp
movl %r12d, %r9d
movl %esi, %ecx
shll %cl, %r9d
addl 0x10(%rsp), %r9d
movl %eax, (%rsp)
movq %rbx, %rdi
movl %ebp, %esi
movl %r9d, %ecx
movl 0x14(%rsp), %r9d
callq 0x13dc
movl %eax, %ecx
movl %r15d, %eax
negl %eax
testb $0x1, %r12b
movq (%rbx), %rdx
cmovel %r15d, %eax
addl %ebp, %eax
cltq
movl (%rdx,%rax,4), %eax
cmpl %eax, %ecx
cmovgl %ecx, %eax
jmp 0x140c
leaq 0x2b5d(%rip), %rdx      # 0x4010
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq (%rbx), %rcx
movslq 0x8(%rsp), %rdx
movl %eax, (%rcx,%rdx,4)
jmp 0x15bf
movl 0xc(%rsp), %ecx
addb $-0x3, %cl
sarl %cl, %r14d
movslq 0x8(%rsp), %rcx
cmpl $0x3, %r14d
ja 0x15b9
leaq 0x2b34(%rip), %rdx      # 0x4020
movslq (%rdx,%r14,4), %rsi
addq %rdx, %rsi
jmpq *%rsi
movq (%rbx), %rdx
movl %eax, 0x8(%rdx,%rcx,4)
movl 0xc(%rdx,%rcx,4), %esi
jmp 0x15a4
movq %rbx, %rdi
movl 0x8(%rsp), %esi
movl 0x10(%rsp), %edx
movl 0xc(%rsp), %ecx
movl 0x14(%rsp), %r8d
movl %eax, %r9d
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2584
movl 0xc(%rsp), %ecx
addb $-0x2, %cl
movl $0x1, %edx
shll %cl, %edx
addl 0x10(%rsp), %edx
xorl %ecx, %ecx
cmpl 0x14(%rsp), %edx
setle %cl
movq (%rbx), %rdx
movslq 0x8(%rsp), %rsi
leaq (%rdx,%rsi,4), %rdx
movl %eax, 0x4(%rdx,%rcx,4)
movl 0x4(%rdx), %ecx
movl 0x8(%rdx), %eax
cmpl %eax, %ecx
cmovgl %ecx, %eax
movl %eax, (%rdx)
jmp 0x15bf
movq (%rbx), %rdx
movl %eax, 0x14(%rdx,%rcx,4)
movl 0x4(%rdx,%rcx,4), %esi
movl 0x18(%rdx,%rcx,4), %edi
jmp 0x1589
movq (%rbx), %rdx
movl %eax, 0x18(%rdx,%rcx,4)
movl 0x4(%rdx,%rcx,4), %esi
movl 0x14(%rdx,%rcx,4), %edi
cmpl %eax, %edi
cmovgl %edi, %eax
movl %eax, 0x10(%rdx,%rcx,4)
cmpl %eax, %esi
cmovgl %esi, %eax
jmp 0x15b6
movq (%rbx), %rdx
movl %eax, 0xc(%rdx,%rcx,4)
movl 0x8(%rdx,%rcx,4), %esi
movl 0x10(%rdx,%rcx,4), %edi
cmpl %eax, %esi
cmovgl %esi, %eax
movl %eax, 0x4(%rdx,%rcx,4)
cmpl %edi, %eax
cmovlel %edi, %eax
movl %eax, (%rdx,%rcx,4)
movq (%rbx), %rax
movl (%rax,%rcx,4), %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq