// File: /workspace/github_c_makefile_star2_O3/CarlosLunaMota[P]BinaryTrees/BinaryTrees.c
// Function: rb_tree_remove_min
void *rb_tree_remove_min(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;   //   node  sister   //

    // 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->right: Double rotation
                        if  (granpa == NULL) { tree->root    = sister->left; }
                        else                 { granpa->left  = sister->left; }
                        granpa = sister->left;
                        
                        parent->right = granpa->left;
                        granpa->left  = parent;

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

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

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

                        parent->right = granpa->left;
                        granpa->left  = parent;
                        sister        = parent->right;

                        node->color   = RED;
                        granpa->color = RED;
                        parent->color = BLACK;
                        granpa->right->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->left)){

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

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

    // Erase "parent", which should be RED:
    old_data = parent->data;
    if (granpa == NULL) { tree->root   = parent->right; }
    else                { granpa->left = parent->right; }
    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 %r14
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0xa713
movq %rdi, %rbx
movq (%rdi), %rcx
testq %rcx, %rcx
je 0xa705
xorl %edx, %edx
movb $0x1, %al
xorl %edi, %edi
xorl %esi, %esi
movq 0x8(%rcx), %r8
testq %r8, %r8
je 0xa5a9
cmpb $0x0, 0x18(%r8)
jne 0xa66d
movq 0x10(%rcx), %r8
testq %r8, %r8
je 0xa5bd
cmpb $0x0, 0x18(%r8)
jne 0xa66d
testq %rdi, %rdi
je 0xa60b
testq %rdx, %rdx
je 0xa661
movq 0x8(%rdx), %r8
testq %r8, %r8
je 0xa5dd
movb 0x18(%r8), %r9b
testb %r9b, %r9b
jne 0xa5f6
movq 0x10(%rdx), %r9
testq %r9, %r9
je 0xa612
cmpb $0x0, 0x18(%r9)
je 0xa612
testq %r8, %r8
je 0xa61a
movb 0x18(%r8), %r9b
cmpb $0x1, %r9b
jne 0xa61a
testq %rsi, %rsi
je 0xa646
movq %r8, 0x8(%rsi)
movq 0x8(%rdx), %r8
jmp 0xa649
movb $0x1, %dl
movq %rcx, %rsi
jmp 0xa66a
movb %al, 0x18(%rcx)
movb %al, 0x18(%rdx)
jmp 0xa665
testq %rsi, %rsi
je 0xa629
movq %rdx, 0x8(%rsi)
movq 0x8(%rdx), %r8
jmp 0xa62c
movq %rdx, (%rbx)
movq %r8, 0x10(%rdi)
movq %rdi, 0x8(%rdx)
movb %al, 0x18(%rcx)
movb %al, 0x18(%rdx)
movb $0x0, 0x18(%rdi)
movq 0x10(%rdx), %rsi
xorl %edx, %edx
jmp 0xa66a
movq %r8, (%rbx)
movq 0x8(%r8), %rsi
movq %rsi, 0x10(%rdi)
movq %rdi, 0x8(%r8)
movq 0x10(%r8), %rsi
movq %rsi, 0x8(%rdx)
movq %rdx, 0x10(%r8)
movb $0x1, 0x18(%rcx)
xorl %edx, %edx
movq %rdi, %rsi
movb %dl, 0x18(%rsi)
movq 0x8(%rcx), %r8
testq %r8, %r8
je 0xa689
cmpb $0x1, 0x18(%r8)
jne 0xa689
movq 0x10(%r8), %rdx
movq %rcx, %rsi
movq %r8, %rdi
jmp 0xa6d4
movq 0x10(%rcx), %rdx
testq %rdx, %rdx
je 0xa6cc
cmpb $0x1, 0x18(%rdx)
jne 0xa6ce
testq %r8, %r8
je 0xa6a4
cmpb $0x1, 0x18(%r8)
je 0xa67d
leaq 0x8(%rdi), %rdx
testq %rdi, %rdi
cmoveq %rbx, %rdx
movq 0x10(%rcx), %rsi
movq %rsi, (%rdx)
movq 0x8(%rsi), %rdx
movq %rdx, 0x10(%rcx)
movq %rcx, 0x8(%rsi)
movb $0x1, 0x18(%rcx)
movb $0x0, 0x18(%rsi)
jmp 0xa6d1
xorl %edx, %edx
movq %rdi, %rsi
movq %rcx, %rdi
movq 0x8(%rdi), %rcx
testq %rcx, %rcx
jne 0xa595
movq (%rdi), %r14
leaq 0x8(%rsi), %rax
testq %rsi, %rsi
cmoveq %rbx, %rax
movq %rdx, (%rax)
callq 0x1120
movq (%rbx), %rax
testq %rax, %rax
je 0xa708
movb $0x0, 0x18(%rax)
jmp 0xa708
xorl %r14d, %r14d
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
leaq 0x3b69(%rip), %rdi      # 0xe283
leaq 0x3aec(%rip), %rsi      # 0xe20d
leaq 0x4217(%rip), %rcx      # 0xe93f
movl $0xbff, %edx            # imm = 0xBFF
callq 0x1080