// File: /workspace/github_cpp_makefile_star2_O2/dlbeer[P]summary_map/./summary_map.hpp
// Function: summary_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int, summary, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, aggregator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>, summary>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>>>::rebalance_after_remove(summary_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int, summary, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, aggregator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>, summary>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>>>::node*)
static void rebalance_after_remove(node *p)
    {
	node *n = 0;
	node *s;

	for (;;) {
	    // If we've hit the root, we're done
	    if (is_header(p))
		return;

	    // At each step here, we have that:
	    //
	    //   - n is black
	    //   - s is non-NULL
	    //   - the black count through n is one less than the count
	    //     through s
	    //
	    // Note that we can't use the sibling(n) to compute s here,
	    // because n might be null.
	    s = (p->left == n) ? p->right : p->left;

	    // If s is red, then p is black and s's children are also
	    // black. Swap colours of p and s, then rotate p towards us.
	    //
	    // This doesn't affect the black count through either path,
	    // but ensures that we have a black parent. It also
	    // invalidates the summary of s (rotation rules).
	    if (is_red(s)) {
		make_red(p);
		make_black(s);
		invalidate(s);

		if (is_right_child(s)) {
		    rotate_left(p);
		    s = p->right;
		} else {
		    rotate_right(p);
		    s = p->left;
		}
	    }

	    // Otherwise, if s is able to become red, colour it so. We
	    // have then balanced p's child subtrees. However, p will
	    // now have a count too low with respect to p's sibling, and
	    // we will have propagated the error upwards.
	    if (is_black(p) && is_black(s->left) && is_black(s->right)) {
		make_red(s);
		n = p;
		p = n->parent;
		continue;
	    }

	    // Otherwise, we will have to fix this by rotations.
	    break;
	}

	// If s and its children are black, but the parent is red, we
	// can just swap colours. This doesn't affect the count through
	// s, but it increases the count through n, this fixing the
	// tree.
	if (is_red(p) && is_black(s->left) && is_black(s->right)) {
	    make_red(s);
	    make_black(p);
	    return;
	}

	// We now know that s has at least one red child. Perform a
	// rotation to ensure that s's red child (or one of them)
	// descends in a different direction to n.
	//
	// We do this, if necessary, by a recolouring and rotation which
	// does not affect black counts.
	if (is_right_child(s) && is_black(s->right)) {
	    make_red(s);
	    make_black(s->left);
	    invalidate(s);
	    invalidate(s->left);
	    rotate_right(s);
	    s = s->parent;
	} else if (is_left_child(s) && is_black(s->left)) {
	    make_red(s);
	    make_black(s->right);
	    invalidate(s);
	    invalidate(s->right);
	    rotate_left(s);
	    s = s->parent;
	}

	// n now has a sibling with a red child whose descent is
	// opposite to that of n's. We don't know what colour p is.
	//
	// Make p black, and then rotate it towards n. Make s take over
	// the colour of p. This increases the black count through n by
	// 1.
	//
	// The far child has had its black parent cut from the path, so
	// recolour it black to balance the count.
	//
	// s is invalidated by this step (p is already invalidated, so
	// we can just copy its flags).
	s->flags = p->flags;
	make_black(p);

	if (is_right_child(s)) {
	    make_black(s->right);
	    rotate_left(p);
	} else {
	    make_black(s->left);
	    rotate_right(p);
	}
    }

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
xorl %eax, %eax
cmpq $0x0, 0x40(%rdi)
je 0x2fab
movq %rdi, %rbx
movq 0x30(%rdi), %r14
cmpq %rax, %r14
jne 0x2f04
movq 0x38(%rbx), %r14
testq %r14, %r14
je 0x2f31
testb $0x1, 0x2c(%r14)
je 0x2f45
orb $0x1, 0x2c(%rbx)
andb $-0x4, 0x2c(%r14)
movq 0x40(%r14), %rax
cmpq %r14, 0x38(%rax)
je 0x2f36
leaq 0x30(%rbx), %r14
movq %rbx, %rdi
callq 0x2c3c
jmp 0x2f42
xorl %r14d, %r14d
jmp 0x2f45
movq %rbx, %rdi
callq 0x2c70
leaq 0x38(%rbx), %r14
movq (%r14), %r14
testb $0x1, 0x2c(%rbx)
jne 0x2f80
movq 0x30(%r14), %rax
testq %rax, %rax
je 0x2f5a
testb $0x1, 0x2c(%rax)
jne 0x2f7a
movq 0x38(%r14), %rax
testq %rax, %rax
je 0x2f69
testb $0x1, 0x2c(%rax)
jne 0x2f7a
orb $0x1, 0x2c(%r14)
movq 0x40(%rbx), %rdi
movq %rbx, %rax
jmp 0x2ee9
leaq 0x2c(%rbx), %r15
jmp 0x2fb1
leaq 0x2c(%rbx), %r15
movq 0x30(%r14), %rax
testq %rax, %rax
je 0x2f93
testb $0x1, 0x2c(%rax)
jne 0x2fb1
movq 0x38(%r14), %rax
testq %rax, %rax
je 0x2fa2
testb $0x1, 0x2c(%rax)
jne 0x2fb1
orb $0x1, 0x2c(%r14)
andb $-0x2, (%r15)
popq %rbx
popq %r14
popq %r15
retq
movq 0x40(%r14), %rax
cmpq %r14, 0x38(%rax)
je 0x2ff0
cmpq %r14, 0x30(%rax)
jne 0x3021
movq 0x30(%r14), %rax
testq %rax, %rax
je 0x2fd0
testb $0x1, 0x2c(%rax)
jne 0x3021
orb $0x1, 0x2c(%r14)
movq 0x38(%r14), %rax
andl $-0x2, 0x2c(%rax)
andb $-0x3, 0x2c(%r14)
andb $-0x3, 0x2c(%rax)
movq %r14, %rdi
callq 0x2c70
jmp 0x301d
movq 0x38(%r14), %rcx
testq %rcx, %rcx
je 0x2fff
testb $0x1, 0x2c(%rcx)
jne 0x2fbb
orb $0x1, 0x2c(%r14)
movq 0x30(%r14), %rax
andl $-0x2, 0x2c(%rax)
andb $-0x3, 0x2c(%r14)
andb $-0x3, 0x2c(%rax)
movq %r14, %rdi
callq 0x2c3c
movq 0x40(%r14), %r14
movl (%r15), %eax
movl %eax, 0x2c(%r14)
andl $-0x2, %eax
movl %eax, (%r15)
movq 0x40(%r14), %rax
cmpq %r14, 0x38(%rax)
je 0x304d
movq 0x30(%r14), %rax
andl $-0x2, 0x2c(%rax)
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x2c3c
movq 0x38(%r14), %rax
andl $-0x2, 0x2c(%rax)
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x2c70