1 /**
2  * Implementation of a custom allocator red-black tree container.
3  * 
4  * Copyright: Red-black tree code copyright (C) 2008- by Steven Schveighoffer. Other code
5  * copyright 2010- Andrei Alexandrescu. All rights reserved by the respective holders.
6  * License: Distributed under the Boost Software License, Version 1.0.
7  * (See at $(WEB boost.org/LICENSE_1_0.txt)).
8  * Authors: Steven Schveighoffer, $(WEB erdani.com, Andrei Alexandrescu)
9 */
10 module memutils.rbtree;
11 
12 import std.functional; // : binaryFun;
13 import std.traits;
14 import std.range;
15 import std.algorithm : countUntil;
16 import memutils.allocators;
17 import memutils.refcounted;
18 import memutils.vector;
19 import memutils.constants;
20 import memutils.utils;
21 
22 alias RBTreeRef(T,  alias less = "a < b", bool allowDuplicates = true, ALLOC = ThreadMem, bool NOGC_ = false) = RefCounted!(RBTree!(T, less, allowDuplicates, ALLOC, NOGC_));
23 
24 template isImplicitlyConvertibleLegacy(From, To)
25 {
26     enum bool isImplicitlyConvertibleLegacy = is(typeof({
27         void fun(ref From v)
28         {
29             void gun(To) {}
30             gun(v);
31         }
32     }));
33 }
34 
35 /**
36  * All inserts, removes, searches, and any function in general has complexity
37  * of $(BIGOH lg(n)).
38  *
39  * To use a different comparison than $(D "a < b"), pass a different operator string
40  * that can be used by $(XREF functional, binaryFun), or pass in a
41  * function, delegate, functor, or any type where $(D less(a, b)) results in a $(D bool)
42  * value.
43  *
44  * Note that less should produce a strict ordering.  That is, for two unequal
45  * elements $(D a) and $(D b), $(D less(a, b) == !less(b, a)). $(D less(a, a)) should
46  * always equal $(D false).
47  *
48  * If $(D allowDuplicates) is set to $(D true), then inserting the same element more than
49  * once continues to add more elements.  If it is $(D false), duplicate elements are
50  * ignored on insertion.  If duplicates are allowed, then new elements are
51  * inserted after all existing duplicate elements.
52  */
53 struct RBTree(T, alias less = "a < b", bool allowDuplicates = true, ALLOC = ThreadMem, bool NOGC_ = false)
54 	if(is(typeof(binaryFun!less(T.init, T.init))))
55 {
56 	@disable this(this);
57 
58 	import std.range : Take;
59 	import std.typetuple : allSatisfy;
60 	import std.traits;
61 	
62 	alias _less = binaryFun!less;
63 	
64 	// BUG: this must come first in the struct due to issue 2810
65 	
66 	// add an element to the tree, returns the node added, or the existing node
67 	// if it has already been added and allowDuplicates is false
68 	
69 	private auto _add(Elem n)
70 	{
71 		Node result;
72 		static if(!allowDuplicates)
73 			bool added = true;
74 
75 		if(!_end.left)
76 		{
77 			_end.left = _begin = result = allocate(n);
78 		}
79 		else
80 		{
81 			Node newParent = _end.left;
82 			Node nxt = void;
83 			while(true)
84 			{
85 				if(_less(n, newParent.value))
86 				{
87 					nxt = newParent.left;
88 					if(nxt is null)
89 					{
90 						//
91 						// add to right of new parent
92 						//
93 						newParent.left = result = allocate(n);
94 						break;
95 					}
96 				}
97 				else
98 				{
99 					static if(!allowDuplicates)
100 					{
101 						if(!_less(newParent.value, n))
102 						{
103 							result = newParent;
104 							added = false;
105 							break;
106 						}
107 					}
108 					nxt = newParent.right;
109 					if(nxt is null)
110 					{
111 						//
112 						// add to right of new parent
113 						//
114 						newParent.right = result = allocate(n);
115 						break;
116 					}
117 				}
118 				newParent = nxt;
119 			}
120 			if(_begin.left)
121 				_begin = _begin.left;
122 		}
123 		
124 		static if(allowDuplicates)
125 		{
126 			result.setColor(_end);
127 			++_length;
128 			return result;
129 		}
130 		else
131 		{
132 			import std.typecons : Tuple;
133 			
134 			if(added)
135 			{
136 				++_length;
137 				result.setColor(_end);
138 			}
139 			return Tuple!(bool, "added", Node, "n")(added, result);
140 		}
141 	}
142 	
143 	
144 	private enum doUnittest = false;
145 	
146 	/**
147       * Element type for the tree
148       */
149 	alias Elem = T;
150 	
151 	// used for convenience
152 	private alias Node = RBNode!(Elem, ALLOC, NOGC_).Node;
153 
154 	private Node   _root;
155 	private Node   _end;
156 	private Node   _begin;
157 	private size_t _length;
158 
159 	package void _defaultInitialize()
160 	{
161 		if (!_end) {
162 			_begin = _end = _root = allocate();
163 		}
164 	}
165 	
166 	static private Node allocate()
167 	{
168 		return ObjectAllocator!(RBNode!(Elem, ALLOC, NOGC_), ALLOC).alloc();
169 	}
170 	
171 	static private Node allocate(Elem v)
172 	{
173 		auto result = allocate();
174 		logTrace("Allocating node ", cast(void*)result);
175 		result.value = v;
176 		return result;
177 	}
178 	
179 	// find a node based on an element value
180 	private Node _find(Elem e) const
181 	{
182 		static if(allowDuplicates)
183 		{
184 			Node cur = _end.left;
185 			Node result = null;
186 			while(cur)
187 			{
188 				if(_less(cur.value, e))
189 					cur = cur.right;
190 				else if(_less(e, cur.value))
191 					cur = cur.left;
192 				else
193 				{
194 					// want to find the left-most element
195 					result = cur;
196 					cur = cur.left;
197 				}
198 			}
199 			return result;
200 		}
201 		else
202 		{
203 			Node cur = _end.left;
204 			while(cur)
205 			{
206 				if(_less(cur.value, e))
207 					cur = cur.right;
208 				else if(_less(e, cur.value))
209 					cur = cur.left;
210 				else
211 					return cur;
212 			}
213 			return null;
214 		}
215 	}
216 	
217 	
218 	
219 	/**
220      * Check if any elements exist in the container.  Returns $(D false) if at least
221      * one element exists.
222      */
223 	@property bool empty() const
224 	{
225 		return _end.left is null;
226 	}
227 	
228 	/++
229         Returns the number of elements in the container.
230 
231         Complexity: $(BIGOH 1).
232     +/
233 	@property size_t length() const
234 	{
235 		return _length;
236 	}
237 		
238 	/**
239      * Fetch a range that spans all the elements in the container.
240      *
241      * Complexity: $(BIGOH 1)
242      */
243 	RBRange!(Elem, ALLOC, NOGC_) opSlice()
244 	{
245 		_defaultInitialize();
246 		return range!(T, ALLOC, NOGC_)(_begin, _end);
247 	}
248 	
249 	/**
250      * The front element in the container
251      *
252      * Complexity: $(BIGOH 1)
253      */
254 	ref Elem front()
255 	{
256 		_defaultInitialize();
257 		return _begin.value;
258 	}
259 	
260 	/**
261      * The last element in the container
262      *
263      * Complexity: $(BIGOH log(n))
264      */
265 	ref Elem back()
266 	{
267 		_defaultInitialize();
268 		return _end.prev.value;
269 	}
270 	
271 	/++
272         $(D in) operator. Check to see if the given element exists in the
273         container.
274 
275        Complexity: $(BIGOH log(n))
276      +/
277 	pragma(inline, true)
278 	bool opBinaryRight(string op)(Elem e) const if (op == "in") 
279 	{
280 		return _find(e) !is null;
281 	}
282 	
283 	/**
284      * Removes all elements from the container.
285      *
286      * Complexity: $(BIGOH 1)
287      */
288 	void clear()
289 	{
290 		_defaultInitialize();
291 		logTrace("Clearing rbtree");
292 		while (length > 0)
293 			removeAny();
294 		logTrace(length, " items left");
295 		return;
296 	}
297 	
298 	/**
299      * Insert a single element in the container.  Note that this does not
300      * invalidate any ranges currently iterating the container.
301      *
302      * Complexity: $(BIGOH log(n))
303      */
304 	pragma(inline, true)
305 	size_t insert(Stuff)(Stuff stuff) if (isImplicitlyConvertibleLegacy!(Stuff, Elem))
306 	{
307 		_defaultInitialize();
308 		static if(allowDuplicates)
309 		{
310 			_add(stuff);
311 			return 1;
312 		}
313 		else
314 		{
315 			return(_add(stuff).added ? 1 : 0);
316 		}
317 	}
318 	
319 	/**
320      * Insert a range of elements in the container.  Note that this does not
321      * invalidate any ranges currently iterating the container.
322      *
323      * Complexity: $(BIGOH m * log(n))
324      */
325 	pragma(inline, true)
326 	size_t insert(Stuff)(Stuff stuff) if(isInputRange!Stuff && isImplicitlyConvertibleLegacy!(ElementType!Stuff, Elem))
327 	{
328 		_defaultInitialize();
329 		size_t result = 0;
330 		static if(allowDuplicates)
331 		{
332 			foreach(e; stuff)
333 			{
334 				++result;
335 				_add(e);
336 			}
337 		}
338 		else
339 		{
340 			foreach(e; stuff)
341 			{
342 				if(_add(e).added)
343 					++result;
344 			}
345 		}
346 		return result;
347 	}
348 
349 	
350 	/**
351      * Remove an element from the container and return its value.
352      *
353      * Complexity: $(BIGOH log(n))
354      */
355 	Elem removeAny()
356 	{
357 		_defaultInitialize();
358 		scope(success)
359 			--_length;
360 		auto n = _begin;
361 		auto result = n.value;
362 		_begin = n.remove(_end);
363 		return result;
364 	}
365 	
366 	/**
367      * Remove the front element from the container.
368      *
369      * Complexity: $(BIGOH log(n))
370      */
371 	void removeFront()
372 	{
373 		_defaultInitialize();
374 		scope(success)
375 			--_length;
376 		_begin = _begin.remove(_end);
377 	}
378 	
379 	/**
380      * Remove the back element from the container.
381      *
382      * Complexity: $(BIGOH log(n))
383      */
384 	void removeBack()
385 	{
386 		_defaultInitialize();
387 		scope(success)
388 			--_length;
389 		auto lastnode = _end.prev;
390 		if(lastnode is _begin)
391 			_begin = _begin.remove(_end);
392 		else
393 			lastnode.remove(_end);
394 	}
395 	
396 	/++
397        Removes elements from the container that are equal to the given values
398        according to the less comparator. One element is removed for each value
399        given which is in the container. If $(D allowDuplicates) is true,
400        duplicates are removed only if duplicate values are given.
401 
402        Returns: The number of elements removed.
403 
404        Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove)
405 
406        Examples:
407 --------------------
408 auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
409 rbt.removeKey(1, 4, 7);
410 assert(equal(rbt[], [0, 1, 1, 5]));
411 rbt.removeKey(1, 1, 0);
412 assert(equal(rbt[], [5]));
413 --------------------
414       +/
415 	size_t remove(U...)(U elems)
416 		if(allSatisfy!(isImplicitlyConvertibleToElem, U))
417 	{
418 		_defaultInitialize();
419 		Elem[U.length] toRemove;
420 		
421 		foreach(i, e; elems)
422 			toRemove[i] = e;
423 		
424 		return remove(toRemove[]);
425 	}
426 	
427 	/++ Ditto +/
428 	size_t remove(U)(U[] elems)
429 		if(isImplicitlyConvertibleLegacy!(U, Elem))
430 	{
431 		_defaultInitialize();
432 		immutable lenBefore = length;
433 		
434 		foreach(e; elems)
435 		{
436 			auto beg = _firstGreaterEqual(e);
437 			if(beg is _end || _less(e, beg.value))
438 				// no values are equal
439 				continue;
440 			immutable isBegin = (beg is _begin);
441 			beg = beg.remove(_end);
442 			if(isBegin)
443 				_begin = beg;
444 			--_length;
445 		}
446 		
447 		return lenBefore - length;
448 	}
449 	
450 	/++ Ditto +/
451 	size_t remove(Stuff)(Stuff stuff)
452 		if(isInputRange!Stuff &&
453 			isImplicitlyConvertibleLegacy!(ElementType!Stuff, Elem) &&
454 			!isDynamicArray!Stuff)
455 	{
456 		_defaultInitialize();
457 		import std.array : array;
458 		//We use array in case stuff is a Range from this RedBlackTree - either
459 		//directly or indirectly.
460 		return remove(array(stuff));
461 	}
462 	
463 	//Helper for removeKey.
464 	private template isImplicitlyConvertibleToElem(U)
465 	{
466 		enum isImplicitlyConvertibleToElem = isImplicitlyConvertibleLegacy!(U, Elem);
467 	}
468 	
469 	/**
470      * Compares two trees for equality.
471      *
472      * Complexity: $(BIGOH n*log(n))
473      */
474 	bool opEquals(ref RBTree rhs)
475 	{
476 		_defaultInitialize();
477 		import std.algorithm : equal;
478 		if (rhs.empty) return false;
479 		
480 		// If there aren't the same number of nodes, we can't be equal.
481 		if (this._length != rhs._length) return false;
482 		
483 		auto thisRange = this[];
484 		auto thatRange = rhs[];
485 		return equal!(function(Elem a, Elem b) => !_less(a,b) && !_less(b,a))(thisRange, thatRange);
486 	}
487 	
488 	// find the first node where the value is > e
489 	private Node _firstGreater(Elem e)
490 	{
491 		// can't use _find, because we cannot return null
492 		auto cur = _end.left;
493 		auto result = _end;
494 		while(cur)
495 		{
496 			if(_less(e, cur.value))
497 			{
498 				result = cur;
499 				cur = cur.left;
500 			}
501 			else
502 				cur = cur.right;
503 		}
504 		return result;
505 	}
506 	
507 	// find the first node where the value is >= e
508 	private Node _firstGreaterEqual(Elem e)
509 	{
510 		// can't use _find, because we cannot return null.
511 		auto cur = _end.left;
512 		auto result = _end;
513 		while(cur)
514 		{
515 			if(_less(cur.value, e))
516 				cur = cur.right;
517 			else
518 			{
519 				result = cur;
520 				cur = cur.left;
521 			}
522 			
523 		}
524 		return result;
525 	}
526 	
527 	/**
528      * Get a range from the container with all elements that are > e according
529      * to the less comparator
530      *
531      * Complexity: $(BIGOH log(n))
532      */
533 	auto upperBoundRange(Elem e)
534 	{
535 		_defaultInitialize();
536 		return range!(T, ALLOC, NOGC_)(_firstGreater(e), _end);
537 	}
538 	
539 	/**
540      * Get a range from the container with all elements that are < e according
541      * to the less comparator
542      *
543      * Complexity: $(BIGOH log(n))
544      */
545 	auto lowerBoundRange(Elem e)
546 	{
547 		_defaultInitialize();
548 		return range!(T, ALLOC, NOGC_)(_begin, _firstGreaterEqual(e));
549 	}
550 	
551 	/**
552      * Get a range from the container with all elements that are == e according
553      * to the less comparator
554      *
555      * Complexity: $(BIGOH log(n))
556      */
557 	auto getValuesAt(Elem e)
558 	{
559 		_defaultInitialize();
560 		auto beg = _firstGreaterEqual(e);
561 		if(beg is _end || _less(e, beg.value))
562 			// no values are equal
563 			return range!(T, ALLOC, NOGC_)(beg, beg);
564 		static if(allowDuplicates)
565 		{
566 			return range!(T, ALLOC, NOGC_)(beg, _firstGreater(e));
567 		}
568 		else
569 		{
570 			// no sense in doing a full search, no duplicates are allowed,
571 			// so we just get the next node.
572 			return range!(T, ALLOC, NOGC_)(beg, beg.next);
573 		}
574 	}
575 
576 	this(size_t elems) {
577 		_defaultInitialize();
578 	}
579 
580 	/**
581      * Constructor. Pass in an array of elements, or individual elements to
582      * initialize the tree with.
583      */
584 	this(Elem[] elems...)
585 	{
586 		_defaultInitialize();
587 		static if (is(Elem == void[])) {
588 			foreach(elem;elems) insert(elem);
589 		}
590 		else
591 			insert(elems);
592 	}
593 	
594 	/**
595      * Constructor. Pass in a range of elements to initialize the tree with.
596      */
597 	this(Stuff)(Stuff stuff) if (isInputRange!Stuff && isImplicitlyConvertibleLegacy!(ElementType!Stuff, Elem))
598 	{
599 		_defaultInitialize();
600 		insert(stuff);
601 	}
602 
603 	~this() {
604 		if (!_end) return;
605 		clear();
606 		ObjectAllocator!(RBNode!(Elem, ALLOC, NOGC_), ALLOC).free(_root);
607 	}
608 	
609 	private this(Node end, size_t length)
610 	{
611 		_end = end;
612 		_begin = end.leftmost;
613 		_length = length;
614 	}
615 }
616 
617 /*
618  * Implementation for a Red Black node for use in a Red Black Tree (see below)
619  *
620  * this implementation assumes we have a marker Node that is the parent of the
621  * root Node.  This marker Node is not a valid Node, but marks the end of the
622  * collection.  The root is the left child of the marker Node, so it is always
623  * last in the collection.  The marker Node is passed in to the setColor
624  * function, and the Node which has this Node as its parent is assumed to be
625  * the root Node.
626  *
627  * A Red Black tree should have O(lg(n)) insertion, removal, and search time.
628  */
629 struct RBNode(V, ALLOC, bool NOGC_ = false)
630 {
631 	enum NOGC = NOGC_;
632 	/*
633      * Convenience alias
634      */
635 	alias Node = RBNode!(V, ALLOC, NOGC_)*;
636 	
637 	private Node _left;
638 	private Node _right;
639 	private Node _parent;
640 	
641 	/**
642      * The value held by this node
643      */
644 	V value;
645 	
646 	/**
647      * Enumeration determining what color the node is.  Null nodes are assumed
648      * to be black.
649      */
650 	enum Color : byte
651 	{
652 		Red,
653 		Black
654 	}
655 	
656 	/**
657      * The color of the node.
658      */
659 	Color color;
660 	
661 	/**
662      * Get the left child
663      */
664 	@property Node left() const
665 	{
666 		return cast(Node)_left;
667 	}
668 	
669 	/**
670      * Get the right child
671      */
672 	@property inout(Node) right() inout
673 	{
674 		return _right;
675 	}
676 	
677 	/**
678      * Get the parent
679      */
680 	@property Node parent()
681 	{
682 		return _parent;
683 	}
684 	
685 	/**
686      * Set the left child.  Also updates the new child's parent node.  This
687      * does not update the previous child.
688      *
689      * Returns newNode
690      */
691 	@property Node left(Node newNode)
692 	{
693 		_left = newNode;
694 		if(newNode !is null)
695 			newNode._parent = &this;
696 		return newNode;
697 	}
698 	
699 	/**
700      * Set the right child.  Also updates the new child's parent node.  This
701      * does not update the previous child.
702      *
703      * Returns newNode
704      */
705 	@property Node right(Node newNode)
706 	{
707 		_right = newNode;
708 		if(newNode !is null)
709 			newNode._parent = &this;
710 		return newNode;
711 	}
712 	
713 	// assume _left is not null
714 	//
715 	// performs rotate-right operation, where this is T, _right is R, _left is
716 	// L, _parent is P:
717 	//
718 	//      P         P
719 	//      |   ->    |
720 	//      T         L
721 	//     / \       / \
722 	//    L   R     a   T
723 	//   / \           / \
724 	//  a   b         b   R
725 	//
726 	/**
727      * Rotate right.  This performs the following operations:
728      *  - The left child becomes the parent of this node.
729      *  - This node becomes the new parent's right child.
730      *  - The old right child of the new parent becomes the left child of this
731      *    node.
732      */
733 	Node rotateR()
734 		in
735 	{
736 		assert(_left !is null);
737 	}
738 	do
739 	{
740 		// sets _left._parent also
741 		if(isLeftNode)
742 			parent.left = _left;
743 		else
744 			parent.right = _left;
745 		Node tmp = _left._right;
746 		
747 		// sets _parent also
748 		_left.right = &this;
749 		
750 		// sets tmp._parent also
751 		left = tmp;
752 		
753 		return &this;
754 	}
755 	
756 	// assumes _right is non null
757 	//
758 	// performs rotate-left operation, where this is T, _right is R, _left is
759 	// L, _parent is P:
760 	//
761 	//      P           P
762 	//      |    ->     |
763 	//      T           R
764 	//     / \         / \
765 	//    L   R       T   b
766 	//       / \     / \
767 	//      a   b   L   a
768 	//
769 	/**
770      * Rotate left.  This performs the following operations:
771      *  - The right child becomes the parent of this node.
772      *  - This node becomes the new parent's left child.
773      *  - The old left child of the new parent becomes the right child of this
774      *    node.
775      */
776 	Node rotateL()
777 		in
778 	{
779 		assert(_right !is null);
780 	}
781 	do
782 	{
783 		// sets _right._parent also
784 		if(isLeftNode)
785 			parent.left = _right;
786 		else
787 			parent.right = _right;
788 		Node tmp = _right._left;
789 		
790 		// sets _parent also
791 		_right.left = &this;
792 		
793 		// sets tmp._parent also
794 		right = tmp;
795 		return &this;
796 	}
797 	
798 	
799 	/**
800      * Returns true if this node is a left child.
801      *
802      * Note that this should always return a value because the root has a
803      * parent which is the marker node.
804      */
805 	@property bool isLeftNode() const
806 	in
807 	{
808 		assert(_parent !is null);
809 	}
810 	do
811 	{
812 		return _parent._left is &this;
813 	}
814 	
815 	/**
816      * Set the color of the node after it is inserted.  This performs an
817      * update to the whole tree, possibly rotating nodes to keep the Red-Black
818      * properties correct.  This is an O(lg(n)) operation, where n is the
819      * number of nodes in the tree.
820      *
821      * end is the marker node, which is the parent of the topmost valid node.
822      */
823 	void setColor(Node end)
824 	{
825 		// test against the marker node
826 		if(_parent !is end)
827 		{
828 			if(_parent.color == Color.Red)
829 			{
830 				Node cur = &this;
831 				while(true)
832 				{
833 					// because root is always black, _parent._parent always exists
834 					if(cur._parent.isLeftNode)
835 					{
836 						// parent is left node, y is 'uncle', could be null
837 						Node y = cur._parent._parent._right;
838 						if(y !is null && y.color == Color.Red)
839 						{
840 							cur._parent.color = Color.Black;
841 							y.color = Color.Black;
842 							cur = cur._parent._parent;
843 							if(cur._parent is end)
844 							{
845 								// root node
846 								cur.color = Color.Black;
847 								break;
848 							}
849 							else
850 							{
851 								// not root node
852 								cur.color = Color.Red;
853 								if(cur._parent.color == Color.Black)
854 									// satisfied, exit the loop
855 									break;
856 							}
857 						}
858 						else
859 						{
860 							if(!cur.isLeftNode)
861 								cur = cur._parent.rotateL();
862 							cur._parent.color = Color.Black;
863 							cur = cur._parent._parent.rotateR();
864 							cur.color = Color.Red;
865 							// tree should be satisfied now
866 							break;
867 						}
868 					}
869 					else
870 					{
871 						// parent is right node, y is 'uncle'
872 						Node y = cur._parent._parent._left;
873 						if(y !is null && y.color == Color.Red)
874 						{
875 							cur._parent.color = Color.Black;
876 							y.color = Color.Black;
877 							cur = cur._parent._parent;
878 							if(cur._parent is end)
879 							{
880 								// root node
881 								cur.color = Color.Black;
882 								break;
883 							}
884 							else
885 							{
886 								// not root node
887 								cur.color = Color.Red;
888 								if(cur._parent.color == Color.Black)
889 									// satisfied, exit the loop
890 									break;
891 							}
892 						}
893 						else
894 						{
895 							if(cur.isLeftNode)
896 								cur = cur._parent.rotateR();
897 							cur._parent.color = Color.Black;
898 							cur = cur._parent._parent.rotateL();
899 							cur.color = Color.Red;
900 							// tree should be satisfied now
901 							break;
902 						}
903 					}
904 				}
905 				
906 			}
907 		}
908 		else
909 		{
910 			//
911 			// this is the root node, color it black
912 			//
913 			color = Color.Black;
914 		}
915 	}
916 	
917 	/**
918      * Remove this node from the tree.  The 'end' node is used as the marker
919      * which is root's parent.  Note that this cannot be null!
920      *
921      * Returns the next highest valued node in the tree after this one, or end
922      * if this was the highest-valued node.
923      */
924 	Node remove(Node end)
925 	{
926 		//
927 		// remove this node from the tree, fixing the color if necessary.
928 		//
929 		Node x;
930 		Node ret = next;
931 		
932 		// if this node has 2 children
933 		if (_left !is null && _right !is null)
934 		{
935 			//
936 			// normally, we can just swap this node's and y's value, but
937 			// because an iterator could be pointing to y and we don't want to
938 			// disturb it, we swap this node and y's structure instead.  This
939 			// can also be a benefit if the value of the tree is a large
940 			// struct, which takes a long time to copy.
941 			//
942 			Node yp, yl, yr;
943 			Node y = ret; // y = next
944 			yp = y._parent;
945 			yl = y._left;
946 			yr = y._right;
947 			auto yc = y.color;
948 			auto isyleft = y.isLeftNode;
949 			
950 			//
951 			// replace y's structure with structure of this node.
952 			//
953 			if(isLeftNode)
954 				_parent.left = y;
955 			else
956 				_parent.right = y;
957 			//
958 			// need special case so y doesn't point back to itself
959 			//
960 			y.left = _left;
961 			if(_right is y)
962 				y.right = &this;
963 			else
964 				y.right = _right;
965 			y.color = color;
966 			
967 			//
968 			// replace this node's structure with structure of y.
969 			//
970 			left = yl;
971 			right = yr;
972 			if(_parent !is y)
973 			{
974 				if(isyleft)
975 					yp.left = &this;
976 				else
977 					yp.right = &this;
978 			}
979 			color = yc;
980 		}
981 		
982 		// if this has less than 2 children, remove it
983 		if(_left !is null)
984 			x = _left;
985 		else
986 			x = _right;
987 		
988 		bool deferedUnlink = false;
989 		if(x is null)
990 		{
991 			// pretend this is a null node, defer unlinking the node
992 			x = &this;
993 			deferedUnlink = true;
994 		}
995 		else if(isLeftNode)
996 			_parent.left = x;
997 		else
998 			_parent.right = x;
999 		
1000 		// if the color of this is black, then it needs to be fixed
1001 		if(color == color.Black)
1002 		{
1003 			// need to recolor the tree.
1004 			while(x._parent !is end && x.color == Node.Color.Black)
1005 			{
1006 				if(x.isLeftNode)
1007 				{
1008 					// left node
1009 					Node w = x._parent._right;
1010 					if(w.color == Node.Color.Red)
1011 					{
1012 						w.color = Node.Color.Black;
1013 						x._parent.color = Node.Color.Red;
1014 						x._parent.rotateL();
1015 						w = x._parent._right;
1016 					}
1017 					Node wl = w.left;
1018 					Node wr = w.right;
1019 					if((wl is null || wl.color == Node.Color.Black) &&
1020 						(wr is null || wr.color == Node.Color.Black))
1021 					{
1022 						w.color = Node.Color.Red;
1023 						x = x._parent;
1024 					}
1025 					else
1026 					{
1027 						if(wr is null || wr.color == Node.Color.Black)
1028 						{
1029 							// wl cannot be null here
1030 							wl.color = Node.Color.Black;
1031 							w.color = Node.Color.Red;
1032 							w.rotateR();
1033 							w = x._parent._right;
1034 						}
1035 						
1036 						w.color = x._parent.color;
1037 						x._parent.color = Node.Color.Black;
1038 						w._right.color = Node.Color.Black;
1039 						x._parent.rotateL();
1040 						x = end.left; // x = root
1041 					}
1042 				}
1043 				else
1044 				{
1045 					// right node
1046 					Node w = x._parent._left;
1047 					if(w.color == Node.Color.Red)
1048 					{
1049 						w.color = Node.Color.Black;
1050 						x._parent.color = Node.Color.Red;
1051 						x._parent.rotateR();
1052 						w = x._parent._left;
1053 					}
1054 					Node wl = w.left;
1055 					Node wr = w.right;
1056 					if((wl is null || wl.color == Node.Color.Black) &&
1057 						(wr is null || wr.color == Node.Color.Black))
1058 					{
1059 						w.color = Node.Color.Red;
1060 						x = x._parent;
1061 					}
1062 					else
1063 					{
1064 						if(wl is null || wl.color == Node.Color.Black)
1065 						{
1066 							// wr cannot be null here
1067 							wr.color = Node.Color.Black;
1068 							w.color = Node.Color.Red;
1069 							w.rotateL();
1070 							w = x._parent._left;
1071 						}
1072 						
1073 						w.color = x._parent.color;
1074 						x._parent.color = Node.Color.Black;
1075 						w._left.color = Node.Color.Black;
1076 						x._parent.rotateR();
1077 						x = end.left; // x = root
1078 					}
1079 				}
1080 			}
1081 			x.color = Node.Color.Black;
1082 		}
1083 		
1084 		if(deferedUnlink)
1085 		{
1086 			//
1087 			// unlink this node from the tree
1088 			//
1089 			if(isLeftNode)
1090 				_parent.left = null;
1091 			else
1092 				_parent.right = null;
1093 			
1094 		}
1095 		
1096 		// clean references to help GC - Bugzilla 12915
1097 		_left = _right = _parent = null;
1098 		
1099 		/// this node object can now be safely deleted
1100 		logTrace("Freeing node ", cast(void*)&this);
1101 		ObjectAllocator!(RBNode!(V, ALLOC, NOGC_), ALLOC).free(cast(RBNode!(V, ALLOC, NOGC_)*)&this);
1102 		
1103 		return ret;
1104 	}
1105 	
1106 	/**
1107      * Return the leftmost descendant of this node.
1108      */
1109 	@property Node leftmost()
1110 	{
1111 		Node result = &this;
1112 		while(result._left !is null)
1113 			result = result._left;
1114 		return result;
1115 	}
1116 	
1117 	/**
1118      * Return the rightmost descendant of this node
1119      */
1120 	@property Node rightmost()
1121 	{
1122 		Node result = &this;
1123 		while(result._right !is null)
1124 			result = result._right;
1125 		return result;
1126 	}
1127 	
1128 	/**
1129      * Returns the next valued node in the tree.
1130      *
1131      * You should never call this on the marker node, as it is assumed that
1132      * there is a valid next node.
1133      */
1134 	@property Node next()
1135 	{
1136 		Node n = &this;
1137 		if(n.right is null)
1138 		{
1139 			while(n._parent && !n.isLeftNode)
1140 				n = n._parent;
1141 			return n._parent;
1142 		}
1143 		else if (n.right !is null) {
1144 			if (!n._parent) return null;
1145 			return n.right.leftmost;
1146 		}
1147 		else return null;
1148 	}
1149 	
1150 	/**
1151      * Returns the previous valued node in the tree.
1152      *
1153      * You should never call this on the leftmost node of the tree as it is
1154      * assumed that there is a valid previous node.
1155      */
1156 	@property Node prev()
1157 	{
1158 		Node n = &this;
1159 		if(n.left is null)
1160 		{
1161 			while(n.isLeftNode)
1162 				n = n._parent;
1163 			return n._parent;
1164 		}
1165 		else
1166 			return n.left.rightmost;
1167 	}
1168 	
1169 	@property Node clone() const
1170 	{
1171 		Node copy = ObjectAllocator!(RBNode!(V, ALLOC, NOGC_), ALLOC).alloc();
1172 		logTrace("Allocating node ", cast(void*)copy);
1173 		copy.value = cast(V)value;
1174 		copy.color = color;
1175 		if(_left !is null)
1176 			copy.left = _left.clone();
1177 		if(_right !is null)
1178 			copy.right = _right.clone();
1179 		return copy;
1180 	}
1181 
1182 	@disable @property Node dup() const;
1183 }
1184 
1185 /**
1186  * The range type for $(D RedBlackTree)
1187  */
1188 struct RBRange(Elem, ALLOC, bool NOGC_ = false)
1189 {
1190 	alias Node = RBNode!(Elem, ALLOC, NOGC_).Node;
1191 	private Node _begin;
1192 	private Node _end;
1193 	
1194 	private this(Node b, Node e)
1195 	{
1196 		_begin = b;
1197 		_end = e;
1198 	}
1199 
1200 	/**
1201      * Returns $(D true) if the range is _empty
1202      */
1203 	@property bool empty() const
1204 	{
1205 		return _begin is _end || !_begin;
1206 	}
1207 	
1208 	/**
1209      * Returns the first element in the range
1210      */
1211 	@property ref Elem front()
1212 	{
1213 		return _begin.value;
1214 	}
1215 	
1216 	/**
1217          * Returns the last element in the range
1218          */
1219 	@property ref Elem back()
1220 	{
1221 		return _end.prev.value;
1222 	}
1223 	
1224 	/**
1225          * pop the front element from the range
1226          *
1227          * complexity: amortized $(BIGOH 1)
1228          */
1229 	void popFront()
1230 	{
1231 		_begin = _begin.next;
1232 	}
1233 	
1234 	/**
1235          * pop the back element from the range
1236          *
1237          * complexity: amortized $(BIGOH 1)
1238          */
1239 	void popBack()
1240 	{
1241 		_end = _end.prev;
1242 	}
1243 	
1244 	/**
1245          * Trivial _save implementation, needed for $(D isForwardRBRange).
1246          */
1247 	@property RBRange save()
1248 	{
1249 		return *cast(RBRange*)&this;
1250 	}
1251 }
1252 
1253 private auto range(Elem, ALLOC, bool NOGC_ = false)(RBNode!(Elem, ALLOC, NOGC_)* start, RBNode!(Elem, ALLOC, NOGC_)* end) {
1254 	return RBRange!(Elem, ALLOC, NOGC_)(start, end);
1255 }
1256 
1257 auto vector(Elem, ALLOC, bool NOGC_ = false)(RBRange!(Elem, ALLOC, NOGC_) r) {
1258 	return Vector!(Unqual!Elem, ALLOC)(r);
1259 }