// File: dvjdjvu[P]bntree/./src/bntree.cpp
// Function: bntree::balance(node_s*)
void bntree::balance(node_t *p) {
    if (!p) {
        return;
    }

    node_t *child = NULL;
    node_t *parent = NULL;
    uint64_t ld = 0;
    uint64_t rd = 0;

    for (;;) {
        ld = this->weight_to_depth(p->left);
        rd = this->weight_to_depth(p->right);

        if (ld > rd && ld - rd > 1) {
            // Правый поворот. 
            // Глубина левого поддерева больше, чем глубина правого

            child = p->left;
            parent = p->parent;

            if (parent) {
                if (parent->right == p) {
                    parent->right = child;
                } else if (parent->left == p) {
                    parent->left = child;
                }
            } else {
                this->tree->root = child;
            }
            child->parent = parent;
            p->parent = child;

            p->left = child->right;
            if (p->left) {
                p->left->parent = p;
            }

            child->right = p;

            p->weight = 1 + this->get_child_weight(p->left) + this->get_child_weight(p->right);
            child->weight = 1 + this->get_child_weight(child->left) + this->get_child_weight(child->right);
            
            p = child;
            //break;
        } else if (rd > ld && rd - ld > 1) {
            // Левый поворот. 
            // Глубина правого поддерева больше, чем глубина левого

            child = p->right;
            parent = p->parent;

            if (parent) {
                if (parent->right == p) {
                    parent->right = child;
                } else if (parent->left == p) {
                    parent->left = child;
                }
            } else {
                this->tree->root = child;
            }
            child->parent = parent;
            p->parent = child;

            p->right = child->left;
            if (p->right) {
                p->right->parent = p;
            }

            child->left = p;

            p->weight = 1 + this->get_child_weight(p->left) + this->get_child_weight(p->right);
            child->weight = 1 + this->get_child_weight(child->left) + this->get_child_weight(child->right);

            p = child;
            //break;
        }

        if (p->parent) {
            p = p->parent;
        } else {
            break;
        }
    }

    return;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x2964
jmp 0x2c77
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq -0x38(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x36a0
movq -0x38(%rbp), %rdi
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x36a0
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x30(%rbp), %rax
jbe 0x2b03
movq -0x28(%rbp), %rax
subq -0x30(%rbp), %rax
cmpq $0x1, %rax
jbe 0x2b03
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x2a27
movq -0x20(%rbp), %rax
movq 0x50(%rax), %rax
cmpq -0x10(%rbp), %rax
jne 0x2a09
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x50(%rax)
jmp 0x2a25
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
cmpq -0x10(%rbp), %rax
jne 0x2a23
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x48(%rax)
jmp 0x2a25
jmp 0x2a35
movq -0x38(%rbp), %rax
movq -0x18(%rbp), %rcx
movq (%rax), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x48(%rax)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x48(%rax)
je 0x2a78
movq -0x10(%rbp), %rcx
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq %rcx, 0x58(%rax)
movq -0x38(%rbp), %rdi
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x50(%rax)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x2700
movq -0x38(%rbp), %rdi
addq $0x1, %rax
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x2700
movq -0x48(%rbp), %rcx
movq -0x38(%rbp), %rdi
addq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x2700
movq -0x38(%rbp), %rdi
addq $0x1, %rax
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x2700
movq -0x40(%rbp), %rcx
addq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x2c55
movq -0x30(%rbp), %rax
cmpq -0x28(%rbp), %rax
jbe 0x2c53
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
cmpq $0x1, %rax
jbe 0x2c53
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x2b7c
movq -0x20(%rbp), %rax
movq 0x50(%rax), %rax
cmpq -0x10(%rbp), %rax
jne 0x2b5e
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x50(%rax)
jmp 0x2b7a
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
cmpq -0x10(%rbp), %rax
jne 0x2b78
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x48(%rax)
jmp 0x2b7a
jmp 0x2b8a
movq -0x38(%rbp), %rax
movq -0x18(%rbp), %rcx
movq (%rax), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x50(%rax)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0x2bcd
movq -0x10(%rbp), %rcx
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rax
movq %rcx, 0x58(%rax)
movq -0x38(%rbp), %rdi
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x48(%rax)
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x2700
movq -0x38(%rbp), %rdi
addq $0x1, %rax
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x2700
movq -0x58(%rbp), %rcx
movq -0x38(%rbp), %rdi
addq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x2700
movq -0x38(%rbp), %rdi
addq $0x1, %rax
movq %rax, -0x50(%rbp)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x2700
movq -0x50(%rbp), %rcx
addq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x2c55
movq -0x10(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x2c6e
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0x2c70
jmp 0x2c75
jmp 0x2984
jmp 0x2c77
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax)