// File: /workspace/github_c_makefile_star2_O0/CarlosLunaMota[P]BinaryTrees/BinaryTrees.c
// Function: bs_tree_intersection
bs_tree *bs_tree_intersection(const bs_tree *tree_1, const bs_tree *tree_2) {

    bs_tree *tree = NULL;
    bs_node *node = NULL;
    bs_node *pred_1;
    bs_node *node_1;
    bs_node *pred_2;
    bs_node *node_2;
    int      comp;

    // Sanity check:
    assert(tree_1 != NULL);
    assert(tree_2 != NULL);

    // Special case: Both trees are the same
    if (tree_1 == tree_2) { return bs_tree_copy(tree_1); }

    // Create a new tree:
    tree = new_bs_tree(tree_1->comp);
    if (tree == NULL) { return NULL; }

    // Special case: Some of them is empty
    if (bs_tree_is_empty(tree_1) == YES) { return tree; }
    if (bs_tree_is_empty(tree_2) == YES) { return tree; }

    // Go to the smallest element of tree_1 while right-threading your path:
    node_1 = tree_1->root;
    if (node_1 != NULL) {
        while (node_1->left != NULL) {
            pred_1 = node_1->left;
            while (pred_1->right != NULL) { pred_1 = pred_1->right; }
            pred_1->right = node_1;
            node_1        = node_1->left;
        }
    }

    // Go to the smallest element of tree_2 while right-threading your path:
    node_2 = tree_2->root;
    if (node_2 != NULL) {
        while (node_2->left != NULL) {
            pred_2 = node_2->left;
            while (pred_2->right != NULL) { pred_2 = pred_2->right; }
            pred_2->right = node_2;
            node_2        = node_2->left;
        }
    }

    // Until we have exhausted at least one of the trees:
    while (node_1 != NULL && node_2 != NULL) {

        // compare both nodes:
        comp = (tree->comp)(node_1->data, node_2->data);

        if (comp < 0) {

            // advance node_1 //////////////////////////////////////////////////
            node_1 = node_1->right;
            if (node_1 != NULL) {
                while (node_1->left != NULL) {
                    pred_1 = node_1->left;
                    while (pred_1->right != NULL && pred_1->right != node_1) {
                        pred_1 = pred_1->right;
                    }
                    if (pred_1->right == NULL) {
                        pred_1->right = node_1;
                        node_1        = node_1->left;
                    } else {
                        pred_1->right = NULL;
                        break;
                    }
                }
            }
            ////////////////////////////////////////////////////////////////////

        } else if (comp > 0) {

            // advance node_2 //////////////////////////////////////////////////
            node_2 = node_2->right;
            if (node_2 != NULL) {
                while (node_2->left != NULL) {
                    pred_2 = node_2->left;
                    while (pred_2->right != NULL && pred_2->right != node_2) {
                        pred_2 = pred_2->right;
                    }
                    if (pred_2->right == NULL) {
                        pred_2->right = node_2;
                        node_2        = node_2->left;
                    } else {
                        pred_2->right = NULL;
                        break;
                    }
                }
            }
            ////////////////////////////////////////////////////////////////////

        } else {

            // insert node_1->data in tree /////////////////////////////////////
            if (node == NULL)  {
                tree->root = (bs_node *) malloc(sizeof(bs_node));
                node = tree->root;
            } else {
                node->right = (bs_node *) malloc(sizeof(bs_node));
                node = node->right;
            }
            if (node == NULL) {
                fprintf(stderr, "ERROR: Unable to allocate bs_node\n");
                return tree;
            } else {
                node->data  = node_1->data;
                node->left  = NULL;
                node->right = NULL;
            }
            ////////////////////////////////////////////////////////////////////

            // advance node_1 //////////////////////////////////////////////////
            node_1 = node_1->right;
            if (node_1 != NULL) {
                while (node_1->left != NULL) {
                    pred_1 = node_1->left;
                    while (pred_1->right != NULL && pred_1->right != node_1) {
                        pred_1 = pred_1->right;
                    }
                    if (pred_1->right == NULL) {
                        pred_1->right = node_1;
                        node_1        = node_1->left;
                    } else {
                        pred_1->right = NULL;
                        break;
                    }
                }
            }
            ////////////////////////////////////////////////////////////////////

            // advance node_2 //////////////////////////////////////////////////
            node_2 = node_2->right;
            if (node_2 != NULL) {
                while (node_2->left != NULL) {
                    pred_2 = node_2->left;
                    while (pred_2->right != NULL && pred_2->right != node_2) {
                        pred_2 = pred_2->right;
                    }
                    if (pred_2->right == NULL) {
                        pred_2->right = node_2;
                        node_2        = node_2->left;
                    } else {
                        pred_2->right = NULL;
                        break;
                    }
                }
            }
            ////////////////////////////////////////////////////////////////////
        }
    }

    // We need to traverse tree_1 completely to restore the modified pointers:
    while (node_1 != NULL) {

        // advance node_1 //////////////////////////////////////////////////////
        node_1 = node_1->right;
        if (node_1 != NULL) {
            while (node_1->left != NULL) {
                pred_1 = node_1->left;
                while (pred_1->right != NULL && pred_1->right != node_1) {
                    pred_1 = pred_1->right;
                }
                if (pred_1->right == NULL) {
                    pred_1->right = node_1;
                    node_1        = node_1->left;
                } else {
                    pred_1->right = NULL;
                    break;
                }
            }
        }
        ////////////////////////////////////////////////////////////////////////
    }

    // We need to traverse tree_2 completely to restore the modified pointers:
    while (node_2 != NULL) {

        // advance node_2 //////////////////////////////////////////////////////
        node_2 = node_2->right;
        if (node_2 != NULL) {
            while (node_2->left != NULL) {
                pred_2 = node_2->left;
                while (pred_2->right != NULL && pred_2->right != node_2) {
                    pred_2 = pred_2->right;
                }
                if (pred_2->right == NULL) {
                    pred_2->right = node_2;
                    node_2        = node_2->left;
                } else {
                    pred_2->right = NULL;
                    break;
                }
            }
        }
        ////////////////////////////////////////////////////////////////////////
    }

    // Return the resulting tree:
    return tree;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0xdf49
jmp 0xdf68
leaq 0x85b5(%rip), %rdi      # 0x16505
leaq 0x82a5(%rip), %rsi      # 0x161fc
movl $0x424, %edx            # imm = 0x424
leaq 0x85f9(%rip), %rcx      # 0x1655c
callq 0x1060
cmpq $0x0, -0x18(%rbp)
je 0xdf71
jmp 0xdf90
leaq 0x85d5(%rip), %rdi      # 0x1654d
leaq 0x827d(%rip), %rsi      # 0x161fc
movl $0x425, %edx            # imm = 0x425
leaq 0x85d1(%rip), %rcx      # 0x1655c
callq 0x1060
movq -0x10(%rbp), %rax
cmpq -0x18(%rbp), %rax
jne 0xdfac
movq -0x10(%rbp), %rdi
callq 0xc650
movq %rax, -0x8(%rbp)
jmp 0xe5c7
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xc5c0
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0xdfd1
movq $0x0, -0x8(%rbp)
jmp 0xe5c7
movq -0x10(%rbp), %rdi
callq 0xccf0
cmpl $0x1, %eax
jne 0xdfec
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xe5c7
movq -0x18(%rbp), %rdi
callq 0xccf0
cmpl $0x1, %eax
jne 0xe007
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xe5c7
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0xe067
jmp 0xe01b
movq -0x38(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe065
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0xe04b
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0xe032
movq -0x38(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0xe01b
jmp 0xe067
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0xe0c7
jmp 0xe07b
movq -0x48(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe0c5
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0xe0ab
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0xe092
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0xe07b
jmp 0xe0c7
jmp 0xe0c9
xorl %eax, %eax
cmpq $0x0, -0x38(%rbp)
movb %al, -0x4d(%rbp)
je 0xe0e0
cmpq $0x0, -0x48(%rbp)
setne %al
movb %al, -0x4d(%rbp)
movb -0x4d(%rbp), %al
testb $0x1, %al
jne 0xe0ec
jmp 0xe455
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x38(%rbp), %rcx
movq (%rcx), %rdi
movq -0x48(%rbp), %rcx
movq (%rcx), %rsi
callq *%rax
movl %eax, -0x4c(%rbp)
cmpl $0x0, -0x4c(%rbp)
jge 0xe1b9
movq -0x38(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0xe1b4
jmp 0xe12a
movq -0x38(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe1b2
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rcx
xorl %eax, %eax
cmpq $0x0, 0x10(%rcx)
movb %al, -0x4e(%rbp)
je 0xe163
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x38(%rbp), %rax
setne %al
movb %al, -0x4e(%rbp)
movb -0x4e(%rbp), %al
testb $0x1, %al
jne 0xe16c
jmp 0xe17a
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0xe141
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0xe19f
movq -0x38(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0xe1ad
movq -0x30(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0xe1b2
jmp 0xe12a
jmp 0xe1b4
jmp 0xe450
cmpl $0x0, -0x4c(%rbp)
jle 0xe26b
movq -0x48(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0xe266
jmp 0xe1dc
movq -0x48(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe264
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rcx
xorl %eax, %eax
cmpq $0x0, 0x10(%rcx)
movb %al, -0x4f(%rbp)
je 0xe215
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x48(%rbp), %rax
setne %al
movb %al, -0x4f(%rbp)
movb -0x4f(%rbp), %al
testb $0x1, %al
jne 0xe21e
jmp 0xe22c
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0xe1f3
movq -0x40(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0xe251
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0xe25f
movq -0x40(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0xe264
jmp 0xe1dc
jmp 0xe266
jmp 0xe44e
cmpq $0x0, -0x28(%rbp)
jne 0xe293
movl $0x18, %edi
callq 0x10a0
movq %rax, %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0xe2b4
movl $0x18, %edi
callq 0x10a0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0xe2e0
movq 0xbd36(%rip), %rax      # 0x19ff8
movq (%rax), %rdi
leaq 0x7fda(%rip), %rsi      # 0x162a6
movb $0x0, %al
callq 0x1080
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xe5c7
movq -0x38(%rbp), %rax
movq (%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movq $0x0, 0x8(%rax)
movq -0x28(%rbp), %rax
movq $0x0, 0x10(%rax)
movq -0x38(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0xe3a9
jmp 0xe31f
movq -0x38(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe3a7
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rcx
xorl %eax, %eax
cmpq $0x0, 0x10(%rcx)
movb %al, -0x50(%rbp)
je 0xe358
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x38(%rbp), %rax
setne %al
movb %al, -0x50(%rbp)
movb -0x50(%rbp), %al
testb $0x1, %al
jne 0xe361
jmp 0xe36f
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0xe336
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0xe394
movq -0x38(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0xe3a2
movq -0x30(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0xe3a7
jmp 0xe31f
jmp 0xe3a9
movq -0x48(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0xe44c
jmp 0xe3c2
movq -0x48(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe44a
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rcx
xorl %eax, %eax
cmpq $0x0, 0x10(%rcx)
movb %al, -0x51(%rbp)
je 0xe3fb
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x48(%rbp), %rax
setne %al
movb %al, -0x51(%rbp)
movb -0x51(%rbp), %al
testb $0x1, %al
jne 0xe404
jmp 0xe412
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0xe3d9
movq -0x40(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0xe437
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0xe445
movq -0x40(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0xe44a
jmp 0xe3c2
jmp 0xe44c
jmp 0xe44e
jmp 0xe450
jmp 0xe0c9
jmp 0xe457
cmpq $0x0, -0x38(%rbp)
je 0xe50a
movq -0x38(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0xe505
jmp 0xe47b
movq -0x38(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe503
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rcx
xorl %eax, %eax
cmpq $0x0, 0x10(%rcx)
movb %al, -0x52(%rbp)
je 0xe4b4
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x38(%rbp), %rax
setne %al
movb %al, -0x52(%rbp)
movb -0x52(%rbp), %al
testb $0x1, %al
jne 0xe4bd
jmp 0xe4cb
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0xe492
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0xe4f0
movq -0x38(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0xe4fe
movq -0x30(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0xe503
jmp 0xe47b
jmp 0xe505
jmp 0xe457
jmp 0xe50c
cmpq $0x0, -0x48(%rbp)
je 0xe5bf
movq -0x48(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0xe5ba
jmp 0xe530
movq -0x48(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xe5b8
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rcx
xorl %eax, %eax
cmpq $0x0, 0x10(%rcx)
movb %al, -0x53(%rbp)
je 0xe569
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x48(%rbp), %rax
setne %al
movb %al, -0x53(%rbp)
movb -0x53(%rbp), %al
testb $0x1, %al
jne 0xe572
jmp 0xe580
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0xe547
movq -0x40(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0xe5a5
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0xe5b3
movq -0x40(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0xe5b8
jmp 0xe530
jmp 0xe5ba
jmp 0xe50c
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)