// File: /workspace/github_c_makefile_star2_O0/CarlosLunaMota[P]BinaryTrees/BinaryTrees.c
// Function: rb_tree_remove_max
void *rb_tree_remove_max(rb_tree *tree) {

    rb_node *granpa   = NULL;   //      granpa      //
    rb_node *parent   = NULL;   //        |         //
    rb_node *sister   = NULL;   //      parent      //
    rb_node *node     = NULL;   //      /    \      // 
    void    *old_data = NULL;   //   sister node    //

    // Sanity Check:
    assert(tree != NULL);
    
    // Initialize the search at the root node:
    node = tree->root;
    if (node == NULL) { return NULL; }
    
    // Look for a leaf:
    while (node != NULL) {

        // At this point node is BLACK, if sister exists is BLACK and if parent 
        // exists is RED. We want to paint node RED and repair any violation.

        // Case 1: Node has two BLACK children
        if (IS_BLACK(node->left) && IS_BLACK(node->right)) {

            // Easy case: the node is the root node
            if (parent == NULL) { node->color = RED; }

            // General case:
            else {

                // Case 1.0: Node has no sister
                if (sister == NULL) {
                    node->color   = RED;
                    parent->color = BLACK;
                    
                // Case 1.1: Sister has 2 BLACK children
                } else if (IS_BLACK(sister->left) && IS_BLACK(sister->right)){
                    node->color   = RED;
                    sister->color = RED;
                    parent->color = BLACK;

                // Case 1.2: Sister has at least 1 RED children
                } else {

                    // If sister->left is RED:
                    if (IS_RED(sister->left)) {

                        // Sister == parent->left: Single rotation
                        if  (granpa == NULL) { tree->root    = sister; }
                        else                 { granpa->right = sister; }
                        granpa = sister;
                        
                        parent->left  = granpa->right;
                        granpa->right = parent;
                        sister        = parent->left;
                        
                        node->color   = RED;
                        granpa->color = RED;
                        parent->color = BLACK;
                        granpa->left->color = BLACK;
                    }

                    // If sister->right is RED:
                    else {

                        // If sister == parent->left: Double rotation
                        if  (granpa == NULL) { tree->root    = sister->right; }
                        else                 { granpa->right = sister->right; }
                        granpa = sister->right;
                        
                        parent->left  = granpa->right;
                        granpa->right = parent;

                        sister->right = granpa->left;
                        granpa->left  = sister;
                        sister        = parent->left;
                        
                        node->color   = RED;
                        parent->color = BLACK;
                    }
                }
            }
        }

        // Case 2: Node has at least one RED children
        if (IS_RED(node->left) || IS_RED(node->right)) {

            // Again node is BLACK, if sister exists is BLACK and if parent
            // exists is RED. We paint node RED and repair any violation.

            // Case 2.1: We are moving to the RED node
            if (IS_RED(node->right)){

                // Move and compare again for free!
                granpa = parent;
                parent = node;
                node   = parent->right;
                sister = parent->left;
            }
            
            // Case 2.2: We are moving to the BLACK node
            else {
                // we are moving to the right: Single right-rotation
                if  (parent == NULL) { tree->root    = node->left; }
                else                 { parent->right = node->left; }
                granpa        = parent;
                parent        = node->left;
                sister        = parent->left;
                node->left    = parent->right;
                parent->right = node;
                                    
                node->color   = RED;
                parent->color = BLACK;
            }
        }

        // ...and finally move!
        granpa = parent;
        parent = node;
        node   = parent->right;
        sister = parent->left;
    }

    // Erase "parent", which should be RED:
    old_data = parent->data;
    if (granpa == NULL) { tree->root    = parent->left; }
    else                { granpa->right = parent->left; }
    free(parent);
    
    // Before leaving: Make sure that the root is BLACK!
    if (tree->root != NULL) { tree->root->color = BLACK; }

    // And return old_data (which will be NULL unless data was already here)
    return old_data;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq $0x0, -0x38(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x11bdd
jmp 0x11bfc
leaq 0x468e(%rip), %rdi      # 0x16272
leaq 0x4611(%rip), %rsi      # 0x161fc
movl $0xc8d, %edx            # imm = 0xC8D
leaq 0x4d68(%rip), %rcx      # 0x1695f
callq 0x1060
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x11c1b
movq $0x0, -0x8(%rbp)
jmp 0x11f98
jmp 0x11c1d
cmpq $0x0, -0x30(%rbp)
je 0x11f3f
movq -0x30(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x11c48
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x0, %eax
jne 0x11e16
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x11c68
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x0, %eax
jne 0x11e16
cmpq $0x0, -0x20(%rbp)
jne 0x11c7c
movq -0x30(%rbp), %rax
movb $0x1, 0x18(%rax)
jmp 0x11e14
cmpq $0x0, -0x28(%rbp)
jne 0x11c98
movq -0x30(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x20(%rbp), %rax
movb $0x0, 0x18(%rax)
jmp 0x11e12
movq -0x28(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x11cb4
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x0, %eax
jne 0x11ced
movq -0x28(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x11cd0
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x0, %eax
jne 0x11ced
movq -0x30(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x28(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x20(%rbp), %rax
movb $0x0, 0x18(%rax)
jmp 0x11e10
movq -0x28(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x11d86
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x1, %eax
jne 0x11d86
cmpq $0x0, -0x18(%rbp)
jne 0x11d21
movq -0x28(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x11d2d
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x18(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x20(%rbp), %rax
movb $0x0, 0x18(%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movb $0x0, 0x18(%rax)
jmp 0x11e0e
cmpq $0x0, -0x18(%rbp)
jne 0x11d9e
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x11dae
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x20(%rbp), %rax
movb $0x0, 0x18(%rax)
jmp 0x11e10
jmp 0x11e12
jmp 0x11e14
jmp 0x11e16
movq -0x30(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x11e32
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x1, %eax
je 0x11e56
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x11f12
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x1, %eax
jne 0x11f12
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x11e9c
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movsbl 0x18(%rax), %eax
cmpl $0x1, %eax
jne 0x11e9c
movq -0x20(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x11f10
cmpq $0x0, -0x20(%rbp)
jne 0x11eb4
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x11ec4
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x30(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x30(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x20(%rbp), %rax
movb $0x0, 0x18(%rax)
jmp 0x11f12
movq -0x20(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x11c1d
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x11f62
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
jmp 0x11f72
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rdi
callq 0x10e0
movq -0x10(%rbp), %rax
cmpq $0x0, (%rax)
je 0x11f90
movq -0x10(%rbp), %rax
movq (%rax), %rax
movb $0x0, 0x18(%rax)
movq -0x38(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)