1 /**
2 This module implements a red-black tree container.
3 
4 This module is a submodule of $(MREF std, container).
5 
6 Source: $(PHOBOSSRC std/container/rbtree.d)
7 
8 Copyright: Red-black tree code copyright (C) 2008- by Steven Schveighoffer. Other code
9 copyright 2010- Andrei Alexandrescu. All rights reserved by the respective holders.
10 
11 License: Distributed under the Boost Software License, Version 1.0.
12 (See accompanying file LICENSE_1_0.txt or copy at $(HTTP
13 boost.org/LICENSE_1_0.txt)).
14 
15 Authors: Steven Schveighoffer, $(HTTP erdani.com, Andrei Alexandrescu)
16 */
17 module std.container.rbtree;
18 
19 ///
20 @safe pure unittest
21 {
22     import std.algorithm.comparison : equal;
23     import std.container.rbtree;
24 
25     auto rbt = redBlackTree(3, 1, 4, 2, 5);
26     assert(rbt.front == 1);
27     assert(equal(rbt[], [1, 2, 3, 4, 5]));
28 
29     rbt.removeKey(1, 4);
30     assert(equal(rbt[], [2, 3, 5]));
31 
32     rbt.removeFront();
33     assert(equal(rbt[], [3, 5]));
34 
35     rbt.insert([1, 2, 4]);
36     assert(equal(rbt[], [1, 2, 3, 4, 5]));
37 
38     // Query bounds in O(log(n))
39     assert(rbt.lowerBound(3).equal([1, 2]));
40     assert(rbt.equalRange(3).equal([3]));
41     assert(rbt.upperBound(3).equal([4, 5]));
42 
43     // A Red Black tree with the highest element at front:
44     import std.range : iota;
45     auto maxTree = redBlackTree!"a > b"(iota(5));
46     assert(equal(maxTree[], [4, 3, 2, 1, 0]));
47 
48     // adding duplicates will not add them, but return 0
49     auto rbt2 = redBlackTree(1, 3);
50     assert(rbt2.insert(1) == 0);
51     assert(equal(rbt2[], [1, 3]));
52     assert(rbt2.insert(2) == 1);
53 
54     // however you can allow duplicates
55     auto ubt = redBlackTree!true([0, 1, 0, 1]);
56     assert(equal(ubt[], [0, 0, 1, 1]));
57 }
58 
59 import std.format;
60 import std.functional : binaryFun;
61 
62 public import std.container.util;
63 
64 version (StdUnittest) debug = RBDoChecks;
65 
66 //debug = RBDoChecks;
67 
68 /*
69  * Implementation for a Red Black node for use in a Red Black Tree (see below)
70  *
71  * this implementation assumes we have a marker Node that is the parent of the
72  * root Node.  This marker Node is not a valid Node, but marks the end of the
73  * collection.  The root is the left child of the marker Node, so it is always
74  * last in the collection.  The marker Node is passed in to the setColor
75  * function, and the Node which has this Node as its parent is assumed to be
76  * the root Node.
77  *
78  * A Red Black tree should have O(lg(n)) insertion, removal, and search time.
79  */
80 struct RBNode(V)
81 {
82     /*
83      * Convenience alias
84      */
85     alias Node = RBNode*;
86 
87     private Node _left;
88     private Node _right;
89     private Node _parent;
90 
91     /**
92      * The value held by this node
93      */
94     V value;
95 
96     /**
97      * Enumeration determining what color the node is.  Null nodes are assumed
98      * to be black.
99      */
100     enum Color : byte
101     {
102         Red,
103         Black
104     }
105 
106     /**
107      * The color of the node.
108      */
109     Color color;
110 
111     /**
112      * Get the left child
113      */
114     @property inout(RBNode)* left() inout return scope
115     {
116         return _left;
117     }
118 
119     /**
120      * Get the right child
121      */
122     @property inout(RBNode)* right() inout return scope
123     {
124         return _right;
125     }
126 
127     /**
128      * Get the parent
129      */
130     @property inout(RBNode)* parent() inout return scope
131     {
132         return _parent;
133     }
134 
135     /**
136      * Set the left child.  Also updates the new child's parent node.  This
137      * does not update the previous child.
138      *
139      * $(RED Warning: If the node this is called on is a local variable, a stack pointer can be
140      * escaped through `newNode.parent`. It's marked `@trusted` only for backwards compatibility.)
141      *
142      * Returns newNode
143      */
144     @property Node left(return scope Node newNode) @trusted
145     {
146         _left = newNode;
147         if (newNode !is null)
148             newNode._parent = &this;
149         return newNode;
150     }
151 
152     /**
153      * Set the right child.  Also updates the new child's parent node.  This
154      * does not update the previous child.
155      *
156      * $(RED Warning: If the node this is called on is a local variable, a stack pointer can be
157      * escaped through `newNode.parent`. It's marked `@trusted` only for backwards compatibility.)
158      *
159      * Returns newNode
160      */
161     @property Node right(return scope Node newNode) @trusted
162     {
163         _right = newNode;
164         if (newNode !is null)
165             newNode._parent = &this;
166         return newNode;
167     }
168 
169     // assume _left is not null
170     //
171     // performs rotate-right operation, where this is T, _right is R, _left is
172     // L, _parent is P:
173     //
174     //      P         P
175     //      |   ->    |
176     //      T         L
177     //     / \       / \
178     //    L   R     a   T
179     //   / \           / \
180     //  a   b         b   R
181     //
182     /**
183      * Rotate right.  This performs the following operations:
184      *  - The left child becomes the parent of this node.
185      *  - This node becomes the new parent's right child.
186      *  - The old right child of the new parent becomes the left child of this
187      *    node.
188      */
189     Node rotateR()
190     in
191     {
192         assert(_left !is null, "left node must not be null");
193     }
194     do
195     {
196         // sets _left._parent also
197         if (isLeftNode)
198             parent.left = _left;
199         else
200             parent.right = _left;
201         Node tmp = _left._right;
202 
203         // sets _parent also
204         _left.right = &this;
205 
206         // sets tmp._parent also
207         left = tmp;
208 
209         return &this;
210     }
211 
212     // assumes _right is non null
213     //
214     // performs rotate-left operation, where this is T, _right is R, _left is
215     // L, _parent is P:
216     //
217     //      P           P
218     //      |    ->     |
219     //      T           R
220     //     / \         / \
221     //    L   R       T   b
222     //       / \     / \
223     //      a   b   L   a
224     //
225     /**
226      * Rotate left.  This performs the following operations:
227      *  - The right child becomes the parent of this node.
228      *  - This node becomes the new parent's left child.
229      *  - The old left child of the new parent becomes the right child of this
230      *    node.
231      */
232     Node rotateL()
233     in
234     {
235         assert(_right !is null, "right node must not be null");
236     }
237     do
238     {
239         // sets _right._parent also
240         if (isLeftNode)
241             parent.left = _right;
242         else
243             parent.right = _right;
244         Node tmp = _right._left;
245 
246         // sets _parent also
247         _right.left = &this;
248 
249         // sets tmp._parent also
250         right = tmp;
251         return &this;
252     }
253 
254 
255     /**
256      * Returns true if this node is a left child.
257      *
258      * Note that this should always return a value because the root has a
259      * parent which is the marker node.
260      */
261     @property bool isLeftNode() const
262     in
263     {
264         assert(_parent !is null, "parent must not be null");
265     }
266     do
267     {
268         return _parent._left is &this;
269     }
270 
271     /**
272      * Set the color of the node after it is inserted.  This performs an
273      * update to the whole tree, possibly rotating nodes to keep the Red-Black
274      * properties correct.  This is an O(lg(n)) operation, where n is the
275      * number of nodes in the tree.
276      *
277      * end is the marker node, which is the parent of the topmost valid node.
278      */
279     void setColor(Node end)
280     {
281         // test against the marker node
282         if (_parent !is end)
283         {
284             if (_parent.color == Color.Red)
285             {
286                 Node cur = &this;
287                 while (true)
288                 {
289                     // because root is always black, _parent._parent always exists
290                     if (cur._parent.isLeftNode)
291                     {
292                         // parent is left node, y is 'uncle', could be null
293                         Node y = cur._parent._parent._right;
294                         if (y !is null && y.color == Color.Red)
295                         {
296                             cur._parent.color = Color.Black;
297                             y.color = Color.Black;
298                             cur = cur._parent._parent;
299                             if (cur._parent is end)
300                             {
301                                 // root node
302                                 cur.color = Color.Black;
303                                 break;
304                             }
305                             else
306                             {
307                                 // not root node
308                                 cur.color = Color.Red;
309                                 if (cur._parent.color == Color.Black)
310                                     // satisfied, exit the loop
311                                     break;
312                             }
313                         }
314                         else
315                         {
316                             if (!cur.isLeftNode)
317                                 cur = cur._parent.rotateL();
318                             cur._parent.color = Color.Black;
319                             cur = cur._parent._parent.rotateR();
320                             cur.color = Color.Red;
321                             // tree should be satisfied now
322                             break;
323                         }
324                     }
325                     else
326                     {
327                         // parent is right node, y is 'uncle'
328                         Node y = cur._parent._parent._left;
329                         if (y !is null && y.color == Color.Red)
330                         {
331                             cur._parent.color = Color.Black;
332                             y.color = Color.Black;
333                             cur = cur._parent._parent;
334                             if (cur._parent is end)
335                             {
336                                 // root node
337                                 cur.color = Color.Black;
338                                 break;
339                             }
340                             else
341                             {
342                                 // not root node
343                                 cur.color = Color.Red;
344                                 if (cur._parent.color == Color.Black)
345                                     // satisfied, exit the loop
346                                     break;
347                             }
348                         }
349                         else
350                         {
351                             if (cur.isLeftNode)
352                                 cur = cur._parent.rotateR();
353                             cur._parent.color = Color.Black;
354                             cur = cur._parent._parent.rotateL();
355                             cur.color = Color.Red;
356                             // tree should be satisfied now
357                             break;
358                         }
359                     }
360                 }
361 
362             }
363         }
364         else
365         {
366             //
367             // this is the root node, color it black
368             //
369             color = Color.Black;
370         }
371     }
372 
373     /**
374      * Remove this node from the tree.  The 'end' node is used as the marker
375      * which is root's parent.  Note that this cannot be null!
376      *
377      * Returns the next highest valued node in the tree after this one, or end
378      * if this was the highest-valued node.
379      */
380     Node remove(Node end) return
381     {
382         //
383         // remove this node from the tree, fixing the color if necessary.
384         //
385         Node x;
386         Node ret = next;
387 
388         // if this node has 2 children
389         if (_left !is null && _right !is null)
390         {
391             //
392             // normally, we can just swap this node's and y's value, but
393             // because an iterator could be pointing to y and we don't want to
394             // disturb it, we swap this node and y's structure instead.  This
395             // can also be a benefit if the value of the tree is a large
396             // struct, which takes a long time to copy.
397             //
398             Node yp, yl, yr;
399             Node y = ret; // y = next
400             yp = y._parent;
401             yl = y._left;
402             yr = y._right;
403             auto yc = y.color;
404             auto isyleft = y.isLeftNode;
405 
406             //
407             // replace y's structure with structure of this node.
408             //
409             if (isLeftNode)
410                 _parent.left = y;
411             else
412                 _parent.right = y;
413             //
414             // need special case so y doesn't point back to itself
415             //
416             y.left = _left;
417             if (_right is y)
418                 y.right = &this;
419             else
420                 y.right = _right;
421             y.color = color;
422 
423             //
424             // replace this node's structure with structure of y.
425             //
426             left = yl;
427             right = yr;
428             if (_parent !is y)
429             {
430                 if (isyleft)
431                     yp.left = &this;
432                 else
433                     yp.right = &this;
434             }
435             color = yc;
436         }
437 
438         // if this has less than 2 children, remove it
439         if (_left !is null)
440             x = _left;
441         else
442             x = _right;
443 
444         bool deferedUnlink = false;
445         if (x is null)
446         {
447             // pretend this is a null node, defer unlinking the node
448             x = &this;
449             deferedUnlink = true;
450         }
451         else if (isLeftNode)
452             _parent.left = x;
453         else
454             _parent.right = x;
455 
456         // if the color of this is black, then it needs to be fixed
457         if (color == color.Black)
458         {
459             // need to recolor the tree.
460             while (x._parent !is end && x.color == Node.Color.Black)
461             {
462                 if (x.isLeftNode)
463                 {
464                     // left node
465                     Node w = x._parent._right;
466                     if (w.color == Node.Color.Red)
467                     {
468                         w.color = Node.Color.Black;
469                         x._parent.color = Node.Color.Red;
470                         x._parent.rotateL();
471                         w = x._parent._right;
472                     }
473                     Node wl = w.left;
474                     Node wr = w.right;
475                     if ((wl is null || wl.color == Node.Color.Black) &&
476                             (wr is null || wr.color == Node.Color.Black))
477                     {
478                         w.color = Node.Color.Red;
479                         x = x._parent;
480                     }
481                     else
482                     {
483                         if (wr is null || wr.color == Node.Color.Black)
484                         {
485                             // wl cannot be null here
486                             wl.color = Node.Color.Black;
487                             w.color = Node.Color.Red;
488                             w.rotateR();
489                             w = x._parent._right;
490                         }
491 
492                         w.color = x._parent.color;
493                         x._parent.color = Node.Color.Black;
494                         w._right.color = Node.Color.Black;
495                         x._parent.rotateL();
496                         x = end.left; // x = root
497                     }
498                 }
499                 else
500                 {
501                     // right node
502                     Node w = x._parent._left;
503                     if (w.color == Node.Color.Red)
504                     {
505                         w.color = Node.Color.Black;
506                         x._parent.color = Node.Color.Red;
507                         x._parent.rotateR();
508                         w = x._parent._left;
509                     }
510                     Node wl = w.left;
511                     Node wr = w.right;
512                     if ((wl is null || wl.color == Node.Color.Black) &&
513                             (wr is null || wr.color == Node.Color.Black))
514                     {
515                         w.color = Node.Color.Red;
516                         x = x._parent;
517                     }
518                     else
519                     {
520                         if (wl is null || wl.color == Node.Color.Black)
521                         {
522                             // wr cannot be null here
523                             wr.color = Node.Color.Black;
524                             w.color = Node.Color.Red;
525                             w.rotateL();
526                             w = x._parent._left;
527                         }
528 
529                         w.color = x._parent.color;
530                         x._parent.color = Node.Color.Black;
531                         w._left.color = Node.Color.Black;
532                         x._parent.rotateR();
533                         x = end.left; // x = root
534                     }
535                 }
536             }
537             x.color = Node.Color.Black;
538         }
539 
540         if (deferedUnlink)
541         {
542             //
543             // unlink this node from the tree
544             //
545             if (isLeftNode)
546                 _parent.left = null;
547             else
548                 _parent.right = null;
549         }
550 
551         // clean references to help GC
552         // https://issues.dlang.org/show_bug.cgi?id=12915
553         _left = _right = _parent = null;
554 
555         return ret;
556     }
557 
558     /**
559      * Return the leftmost descendant of this node.
560      */
561     @property inout(RBNode)* leftmost() inout return
562     {
563         inout(RBNode)* result = &this;
564         while (result._left !is null)
565             result = result._left;
566         return result;
567     }
568 
569     /**
570      * Return the rightmost descendant of this node
571      */
572     @property inout(RBNode)* rightmost() inout return
573     {
574         inout(RBNode)* result = &this;
575         while (result._right !is null)
576             result = result._right;
577         return result;
578     }
579 
580     /**
581      * Returns the next valued node in the tree.
582      *
583      * You should never call this on the marker node, as it is assumed that
584      * there is a valid next node.
585      */
586     @property inout(RBNode)* next() inout return
587     {
588         inout(RBNode)* n = &this;
589         if (n.right is null)
590         {
591             while (!n.isLeftNode)
592                 n = n._parent;
593             return n._parent;
594         }
595         else
596             return n.right.leftmost;
597     }
598 
599     /**
600      * Returns the previous valued node in the tree.
601      *
602      * You should never call this on the leftmost node of the tree as it is
603      * assumed that there is a valid previous node.
604      */
605     @property inout(RBNode)* prev() inout return
606     {
607         inout(RBNode)* n = &this;
608         if (n.left is null)
609         {
610             while (n.isLeftNode)
611                 n = n._parent;
612             return n._parent;
613         }
614         else
615             return n.left.rightmost;
616     }
617 
618     Node dup(scope Node delegate(V v) alloc)
619     {
620         //
621         // duplicate this and all child nodes
622         //
623         // The recursion should be lg(n), so we shouldn't have to worry about
624         // stack size.
625         //
626         Node copy = alloc(value);
627         copy.color = color;
628         if (_left !is null)
629             copy.left = _left.dup(alloc);
630         if (_right !is null)
631             copy.right = _right.dup(alloc);
632         return copy;
633     }
634 
635     Node dup()
636     {
637         Node copy = new RBNode!V(null, null, null, value);
638         copy.color = color;
639         if (_left !is null)
640             copy.left = _left.dup();
641         if (_right !is null)
642             copy.right = _right.dup();
643         return copy;
644     }
645 }
646 
647 //constness checks
648 @safe pure unittest
649 {
650     const RBNode!int n;
651     static assert(is(typeof(n.leftmost)));
652     static assert(is(typeof(n.rightmost)));
653     static assert(is(typeof(n.next)));
654     static assert(is(typeof(n.prev)));
655 }
656 
657 private struct RBRange(N)
658 {
659     alias Node = N;
660     alias Elem = typeof(Node.value);
661 
662     private Node _begin;
663     private Node _end;
664 
665     private this(Node b, Node e)
666     {
667         _begin = b;
668         _end = e;
669     }
670 
671     /**
672      * Returns `true` if the range is _empty
673      */
674     @property bool empty() const
675     {
676         return _begin is _end;
677     }
678 
679     /**
680      * Returns the first element in the range
681      */
682     ref @property Elem front()
683     {
684         return _begin.value;
685     }
686 
687     /**
688      * Returns the last element in the range
689      */
690     ref @property Elem back()
691     {
692         return _end.prev.value;
693     }
694 
695     /**
696      * pop the front element from the range
697      *
698      * Complexity: amortized $(BIGOH 1)
699      */
700     void popFront()
701     {
702         _begin = _begin.next;
703     }
704 
705     /**
706      * pop the back element from the range
707      *
708      * Complexity: amortized $(BIGOH 1)
709      */
710     void popBack()
711     {
712         _end = _end.prev;
713     }
714 
715     /**
716      * Trivial _save implementation, needed for `isForwardRange`.
717      */
718     @property RBRange save()
719     {
720         return this;
721     }
722 }
723 
724 /**
725  * Implementation of a $(LINK2 https://en.wikipedia.org/wiki/Red%E2%80%93black_tree,
726  * red-black tree) container.
727  *
728  * All inserts, removes, searches, and any function in general has complexity
729  * of $(BIGOH lg(n)).
730  *
731  * To use a different comparison than $(D "a < b"), pass a different operator string
732  * that can be used by $(REF binaryFun, std,functional), or pass in a
733  * function, delegate, functor, or any type where $(D less(a, b)) results in a `bool`
734  * value.
735  *
736  * Note that less should produce a strict ordering.  That is, for two unequal
737  * elements `a` and `b`, $(D less(a, b) == !less(b, a)). $(D less(a, a)) should
738  * always equal `false`.
739  *
740  * Care should also be taken to not modify elements in the tree (e.g. via `front` /
741  * `back`, which return by `ref`) in a way which would affect the order defined by
742  * the `less` predicate.
743  *
744  * If `allowDuplicates` is set to `true`, then inserting the same element more than
745  * once continues to add more elements.  If it is `false`, duplicate elements are
746  * ignored on insertion.  If duplicates are allowed, then new elements are
747  * inserted after all existing duplicate elements.
748  */
749 final class RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
750 if (is(typeof(binaryFun!less(T.init, T.init))))
751 {
752     import std.meta : allSatisfy;
753     import std.range : Take;
754     import std.range.primitives : isInputRange, walkLength;
755     import std.traits : isIntegral, isDynamicArray, isImplicitlyConvertible;
756 
757     alias _less = binaryFun!less;
758 
759     version (StdUnittest)
760     {
761         static if (is(typeof(less) == string))
762         {
763             private enum doUnittest = is(byte : T) && isIntegral!T && (less == "a < b" || less == "a > b");
764         }
765         else
766             enum doUnittest = false;
767 
768         // note, this must be final so it does not affect the vtable layout
769         bool arrayEqual(T[] arr)
770         {
771             if (walkLength(this[]) == arr.length)
772             {
773                 foreach (v; arr)
774                 {
775                     if (!(v in this))
776                         return false;
777                 }
778                 return true;
779             }
780             return false;
781         }
782     }
783     else
784     {
785         private enum doUnittest = false;
786     }
787 
788     /**
789       * Element type for the tree
790       */
791     alias Elem = T;
792 
793     // used for convenience
794     private alias RBNode = .RBNode!Elem;
795     private alias Node = RBNode.Node;
796 
797     private Node   _end;
798     private Node   _begin;
799     private size_t _length;
800 
801     private void _setup()
802     {
803         //Make sure that _setup isn't run more than once.
804         assert(!_end, "Setup must only be run once");
805         _begin = _end = allocate();
806     }
807 
808     static private Node allocate()
809     {
810         return new RBNode;
811     }
812 
813     static private Node allocate(Elem v)
814     {
815         return new RBNode(null, null, null, v);
816     }
817 
818     /**
819      * The range types for `RedBlackTree`
820      */
821     alias Range = RBRange!(RBNode*);
822     alias ConstRange = RBRange!(const(RBNode)*); /// Ditto
823     alias ImmutableRange = RBRange!(immutable(RBNode)*); /// Ditto
824 
825     static if (doUnittest) @safe pure unittest
826     {
827         import std.algorithm.comparison : equal;
828         import std.range.primitives;
829         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
830         assert(ts.length == 5);
831         auto r = ts[];
832 
833         static if (less == "a < b")
834             auto vals = [1, 2, 3, 4, 5];
835         else
836             auto vals = [5, 4, 3, 2, 1];
837         assert(equal(r, vals));
838 
839         assert(r.front == vals.front);
840         assert(r.back != r.front);
841         auto oldfront = r.front;
842         auto oldback = r.back;
843         r.popFront();
844         r.popBack();
845         assert(r.front != r.back);
846         assert(r.front != oldfront);
847         assert(r.back != oldback);
848         assert(ts.length == 5);
849     }
850 
851     // find a node based on an element value
852     private inout(RBNode)* _find(Elem e) inout
853     {
854         static if (allowDuplicates)
855         {
856             inout(RBNode)* cur = _end.left;
857             inout(RBNode)* result = null;
858             while (cur)
859             {
860                 if (_less(cur.value, e))
861                     cur = cur.right;
862                 else if (_less(e, cur.value))
863                     cur = cur.left;
864                 else
865                 {
866                     // want to find the left-most element
867                     result = cur;
868                     cur = cur.left;
869                 }
870             }
871             return result;
872         }
873         else
874         {
875             inout(RBNode)* cur = _end.left;
876             while (cur)
877             {
878                 if (_less(cur.value, e))
879                     cur = cur.right;
880                 else if (_less(e, cur.value))
881                     cur = cur.left;
882                 else
883                     return cur;
884             }
885             return null;
886         }
887     }
888 
889     /* add an element to the tree, returns the node added, or the existing node
890      * if it has already been added and allowDuplicates is false
891      * Returns:
892      *   true if node was added
893      */
894     private bool _add(return scope Elem n)
895     {
896         Node result;
897         static if (!allowDuplicates)
898             bool added = true;
899 
900         if (!_end.left)
901         {
902             result = allocate(n);
903             (() @trusted { _end.left = _begin = result; }) ();
904         }
905         else
906         {
907             Node newParent = _end.left;
908             Node nxt;
909             while (true)
910             {
911                 if (_less(n, newParent.value))
912                 {
913                     nxt = newParent.left;
914                     if (nxt is null)
915                     {
916                         //
917                         // add to right of new parent
918                         //
919                         result = allocate(n);
920                         (() @trusted { newParent.left = result; }) ();
921                         break;
922                     }
923                 }
924                 else
925                 {
926                     static if (!allowDuplicates)
927                     {
928                         if (!_less(newParent.value, n))
929                         {
930                             result = newParent;
931                             added = false;
932                             break;
933                         }
934                     }
935                     nxt = newParent.right;
936                     if (nxt is null)
937                     {
938                         //
939                         // add to right of new parent
940                         //
941                         result = allocate(n);
942                         (() @trusted { newParent.right = result; }) ();
943                         break;
944                     }
945                 }
946                 newParent = nxt;
947             }
948             if (_begin.left)
949                 _begin = _begin.left;
950         }
951         static if (allowDuplicates)
952         {
953             result.setColor(_end);
954             debug(RBDoChecks)
955                 check();
956             ++_length;
957             return true;
958         }
959         else
960         {
961             if (added)
962             {
963                 ++_length;
964                 result.setColor(_end);
965             }
966             debug(RBDoChecks)
967                 check();
968             return added;
969         }
970     }
971 
972 
973     /**
974      * Check if any elements exist in the container.  Returns `false` if at least
975      * one element exists.
976      */
977     @property bool empty() const // pure, nothrow, @safe, @nogc: are inferred
978     {
979         return _end.left is null;
980     }
981 
982     /++
983         Returns the number of elements in the container.
984 
985         Complexity: $(BIGOH 1).
986     +/
987     @property size_t length() const
988     {
989         return _length;
990     }
991 
992     /**
993      * Duplicate this container.  The resulting container contains a shallow
994      * copy of the elements.
995      *
996      * Complexity: $(BIGOH n)
997      */
998     @property RedBlackTree dup()
999     {
1000         return new RedBlackTree(_end.dup(), _length);
1001     }
1002 
1003     static if (doUnittest) @safe pure unittest
1004     {
1005         import std.algorithm.comparison : equal;
1006         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1007         assert(ts.length == 5);
1008         auto ts2 = ts.dup;
1009         assert(ts2.length == 5);
1010         assert(equal(ts[], ts2[]));
1011         ts2.insert(cast(Elem) 6);
1012         assert(!equal(ts[], ts2[]));
1013         assert(ts.length == 5 && ts2.length == 6);
1014     }
1015 
1016     /**
1017      * Fetch a range that spans all the elements in the container.
1018      *
1019      * Complexity: $(BIGOH 1)
1020      */
1021     Range opSlice()
1022     {
1023         return Range(_begin, _end);
1024     }
1025 
1026     /// Ditto
1027     ConstRange opSlice() const
1028     {
1029         return ConstRange(_begin, _end);
1030     }
1031 
1032     /// Ditto
1033     ImmutableRange opSlice() immutable
1034     {
1035         return ImmutableRange(_begin, _end);
1036     }
1037 
1038     /**
1039      * The front element in the container
1040      *
1041      * Complexity: $(BIGOH 1)
1042      */
1043     ref inout(Elem) front() inout
1044     {
1045         return _begin.value;
1046     }
1047 
1048     /**
1049      * The last element in the container
1050      *
1051      * Complexity: $(BIGOH log(n))
1052      */
1053     ref inout(Elem) back() inout
1054     {
1055         return _end.prev.value;
1056     }
1057 
1058     /++
1059         `in` operator. Check to see if the given element exists in the
1060         container.
1061 
1062        Complexity: $(BIGOH log(n))
1063      +/
1064     bool opBinaryRight(string op)(Elem e) const
1065     if (op == "in")
1066     {
1067         return _find(e) !is null;
1068     }
1069 
1070     static if (doUnittest) @safe pure unittest
1071     {
1072         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1073         assert(cast(Elem) 3 in ts);
1074         assert(cast(Elem) 6 !in ts);
1075     }
1076 
1077     /**
1078      * Compares two trees for equality.
1079      *
1080      * Complexity: $(BIGOH n)
1081      */
1082     override bool opEquals(Object rhs)
1083     {
1084         import std.algorithm.comparison : equal;
1085 
1086         RedBlackTree that = cast(RedBlackTree) rhs;
1087         if (that is null) return false;
1088 
1089         // If there aren't the same number of nodes, we can't be equal.
1090         if (this._length != that._length) return false;
1091 
1092         auto thisRange = this[];
1093         auto thatRange = that[];
1094         return equal!((Elem a, Elem b) => !_less(a,b) && !_less(b,a))
1095                      (thisRange, thatRange);
1096     }
1097 
1098     static if (doUnittest) @system unittest
1099     {
1100         auto t1 = new RedBlackTree(1,2,3,4);
1101         auto t2 = new RedBlackTree(1,2,3,4);
1102         auto t3 = new RedBlackTree(1,2,3,5);
1103         auto t4 = new RedBlackTree(1,2,3,4,5);
1104         auto o = new Object();
1105 
1106         assert(t1 == t1);
1107         assert(t1 == t2);
1108         assert(t1 != t3);
1109         assert(t1 != t4);
1110         assert(t1 != o);  // pathological case, must not crash
1111     }
1112 
1113     /**
1114      * Generates a hash for the tree. Note that with a custom comparison function
1115      * it may not hold that if two rbtrees are equal, the hashes of the trees
1116      * will be equal.
1117      */
1118     override size_t toHash() nothrow @safe
1119     {
1120         size_t hash = cast(size_t) 0x6b63_616c_4264_6552UL;
1121         foreach (ref e; this[])
1122             // As in boost::hash_combine
1123             // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
1124             hash += .hashOf(e) + 0x9e3779b9 + (hash << 6) + (hash >>> 2);
1125         return hash;
1126     }
1127 
1128     static if (doUnittest) @system unittest
1129     {
1130         auto t1 = new RedBlackTree(1,2,3,4);
1131         auto t2 = new RedBlackTree(1,2,3,4);
1132         auto t3 = new RedBlackTree(1,2,3,5);
1133         auto t4 = new RedBlackTree(1,2,3,4,5);
1134 
1135         assert(t1.toHash() == t2.toHash);
1136 
1137         assert(t1.toHash() != t3.toHash);
1138         assert(t2.toHash() != t3.toHash);
1139 
1140         assert(t3.toHash() != t4.toHash);
1141         assert(t1.toHash() != t4.toHash);
1142 
1143         // empty tree
1144         auto t5 = new RedBlackTree();
1145         auto t6 = new RedBlackTree();
1146 
1147         assert(t5.toHash() == t6.toHash());
1148 
1149         auto t7 = new RedBlackTree!string("red", "black");
1150         auto t8 = new RedBlackTree!string("white", "black");
1151         auto t9 = new RedBlackTree!string("red", "black");
1152 
1153         assert(t7.toHash() == t9.toHash());
1154         assert(t7.toHash() != t8.toHash());
1155 
1156         static struct MyInt
1157         {
1158             int x;
1159 
1160           @safe:
1161 
1162             this(int init_x)
1163             {
1164                 x = init_x;
1165             }
1166 
1167             size_t toHash() const nothrow
1168             {
1169                 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0;
1170             }
1171 
1172             int opCmp(const MyInt that) const
1173             {
1174                 return (x > that.x) - (x < that.x);
1175             }
1176 
1177             bool opEquals(const MyInt that) const
1178             {
1179                 return (this.x == that.x);
1180             }
1181         }
1182 
1183         auto rbt1 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4));
1184         auto rbt2 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4));
1185 
1186         assert(rbt1.toHash() == rbt2.toHash());
1187         assert(rbt1.toHash() != t1.toHash());
1188 
1189         auto rbt3 = new RedBlackTree!MyInt(MyInt(4), MyInt(2), MyInt(3), MyInt(4));
1190 
1191         assert(rbt1.toHash() != rbt3.toHash());
1192 
1193         class MyInt2
1194         {
1195             int x;
1196 
1197             this(int init_x)
1198             {
1199                 x = init_x;
1200             }
1201 
1202             override size_t toHash() const @safe nothrow
1203             {
1204                 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0;
1205             }
1206 
1207             int opCmp(const MyInt2 that) const
1208             {
1209                 return (x > that.x) - (x < that.x);
1210             }
1211 
1212             bool opEquals(const MyInt2 that) const
1213             {
1214                 return (this.x == that.x);
1215             }
1216         }
1217 
1218         static bool nullSafeLess(scope const MyInt2 a, scope const MyInt2 b)
1219         {
1220             return a is null ? b !is null : (b !is null && a < b);
1221         }
1222 
1223         auto rbt4 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42));
1224         auto rbt5 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42));
1225         auto rbt6 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(9), new MyInt2(3), new MyInt2(42));
1226         auto rbt7 = new RedBlackTree!(MyInt2, nullSafeLess)(null);
1227 
1228         assert(rbt6.toHash() != rbt5.toHash());
1229         assert(rbt6.toHash() != rbt4.toHash());
1230         assert(rbt6.toHash() != rbt7.toHash());
1231         assert(rbt4.toHash() == rbt5.toHash());
1232 
1233         auto rbt8 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42));
1234         auto rbt9 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42));
1235         auto rbt10 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(94), null, new MyInt2(147));
1236 
1237         assert(rbt8.toHash() == rbt9.toHash());
1238         assert(rbt8.toHash() != rbt10.toHash());
1239     }
1240 
1241     /**
1242      * Removes all elements from the container.
1243      *
1244      * Complexity: $(BIGOH 1)
1245      */
1246     void clear()
1247     {
1248         _end.left = null;
1249         _begin = _end;
1250         _length = 0;
1251     }
1252 
1253     static if (doUnittest) @safe pure unittest
1254     {
1255         auto ts = new RedBlackTree(1,2,3,4,5);
1256         assert(ts.length == 5);
1257         ts.clear();
1258         assert(ts.empty && ts.length == 0);
1259     }
1260 
1261     /**
1262      * Insert a single element in the container.  Note that this does not
1263      * invalidate any ranges currently iterating the container.
1264      *
1265      * Returns: The number of elements inserted.
1266      *
1267      * Complexity: $(BIGOH log(n))
1268      */
1269     size_t stableInsert(Stuff)(Stuff stuff)
1270     if (isImplicitlyConvertible!(Stuff, Elem))
1271     {
1272         static if (allowDuplicates)
1273         {
1274             _add(stuff);
1275             return 1;
1276         }
1277         else
1278         {
1279             return _add(stuff);
1280         }
1281     }
1282 
1283     /**
1284      * Insert a range of elements in the container.  Note that this does not
1285      * invalidate any ranges currently iterating the container.
1286      *
1287      * Returns: The number of elements inserted.
1288      *
1289      * Complexity: $(BIGOH m * log(n))
1290      */
1291     size_t stableInsert(Stuff)(scope Stuff stuff)
1292     if (isInputRange!Stuff &&
1293         isImplicitlyConvertible!(ElementType!Stuff, Elem))
1294     {
1295         size_t result = 0;
1296         static if (allowDuplicates)
1297         {
1298             foreach (e; stuff)
1299             {
1300                 ++result;
1301                 _add(e);
1302             }
1303         }
1304         else
1305         {
1306             foreach (e; stuff)
1307             {
1308                 result += _add(e);
1309             }
1310         }
1311         return result;
1312     }
1313 
1314     /// ditto
1315     alias insert = stableInsert;
1316 
1317     static if (doUnittest) @safe pure unittest
1318     {
1319         auto ts = new RedBlackTree(2,1,3,4,5,2,5);
1320         static if (allowDuplicates)
1321         {
1322             assert(ts.length == 7);
1323             assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 6);
1324             assert(ts.length == 13);
1325             assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 14);
1326             assert(ts.stableInsert(cast(Elem) 7) == 1 && ts.length == 15);
1327 
1328             static if (less == "a < b")
1329                 assert(ts.arrayEqual([1,2,2,3,4,5,5,6,7,7,8,8,9,10,11]));
1330             else
1331                 assert(ts.arrayEqual([11,10,9,8,8,7,7,6,5,5,4,3,2,2,1]));
1332         }
1333         else
1334         {
1335             assert(ts.length == 5);
1336             Elem[] elems = [7, 8, 6, 9, 10, 8];
1337             assert(ts.stableInsert(elems) == 5);
1338             assert(ts.length == 10);
1339             assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 11);
1340             assert(ts.stableInsert(cast(Elem) 7) == 0 && ts.length == 11);
1341 
1342             static if (less == "a < b")
1343                 assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11]));
1344             else
1345                 assert(ts.arrayEqual([11,10,9,8,7,6,5,4,3,2,1]));
1346         }
1347     }
1348 
1349     /**
1350      * Remove an element from the container and return its value.
1351      *
1352      * Complexity: $(BIGOH log(n))
1353      */
1354     Elem removeAny()
1355     {
1356         scope(success)
1357             --_length;
1358         auto n = _begin;
1359         auto result = n.value;
1360         _begin = n.remove(_end);
1361         debug(RBDoChecks)
1362             check();
1363         return result;
1364     }
1365 
1366     static if (doUnittest) @safe pure unittest
1367     {
1368         auto ts = new RedBlackTree(1,2,3,4,5);
1369         assert(ts.length == 5);
1370         auto x = ts.removeAny();
1371         assert(ts.length == 4);
1372         Elem[] arr;
1373         foreach (Elem i; 1 .. 6)
1374             if (i != x) arr ~= i;
1375         assert(ts.arrayEqual(arr));
1376     }
1377 
1378     /**
1379      * Remove the front element from the container.
1380      *
1381      * Complexity: $(BIGOH log(n))
1382      */
1383     void removeFront()
1384     {
1385         scope(success)
1386             --_length;
1387         _begin = _begin.remove(_end);
1388         debug(RBDoChecks)
1389             check();
1390     }
1391 
1392     /**
1393      * Remove the back element from the container.
1394      *
1395      * Complexity: $(BIGOH log(n))
1396      */
1397     void removeBack()
1398     {
1399         scope(success)
1400             --_length;
1401         auto lastnode = _end.prev;
1402         if (lastnode is _begin)
1403             _begin = _begin.remove(_end);
1404         else
1405             lastnode.remove(_end);
1406         debug(RBDoChecks)
1407             check();
1408     }
1409 
1410     static if (doUnittest) @safe pure unittest
1411     {
1412         auto ts = new RedBlackTree(1,2,3,4,5);
1413         assert(ts.length == 5);
1414         ts.removeBack();
1415         assert(ts.length == 4);
1416 
1417         static if (less == "a < b")
1418             assert(ts.arrayEqual([1,2,3,4]));
1419         else
1420             assert(ts.arrayEqual([2,3,4,5]));
1421 
1422         ts.removeFront();
1423         assert(ts.arrayEqual([2,3,4]) && ts.length == 3);
1424     }
1425 
1426     /++
1427         Removes the given range from the container.
1428 
1429         Returns: A range containing all of the elements that were after the
1430                  given range.
1431 
1432         Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
1433                     the range)
1434      +/
1435     Range remove(Range r)
1436     {
1437         auto b = r._begin;
1438         auto e = r._end;
1439         if (_begin is b)
1440             _begin = e;
1441         while (b !is e)
1442         {
1443             b = b.remove(_end);
1444             --_length;
1445         }
1446         debug(RBDoChecks)
1447             check();
1448         return Range(e, _end);
1449     }
1450 
1451     static if (doUnittest) @safe pure unittest
1452     {
1453         import std.algorithm.comparison : equal;
1454         auto ts = new RedBlackTree(1,2,3,4,5);
1455         assert(ts.length == 5);
1456         auto r = ts[];
1457         r.popFront();
1458         r.popBack();
1459         assert(ts.length == 5);
1460         auto r2 = ts.remove(r);
1461         assert(ts.length == 2);
1462         assert(ts.arrayEqual([1,5]));
1463 
1464         static if (less == "a < b")
1465             assert(equal(r2, [5]));
1466         else
1467             assert(equal(r2, [1]));
1468     }
1469 
1470     /++
1471         Removes the given `Take!Range` from the container
1472 
1473         Returns: A range containing all of the elements that were after the
1474                  given range.
1475 
1476         Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
1477                     the range)
1478      +/
1479     Range remove(Take!Range r)
1480     {
1481         immutable isBegin = (r.source._begin is _begin);
1482         auto b = r.source._begin;
1483 
1484         while (!r.empty)
1485         {
1486             r.popFront();
1487             b = b.remove(_end);
1488             --_length;
1489         }
1490 
1491         if (isBegin)
1492             _begin = b;
1493 
1494         return Range(b, _end);
1495     }
1496 
1497     static if (doUnittest) @safe pure unittest
1498     {
1499         import std.algorithm.comparison : equal;
1500         import std.range : take;
1501         auto ts = new RedBlackTree(1,2,3,4,5);
1502         auto r = ts[];
1503         r.popFront();
1504         assert(ts.length == 5);
1505         auto r2 = ts.remove(take(r, 0));
1506 
1507         static if (less == "a < b")
1508         {
1509             assert(equal(r2, [2,3,4,5]));
1510             auto r3 = ts.remove(take(r, 2));
1511             assert(ts.arrayEqual([1,4,5]) && ts.length == 3);
1512             assert(equal(r3, [4,5]));
1513         }
1514         else
1515         {
1516             assert(equal(r2, [4,3,2,1]));
1517             auto r3 = ts.remove(take(r, 2));
1518             assert(ts.arrayEqual([5,2,1]) && ts.length == 3);
1519             assert(equal(r3, [2,1]));
1520         }
1521     }
1522 
1523     /++
1524        Removes elements from the container that are equal to the given values
1525        according to the less comparator. One element is removed for each value
1526        given which is in the container. If `allowDuplicates` is true,
1527        duplicates are removed only if duplicate values are given.
1528 
1529        Returns: The number of elements removed.
1530 
1531        Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove)
1532 
1533        Example:
1534 --------------------
1535 auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
1536 rbt.removeKey(1, 4, 7);
1537 assert(equal(rbt[], [0, 1, 1, 5]));
1538 rbt.removeKey(1, 1, 0);
1539 assert(equal(rbt[], [5]));
1540 --------------------
1541       +/
1542     size_t removeKey(U...)(U elems)
1543     if (allSatisfy!(isImplicitlyConvertibleToElem, U))
1544     {
1545         Elem[U.length] toRemove = [elems];
1546         return removeKey(toRemove[]);
1547     }
1548 
1549     /++ Ditto +/
1550     size_t removeKey(U)(scope U[] elems)
1551     if (isImplicitlyConvertible!(U, Elem))
1552     {
1553         immutable lenBefore = length;
1554 
1555         foreach (e; elems)
1556         {
1557             auto beg = _firstGreaterEqual(e);
1558             if (beg is _end || _less(e, beg.value))
1559                 // no values are equal
1560                 continue;
1561             immutable isBegin = (beg is _begin);
1562             beg = beg.remove(_end);
1563             if (isBegin)
1564                 _begin = beg;
1565             --_length;
1566         }
1567 
1568         return lenBefore - length;
1569     }
1570 
1571     /++ Ditto +/
1572     size_t removeKey(Stuff)(Stuff stuff)
1573     if (isInputRange!Stuff &&
1574         isImplicitlyConvertible!(ElementType!Stuff, Elem) &&
1575         !isDynamicArray!Stuff)
1576     {
1577         import std.array : array;
1578         //We use array in case stuff is a Range from this RedBlackTree - either
1579         //directly or indirectly.
1580         return removeKey(array(stuff));
1581     }
1582 
1583     //Helper for removeKey.
1584     private template isImplicitlyConvertibleToElem(U)
1585     {
1586         enum isImplicitlyConvertibleToElem = isImplicitlyConvertible!(U, Elem);
1587     }
1588 
1589     static if (doUnittest) @safe pure unittest
1590     {
1591         import std.algorithm.comparison : equal;
1592         import std.range : take;
1593         auto rbt = new RedBlackTree(5, 4, 3, 7, 2, 1, 7, 6, 2, 19, 45);
1594 
1595         //The cast(Elem) is because these tests are instantiated with a variety
1596         //of numeric types, and the literals are all int, which is not always
1597         //implicitly convertible to Elem (e.g. short).
1598         static if (allowDuplicates)
1599         {
1600             assert(rbt.length == 11);
1601             assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 10);
1602             assert(rbt.arrayEqual([1,2,2,3,5,6,7,7,19,45]) && rbt.length == 10);
1603 
1604             assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3);
1605             assert(rbt.arrayEqual([2,3,5,7,7,19,45]) && rbt.length == 7);
1606 
1607             assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 7);
1608             assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 4);
1609 
1610             static if (less == "a < b")
1611                 assert(equal(rbt[], [7,7,19,45]));
1612             else
1613                 assert(equal(rbt[], [7,5,3,2]));
1614         }
1615         else
1616         {
1617             assert(rbt.length == 9);
1618             assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 8);
1619             assert(rbt.arrayEqual([1,2,3,5,6,7,19,45]));
1620 
1621             assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3);
1622             assert(rbt.arrayEqual([3,5,7,19,45]) && rbt.length == 5);
1623 
1624             assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 5);
1625             assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 2);
1626 
1627             static if (less == "a < b")
1628                 assert(equal(rbt[], [19,45]));
1629             else
1630                 assert(equal(rbt[], [5,3]));
1631         }
1632     }
1633 
1634     // find the first node where the value is > e
1635     private inout(RBNode)* _firstGreater(Elem e) inout
1636     {
1637         // can't use _find, because we cannot return null
1638         auto cur = _end.left;
1639         inout(RBNode)* result = _end;
1640         while (cur)
1641         {
1642             if (_less(e, cur.value))
1643             {
1644                 result = cur;
1645                 cur = cur.left;
1646             }
1647             else
1648                 cur = cur.right;
1649         }
1650         return result;
1651     }
1652 
1653     // find the first node where the value is >= e
1654     private inout(RBNode)* _firstGreaterEqual(Elem e) inout
1655     {
1656         // can't use _find, because we cannot return null.
1657         auto cur = _end.left;
1658         inout(RBNode)* result = _end;
1659         while (cur)
1660         {
1661             if (_less(cur.value, e))
1662                 cur = cur.right;
1663             else
1664             {
1665                 result = cur;
1666                 cur = cur.left;
1667             }
1668 
1669         }
1670         return result;
1671     }
1672 
1673     /**
1674      * Get a range from the container with all elements that are > e according
1675      * to the less comparator
1676      *
1677      * Complexity: $(BIGOH log(n))
1678      */
1679     Range upperBound(Elem e)
1680     {
1681         return Range(_firstGreater(e), _end);
1682     }
1683 
1684     /// Ditto
1685     ConstRange upperBound(Elem e) const
1686     {
1687         return ConstRange(_firstGreater(e), _end);
1688     }
1689 
1690     /// Ditto
1691     ImmutableRange upperBound(Elem e) immutable
1692     {
1693         return ImmutableRange(_firstGreater(e), _end);
1694     }
1695 
1696     /**
1697      * Get a range from the container with all elements that are < e according
1698      * to the less comparator
1699      *
1700      * Complexity: $(BIGOH log(n))
1701      */
1702     Range lowerBound(Elem e)
1703     {
1704         return Range(_begin, _firstGreaterEqual(e));
1705     }
1706 
1707     /// Ditto
1708     ConstRange lowerBound(Elem e) const
1709     {
1710         return ConstRange(_begin, _firstGreaterEqual(e));
1711     }
1712 
1713     /// Ditto
1714     ImmutableRange lowerBound(Elem e) immutable
1715     {
1716         return ImmutableRange(_begin, _firstGreaterEqual(e));
1717     }
1718 
1719     /**
1720      * Get a range from the container with all elements that are == e according
1721      * to the less comparator
1722      *
1723      * Complexity: $(BIGOH log(n))
1724      */
1725     auto equalRange(this This)(Elem e)
1726     {
1727         auto beg = _firstGreaterEqual(e);
1728         alias RangeType = RBRange!(typeof(beg));
1729         if (beg is _end || _less(e, beg.value))
1730             // no values are equal
1731             return RangeType(beg, beg);
1732         static if (allowDuplicates)
1733         {
1734             return RangeType(beg, _firstGreater(e));
1735         }
1736         else
1737         {
1738             // no sense in doing a full search, no duplicates are allowed,
1739             // so we just get the next node.
1740             return RangeType(beg, beg.next);
1741         }
1742     }
1743 
1744     /**
1745      * Returns a static array of 3 ranges `r` such that `r[0]` is the
1746      * same as the result of `lowerBound(value)`, `r[1]` is the same
1747      * as the result of $(D equalRange(value)), and `r[2]` is the same
1748      * as the result of $(D upperBound(value)).
1749      *
1750      * Complexity: $(BIGOH log(n))
1751      */
1752     auto trisect(this This)(Elem e)
1753     {
1754         auto equalRange = this.equalRange(e);
1755         alias RangeType = typeof(equalRange);
1756         RangeType[3] result = [
1757             RangeType(_begin, equalRange._begin),
1758             equalRange,
1759             RangeType(equalRange._end, _end)
1760         ];
1761         return result;
1762     }
1763 
1764     static if (doUnittest) @safe pure unittest
1765     {
1766         import std.algorithm.comparison : equal;
1767         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1768         auto rl = ts.lowerBound(3);
1769         auto ru = ts.upperBound(3);
1770         auto re = ts.equalRange(3);
1771 
1772         static if (less == "a < b")
1773         {
1774             assert(equal(rl, [1,2]));
1775             assert(equal(ru, [4,5]));
1776         }
1777         else
1778         {
1779             assert(equal(rl, [5,4]));
1780             assert(equal(ru, [2,1]));
1781         }
1782 
1783         assert(equal(re, [3]));
1784     }
1785 
1786     debug(RBDoChecks)
1787     {
1788         /*
1789          * Print the tree.  This prints a sideways view of the tree in ASCII form,
1790          * with the number of indentations representing the level of the nodes.
1791          * It does not print values, only the tree structure and color of nodes.
1792          */
1793         void printTree(Node n, int indent = 0)
1794         {
1795             import std.stdio : write, writeln;
1796             if (n !is null)
1797             {
1798                 printTree(n.right, indent + 2);
1799                 for (int i = 0; i < indent; i++)
1800                     write(".");
1801                 writeln(n.color == n.color.Black ? "B" : "R");
1802                 printTree(n.left, indent + 2);
1803             }
1804             else
1805             {
1806                 for (int i = 0; i < indent; i++)
1807                     write(".");
1808                 writeln("N");
1809             }
1810             if (indent is 0)
1811                 writeln();
1812         }
1813 
1814         /*
1815          * Check the tree for validity.  This is called after every add or remove.
1816          * This should only be enabled to debug the implementation of the RB Tree.
1817          */
1818         void check() @trusted
1819         {
1820             //
1821             // check implementation of the tree
1822             //
1823             int recurse(Node n, string path)
1824             {
1825                 import std.stdio : writeln;
1826                 if (n is null)
1827                     return 1;
1828                 if (n.parent.left !is n && n.parent.right !is n)
1829                     throw new Exception("Node at path " ~ path ~ " has inconsistent pointers");
1830                 Node next = n.next;
1831                 static if (allowDuplicates)
1832                 {
1833                     if (next !is _end && _less(next.value, n.value))
1834                         throw new Exception("ordering invalid at path " ~ path);
1835                 }
1836                 else
1837                 {
1838                     if (next !is _end && !_less(n.value, next.value))
1839                         throw new Exception("ordering invalid at path " ~ path);
1840                 }
1841                 if (n.color == n.color.Red)
1842                 {
1843                     if ((n.left !is null && n.left.color == n.color.Red) ||
1844                             (n.right !is null && n.right.color == n.color.Red))
1845                         throw new Exception("Node at path " ~ path ~ " is red with a red child");
1846                 }
1847 
1848                 int l = recurse(n.left, path ~ "L");
1849                 int r = recurse(n.right, path ~ "R");
1850                 if (l != r)
1851                 {
1852                     writeln("bad tree at:");
1853                     debug printTree(n);
1854                     throw new Exception(
1855                         "Node at path " ~ path ~ " has different number of black nodes on left and right paths"
1856                     );
1857                 }
1858                 return l + (n.color == n.color.Black ? 1 : 0);
1859             }
1860 
1861             try
1862             {
1863                 recurse(_end.left, "");
1864             }
1865             catch (Exception e)
1866             {
1867                 debug printTree(_end.left, 0);
1868                 throw e;
1869             }
1870         }
1871     }
1872 
1873     /**
1874       Formats the RedBlackTree into a sink function. For more info see $(D
1875       std.format.formatValue). Note that this only is available when the
1876       element type can be formatted. Otherwise, the default toString from
1877       Object is used.
1878      */
1879     static if (is(typeof((){FormatSpec!(char) fmt; formatValue((const(char)[]) {}, ConstRange.init, fmt);})))
1880     {
1881         void toString(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
1882         {
1883             sink("RedBlackTree(");
1884             sink.formatValue(this[], fmt);
1885             sink(")");
1886         }
1887     }
1888 
1889     /**
1890      * Constructor. Pass in an array of elements, or individual elements to
1891      * initialize the tree with.
1892      */
1893     this(Elem[] elems...)
1894     {
1895         _setup();
1896         stableInsert(elems);
1897     }
1898 
1899     /**
1900      * Constructor. Pass in a range of elements to initialize the tree with.
1901      */
1902     this(Stuff)(Stuff stuff)
1903     if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, Elem))
1904     {
1905         _setup();
1906         stableInsert(stuff);
1907     }
1908 
1909     ///
1910     this()
1911     {
1912         _setup();
1913     }
1914 
1915     private this(Node end, size_t length)
1916     {
1917         _end = end;
1918         _begin = end.leftmost;
1919         _length = length;
1920     }
1921 }
1922 
1923 //Verify Example for removeKey.
1924 @safe pure unittest
1925 {
1926     import std.algorithm.comparison : equal;
1927     auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
1928     rbt.removeKey(1, 4, 7);
1929     assert(equal(rbt[], [0, 1, 1, 5]));
1930     rbt.removeKey(1, 1, 0);
1931     assert(equal(rbt[], [5]));
1932 }
1933 
1934 //Tests for removeKey
1935 @safe pure unittest
1936 {
1937     import std.algorithm.comparison : equal;
1938     {
1939         auto rbt = redBlackTree(["hello", "world", "foo", "bar"]);
1940         assert(equal(rbt[], ["bar", "foo", "hello", "world"]));
1941         assert(rbt.removeKey("hello") == 1);
1942         assert(equal(rbt[], ["bar", "foo", "world"]));
1943         assert(rbt.removeKey("hello") == 0);
1944         assert(equal(rbt[], ["bar", "foo", "world"]));
1945         assert(rbt.removeKey("hello", "foo", "bar") == 2);
1946         assert(equal(rbt[], ["world"]));
1947         assert(rbt.removeKey(["", "world", "hello"]) == 1);
1948         assert(rbt.empty);
1949     }
1950 
1951     {
1952         auto rbt = redBlackTree([1, 2, 12, 27, 4, 500]);
1953         assert(equal(rbt[], [1, 2, 4, 12, 27, 500]));
1954         assert(rbt.removeKey(1u) == 1);
1955         assert(equal(rbt[], [2, 4, 12, 27, 500]));
1956         assert(rbt.removeKey(cast(byte) 1) == 0);
1957         assert(equal(rbt[], [2, 4, 12, 27, 500]));
1958         assert(rbt.removeKey(1, 12u, cast(byte) 27) == 2);
1959         assert(equal(rbt[], [2, 4, 500]));
1960         assert(rbt.removeKey([cast(short) 0, cast(short) 500, cast(short) 1]) == 1);
1961         assert(equal(rbt[], [2, 4]));
1962     }
1963 }
1964 
1965 @safe pure unittest
1966 {
1967     void test(T)()
1968     {
1969         auto rt1 = new RedBlackTree!(T, "a < b", false)();
1970         auto rt2 = new RedBlackTree!(T, "a < b", true)();
1971         auto rt3 = new RedBlackTree!(T, "a > b", false)();
1972         auto rt4 = new RedBlackTree!(T, "a > b", true)();
1973     }
1974 
1975     test!long();
1976     test!ulong();
1977     test!int();
1978     test!uint();
1979     test!short();
1980     test!ushort();
1981     test!byte();
1982     test!byte();
1983 }
1984 
1985 // https://issues.dlang.org/show_bug.cgi?id=19626
1986 @safe pure unittest
1987 {
1988     enum T { a, b }
1989     alias t = RedBlackTree!T;
1990 }
1991 
1992 import std.range.primitives : isInputRange, ElementType;
1993 import std.traits : isArray, isSomeString;
1994 
1995 /++
1996     Convenience function for creating a `RedBlackTree!E` from a list of
1997     values.
1998 
1999     Params:
2000         allowDuplicates =  Whether duplicates should be allowed (optional, default: false)
2001         less = predicate to sort by (optional)
2002         elems = elements to insert into the rbtree (variadic arguments)
2003         range = range elements to insert into the rbtree (alternative to elems)
2004   +/
2005 auto redBlackTree(E)(E[] elems...)
2006 {
2007     return new RedBlackTree!E(elems);
2008 }
2009 
2010 /++ Ditto +/
2011 auto redBlackTree(bool allowDuplicates, E)(E[] elems...)
2012 {
2013     return new RedBlackTree!(E, "a < b", allowDuplicates)(elems);
2014 }
2015 
2016 /++ Ditto +/
2017 auto redBlackTree(alias less, E)(E[] elems...)
2018 if (is(typeof(binaryFun!less(E.init, E.init))))
2019 {
2020     return new RedBlackTree!(E, less)(elems);
2021 }
2022 
2023 /++ Ditto +/
2024 auto redBlackTree(alias less, bool allowDuplicates, E)(E[] elems...)
2025 if (is(typeof(binaryFun!less(E.init, E.init))))
2026 {
2027     //We shouldn't need to instantiate less here, but for some reason,
2028     //dmd can't handle it if we don't (even though the template which
2029     //takes less but not allowDuplicates works just fine).
2030     return new RedBlackTree!(E, binaryFun!less, allowDuplicates)(elems);
2031 }
2032 
2033 /++ Ditto +/
2034 auto redBlackTree(Stuff)(Stuff range)
2035 if (isInputRange!Stuff && !isArray!(Stuff))
2036 {
2037     return new RedBlackTree!(ElementType!Stuff)(range);
2038 }
2039 
2040 /++ Ditto +/
2041 auto redBlackTree(bool allowDuplicates, Stuff)(Stuff range)
2042 if (isInputRange!Stuff && !isArray!(Stuff))
2043 {
2044     return new RedBlackTree!(ElementType!Stuff, "a < b", allowDuplicates)(range);
2045 }
2046 
2047 /++ Ditto +/
2048 auto redBlackTree(alias less, Stuff)(Stuff range)
2049 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))
2050     && isInputRange!Stuff && !isArray!(Stuff))
2051 {
2052     return new RedBlackTree!(ElementType!Stuff, less)(range);
2053 }
2054 
2055 /++ Ditto +/
2056 auto redBlackTree(alias less, bool allowDuplicates, Stuff)(Stuff range)
2057 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))
2058     && isInputRange!Stuff && !isArray!(Stuff))
2059 {
2060     //We shouldn't need to instantiate less here, but for some reason,
2061     //dmd can't handle it if we don't (even though the template which
2062     //takes less but not allowDuplicates works just fine).
2063     return new RedBlackTree!(ElementType!Stuff, binaryFun!less, allowDuplicates)(range);
2064 }
2065 
2066 ///
2067 @safe pure unittest
2068 {
2069     import std.range : iota;
2070 
2071     auto rbt1 = redBlackTree(0, 1, 5, 7);
2072     auto rbt2 = redBlackTree!string("hello", "world");
2073     auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
2074     auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
2075     auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
2076 
2077     // also works with ranges
2078     auto rbt6 = redBlackTree(iota(3));
2079     auto rbt7 = redBlackTree!true(iota(3));
2080     auto rbt8 = redBlackTree!"a > b"(iota(3));
2081     auto rbt9 = redBlackTree!("a > b", true)(iota(3));
2082 }
2083 
2084 //Combinations not in examples.
2085 @system pure unittest
2086 {
2087     auto rbt1 = redBlackTree!(true, string)("hello", "hello");
2088     auto rbt2 = redBlackTree!((a, b){return a < b;}, double)(5.1, 2.3);
2089     auto rbt3 = redBlackTree!("a > b", true, string)("hello", "world");
2090 }
2091 
2092 //Range construction.
2093 @safe pure unittest
2094 {
2095     import std.algorithm.comparison : equal;
2096     import std.range : iota;
2097     auto rbt = new RedBlackTree!(int, "a > b")(iota(5));
2098     assert(equal(rbt[], [4, 3, 2, 1, 0]));
2099 }
2100 
2101 
2102 // construction with arrays
2103 @safe pure unittest
2104 {
2105     import std.algorithm.comparison : equal;
2106 
2107     auto rbt = redBlackTree!"a > b"([0, 1, 2, 3, 4]);
2108     assert(equal(rbt[], [4, 3, 2, 1, 0]));
2109 
2110     auto rbt2 = redBlackTree!"a > b"(["a", "b"]);
2111     assert(equal(rbt2[], ["b", "a"]));
2112 
2113     auto rbt3 = redBlackTree!"a > b"([1, 2]);
2114     assert(equal(rbt3[], [2, 1]));
2115 
2116     auto rbt4 = redBlackTree([0, 1, 7, 5]);
2117     assert(equal(rbt4[], [0, 1, 5, 7]));
2118 
2119     auto rbt5 = redBlackTree(["hello", "world"]);
2120     assert(equal(rbt5[], ["hello", "world"]));
2121 
2122     auto rbt6 = redBlackTree!true([0, 1, 5, 7, 5]);
2123     assert(equal(rbt6[], [0, 1, 5, 5, 7]));
2124 
2125     auto rbt7 = redBlackTree!"a > b"([0, 1, 5, 7]);
2126     assert(equal(rbt7[], [7, 5, 1, 0]));
2127 
2128     auto rbt8 = redBlackTree!("a > b", true)([0.1, 1.3, 5.9, 7.2, 5.9]);
2129     assert(equal(rbt8[], [7.2, 5.9, 5.9, 1.3, 0.1]));
2130 }
2131 
2132 // convenience wrapper range construction
2133 @safe pure unittest
2134 {
2135     import std.algorithm.comparison : equal;
2136     import std.range : chain, iota;
2137 
2138     auto rbt = redBlackTree(iota(3));
2139     assert(equal(rbt[], [0, 1, 2]));
2140 
2141     auto rbt2 = redBlackTree!"a > b"(iota(2));
2142     assert(equal(rbt2[], [1, 0]));
2143 
2144     auto rbt3 = redBlackTree(chain([0, 1], [7, 5]));
2145     assert(equal(rbt3[], [0, 1, 5, 7]));
2146 
2147     auto rbt4 = redBlackTree(chain(["hello"], ["world"]));
2148     assert(equal(rbt4[], ["hello", "world"]));
2149 
2150     auto rbt5 = redBlackTree!true(chain([0, 1], [5, 7, 5]));
2151     assert(equal(rbt5[], [0, 1, 5, 5, 7]));
2152 
2153     auto rbt6 = redBlackTree!("a > b", true)(chain([0.1, 1.3], [5.9, 7.2, 5.9]));
2154     assert(equal(rbt6[], [7.2, 5.9, 5.9, 1.3, 0.1]));
2155 }
2156 
2157 @safe pure unittest
2158 {
2159     import std.array : array;
2160 
2161     auto rt1 = redBlackTree(5, 4, 3, 2, 1);
2162     assert(rt1.length == 5);
2163     assert(array(rt1[]) == [1, 2, 3, 4, 5]);
2164 
2165     auto rt2 = redBlackTree!"a > b"(1.1, 2.1);
2166     assert(rt2.length == 2);
2167     assert(array(rt2[]) == [2.1, 1.1]);
2168 
2169     auto rt3 = redBlackTree!true(5, 5, 4);
2170     assert(rt3.length == 3);
2171     assert(array(rt3[]) == [4, 5, 5]);
2172 
2173     auto rt4 = redBlackTree!string("hello", "hello");
2174     assert(rt4.length == 1);
2175     assert(array(rt4[]) == ["hello"]);
2176 }
2177 
2178 @system unittest
2179 {
2180     import std.conv : to;
2181 
2182     auto rt1 = redBlackTree!string();
2183     assert(rt1.to!string == "RedBlackTree([])");
2184 
2185     auto rt2 = redBlackTree!string("hello");
2186     assert(rt2.to!string == "RedBlackTree([\"hello\"])");
2187 
2188     auto rt3 = redBlackTree!string("hello", "world", "!");
2189     assert(rt3.to!string == "RedBlackTree([\"!\", \"hello\", \"world\"])");
2190 
2191     // type deduction can be done automatically
2192     auto rt4 = redBlackTree(["hello"]);
2193     assert(rt4.to!string == "RedBlackTree([\"hello\"])");
2194 }
2195 
2196 //constness checks
2197 @safe pure unittest
2198 {
2199     const rt1 = redBlackTree(5,4,3,2,1);
2200     void allQualifiers() pure nothrow @safe @nogc {
2201         assert(!rt1.empty);
2202         assert(rt1.length == 5);
2203         assert(5 in rt1);
2204     }
2205     allQualifiers();
2206 
2207     static assert(is(typeof(rt1.upperBound(3).front) == const(int)));
2208     import std.algorithm.comparison : equal;
2209     assert(rt1.upperBound(3).equal([4, 5]));
2210     assert(rt1.lowerBound(3).equal([1, 2]));
2211     assert(rt1.equalRange(3).equal([3]));
2212     assert(rt1[].equal([1, 2, 3, 4, 5]));
2213 
2214     auto t = rt1.trisect(3);
2215     assert(t[0].equal(rt1.lowerBound(3)));
2216     assert(t[1].equal(rt1.equalRange(3)));
2217     assert(t[2].equal(rt1.upperBound(3)));
2218 }
2219 
2220 //immutable checks
2221 @safe pure unittest
2222 {
2223     immutable rt1 = redBlackTree(5,4,3,2,1);
2224     static assert(is(typeof(rt1.empty)));
2225     static assert(is(typeof(rt1.length)));
2226     static assert(is(typeof(5 in rt1)));
2227 
2228     static assert(is(typeof(rt1.upperBound(3).front) == immutable(int)));
2229     import std.algorithm.comparison : equal;
2230     assert(rt1.upperBound(2).equal([3, 4, 5]));
2231 }
2232 
2233 // https://issues.dlang.org/show_bug.cgi?id=15941
2234 @safe pure unittest
2235 {
2236     class C {}
2237     RedBlackTree!(C, "cast(void*)a < cast(void*) b") tree;
2238 }
2239 
2240 // const/immutable elements (https://issues.dlang.org/show_bug.cgi?id=17519)
2241 @safe pure unittest
2242 {
2243     RedBlackTree!(immutable int) t1;
2244     RedBlackTree!(const int) t2;
2245 
2246     import std.algorithm.iteration : map;
2247     static struct S { int* p; }
2248     auto t3 = new RedBlackTree!(immutable S, (a, b) => *a.p < *b.p);
2249     t3.insert([1, 2, 3].map!(x => immutable S(new int(x))));
2250     static assert(!__traits(compiles, *t3.front.p = 4));
2251     assert(*t3.front.p == 1);
2252 }
2253 
2254 // make sure the comparator can be a delegate
2255 @safe pure unittest
2256 {
2257     import std.algorithm.comparison : equal;
2258 
2259     auto t = new RedBlackTree!(int, delegate(a, b) => a > b);
2260     t.insert([1, 3, 5, 4, 2]);
2261     assert(t[].equal([5, 4, 3, 2, 1]));
2262 }