// File: 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:
subq $0x28, %rsp
movq %rdi, 0x20(%rsp)
movq $0x0, 0x18(%rsp)
movq 0x20(%rsp), %rdi
callq 0x4380
testb $0x1, %al
jne 0x4a92
jmp 0x4a97
jmp 0x4d2b
movq 0x20(%rsp), %rax
movq 0x30(%rax), %rax
cmpq 0x18(%rsp), %rax
jne 0x4ab7
movq 0x20(%rsp), %rax
movq 0x38(%rax), %rax
movq %rax, 0x8(%rsp)
jmp 0x4ac5
movq 0x20(%rsp), %rax
movq 0x30(%rax), %rax
movq %rax, 0x8(%rsp)
movq 0x8(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x10(%rsp), %rdi
callq 0x4a40
testb $0x1, %al
jne 0x4adf
jmp 0x4b41
movq 0x20(%rsp), %rdi
callq 0x40f0
movq 0x10(%rsp), %rdi
callq 0x4130
movq 0x10(%rsp), %rdi
callq 0x45d0
movq 0x10(%rsp), %rdi
callq 0x4220
testb $0x1, %al
jne 0x4b0d
jmp 0x4b27
movq 0x20(%rsp), %rdi
callq 0x42e0
movq 0x20(%rsp), %rax
movq 0x38(%rax), %rax
movq %rax, 0x10(%rsp)
jmp 0x4b3f
movq 0x20(%rsp), %rdi
callq 0x4240
movq 0x20(%rsp), %rax
movq 0x30(%rax), %rax
movq %rax, 0x10(%rsp)
jmp 0x4b41
movq 0x20(%rsp), %rdi
callq 0x4150
testb $0x1, %al
jne 0x4b51
jmp 0x4ba0
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rdi
callq 0x4150
testb $0x1, %al
jne 0x4b65
jmp 0x4ba0
movq 0x10(%rsp), %rax
movq 0x38(%rax), %rdi
callq 0x4150
testb $0x1, %al
jne 0x4b79
jmp 0x4ba0
movq 0x10(%rsp), %rdi
callq 0x40f0
movq 0x20(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movq 0x40(%rax), %rax
movq %rax, 0x20(%rsp)
jmp 0x4a82
jmp 0x4ba2
movq 0x20(%rsp), %rdi
callq 0x4a40
testb $0x1, %al
jne 0x4bb2
jmp 0x4bf3
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rdi
callq 0x4150
testb $0x1, %al
jne 0x4bc6
jmp 0x4bf3
movq 0x10(%rsp), %rax
movq 0x38(%rax), %rdi
callq 0x4150
testb $0x1, %al
jne 0x4bda
jmp 0x4bf3
movq 0x10(%rsp), %rdi
callq 0x40f0
movq 0x20(%rsp), %rdi
callq 0x4130
jmp 0x4d2b
movq 0x10(%rsp), %rdi
callq 0x4220
testb $0x1, %al
jne 0x4c03
jmp 0x4c61
movq 0x10(%rsp), %rax
movq 0x38(%rax), %rdi
callq 0x4150
testb $0x1, %al
jne 0x4c17
jmp 0x4c61
movq 0x10(%rsp), %rdi
callq 0x40f0
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rdi
callq 0x4130
movq 0x10(%rsp), %rdi
callq 0x45d0
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rdi
callq 0x45d0
movq 0x10(%rsp), %rdi
callq 0x4240
movq 0x10(%rsp), %rax
movq 0x40(%rax), %rax
movq %rax, 0x10(%rsp)
jmp 0x4ccf
movq 0x10(%rsp), %rdi
callq 0x4200
testb $0x1, %al
jne 0x4c71
jmp 0x4ccd
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rdi
callq 0x4150
testb $0x1, %al
jne 0x4c85
jmp 0x4ccd
movq 0x10(%rsp), %rdi
callq 0x40f0
movq 0x10(%rsp), %rax
movq 0x38(%rax), %rdi
callq 0x4130
movq 0x10(%rsp), %rdi
callq 0x45d0
movq 0x10(%rsp), %rax
movq 0x38(%rax), %rdi
callq 0x45d0
movq 0x10(%rsp), %rdi
callq 0x42e0
movq 0x10(%rsp), %rax
movq 0x40(%rax), %rax
movq %rax, 0x10(%rsp)
jmp 0x4ccf
movq 0x20(%rsp), %rax
movl 0x2c(%rax), %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x2c(%rax)
movq 0x20(%rsp), %rdi
callq 0x4130
movq 0x10(%rsp), %rdi
callq 0x4220
testb $0x1, %al
jne 0x4cf9
jmp 0x4d13
movq 0x10(%rsp), %rax
movq 0x38(%rax), %rdi
callq 0x4130
movq 0x20(%rsp), %rdi
callq 0x42e0
jmp 0x4d2b
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rdi
callq 0x4130
movq 0x20(%rsp), %rdi
callq 0x4240
addq $0x28, %rsp
retq