PR rtl-optimization/82913
[official-gcc.git] / gcc / ada / libgnat / a-crbtgo.adb
blob53fe273fd96277646f8c15fe6730259c27146dcf
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_OPERATIONS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2017, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 -- The references below to "CLR" refer to the following book, from which
31 -- several of the algorithms here were adapted:
32 -- Introduction to Algorithms
33 -- by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest
34 -- Publisher: The MIT Press (June 18, 1990)
35 -- ISBN: 0262031418
37 with System; use type System.Address;
39 package body Ada.Containers.Red_Black_Trees.Generic_Operations is
41 pragma Warnings (Off, "variable ""Busy*"" is not referenced");
42 pragma Warnings (Off, "variable ""Lock*"" is not referenced");
43 -- See comment in Ada.Containers.Helpers
45 -----------------------
46 -- Local Subprograms --
47 -----------------------
49 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access);
51 procedure Delete_Swap (Tree : in out Tree_Type; Z, Y : Node_Access);
53 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access);
54 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access);
56 -- Why is all the following code commented out ???
58 -- ---------------------
59 -- -- Check_Invariant --
60 -- ---------------------
62 -- procedure Check_Invariant (Tree : Tree_Type) is
63 -- Root : constant Node_Access := Tree.Root;
65 -- function Check (Node : Node_Access) return Natural;
67 -- -----------
68 -- -- Check --
69 -- -----------
71 -- function Check (Node : Node_Access) return Natural is
72 -- begin
73 -- if Node = null then
74 -- return 0;
75 -- end if;
77 -- if Color (Node) = Red then
78 -- declare
79 -- L : constant Node_Access := Left (Node);
80 -- begin
81 -- pragma Assert (L = null or else Color (L) = Black);
82 -- null;
83 -- end;
85 -- declare
86 -- R : constant Node_Access := Right (Node);
87 -- begin
88 -- pragma Assert (R = null or else Color (R) = Black);
89 -- null;
90 -- end;
92 -- declare
93 -- NL : constant Natural := Check (Left (Node));
94 -- NR : constant Natural := Check (Right (Node));
95 -- begin
96 -- pragma Assert (NL = NR);
97 -- return NL;
98 -- end;
99 -- end if;
101 -- declare
102 -- NL : constant Natural := Check (Left (Node));
103 -- NR : constant Natural := Check (Right (Node));
104 -- begin
105 -- pragma Assert (NL = NR);
106 -- return NL + 1;
107 -- end;
108 -- end Check;
110 -- -- Start of processing for Check_Invariant
112 -- begin
113 -- if Root = null then
114 -- pragma Assert (Tree.First = null);
115 -- pragma Assert (Tree.Last = null);
116 -- pragma Assert (Tree.Length = 0);
117 -- null;
119 -- else
120 -- pragma Assert (Color (Root) = Black);
121 -- pragma Assert (Tree.Length > 0);
122 -- pragma Assert (Tree.Root /= null);
123 -- pragma Assert (Tree.First /= null);
124 -- pragma Assert (Tree.Last /= null);
125 -- pragma Assert (Parent (Tree.Root) = null);
126 -- pragma Assert ((Tree.Length > 1)
127 -- or else (Tree.First = Tree.Last
128 -- and Tree.First = Tree.Root));
129 -- pragma Assert (Left (Tree.First) = null);
130 -- pragma Assert (Right (Tree.Last) = null);
132 -- declare
133 -- L : constant Node_Access := Left (Root);
134 -- R : constant Node_Access := Right (Root);
135 -- NL : constant Natural := Check (L);
136 -- NR : constant Natural := Check (R);
137 -- begin
138 -- pragma Assert (NL = NR);
139 -- null;
140 -- end;
141 -- end if;
142 -- end Check_Invariant;
144 ------------------
145 -- Delete_Fixup --
146 ------------------
148 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access) is
150 -- CLR p274
152 X : Node_Access := Node;
153 W : Node_Access;
155 begin
156 while X /= Tree.Root
157 and then Color (X) = Black
158 loop
159 if X = Left (Parent (X)) then
160 W := Right (Parent (X));
162 if Color (W) = Red then
163 Set_Color (W, Black);
164 Set_Color (Parent (X), Red);
165 Left_Rotate (Tree, Parent (X));
166 W := Right (Parent (X));
167 end if;
169 if (Left (W) = null or else Color (Left (W)) = Black)
170 and then
171 (Right (W) = null or else Color (Right (W)) = Black)
172 then
173 Set_Color (W, Red);
174 X := Parent (X);
176 else
177 if Right (W) = null
178 or else Color (Right (W)) = Black
179 then
180 -- As a condition for setting the color of the left child to
181 -- black, the left child access value must be non-null. A
182 -- truth table analysis shows that if we arrive here, that
183 -- condition holds, so there's no need for an explicit test.
184 -- The assertion is here to document what we know is true.
186 pragma Assert (Left (W) /= null);
187 Set_Color (Left (W), Black);
189 Set_Color (W, Red);
190 Right_Rotate (Tree, W);
191 W := Right (Parent (X));
192 end if;
194 Set_Color (W, Color (Parent (X)));
195 Set_Color (Parent (X), Black);
196 Set_Color (Right (W), Black);
197 Left_Rotate (Tree, Parent (X));
198 X := Tree.Root;
199 end if;
201 else
202 pragma Assert (X = Right (Parent (X)));
204 W := Left (Parent (X));
206 if Color (W) = Red then
207 Set_Color (W, Black);
208 Set_Color (Parent (X), Red);
209 Right_Rotate (Tree, Parent (X));
210 W := Left (Parent (X));
211 end if;
213 if (Left (W) = null or else Color (Left (W)) = Black)
214 and then
215 (Right (W) = null or else Color (Right (W)) = Black)
216 then
217 Set_Color (W, Red);
218 X := Parent (X);
220 else
221 if Left (W) = null or else Color (Left (W)) = Black then
223 -- As a condition for setting the color of the right child
224 -- to black, the right child access value must be non-null.
225 -- A truth table analysis shows that if we arrive here, that
226 -- condition holds, so there's no need for an explicit test.
227 -- The assertion is here to document what we know is true.
229 pragma Assert (Right (W) /= null);
230 Set_Color (Right (W), Black);
232 Set_Color (W, Red);
233 Left_Rotate (Tree, W);
234 W := Left (Parent (X));
235 end if;
237 Set_Color (W, Color (Parent (X)));
238 Set_Color (Parent (X), Black);
239 Set_Color (Left (W), Black);
240 Right_Rotate (Tree, Parent (X));
241 X := Tree.Root;
242 end if;
243 end if;
244 end loop;
246 Set_Color (X, Black);
247 end Delete_Fixup;
249 ---------------------------
250 -- Delete_Node_Sans_Free --
251 ---------------------------
253 procedure Delete_Node_Sans_Free
254 (Tree : in out Tree_Type;
255 Node : Node_Access)
257 -- CLR p273
259 X, Y : Node_Access;
261 Z : constant Node_Access := Node;
262 pragma Assert (Z /= null);
264 begin
265 TC_Check (Tree.TC);
267 -- Why are these all commented out ???
269 -- pragma Assert (Tree.Length > 0);
270 -- pragma Assert (Tree.Root /= null);
271 -- pragma Assert (Tree.First /= null);
272 -- pragma Assert (Tree.Last /= null);
273 -- pragma Assert (Parent (Tree.Root) = null);
274 -- pragma Assert ((Tree.Length > 1)
275 -- or else (Tree.First = Tree.Last
276 -- and then Tree.First = Tree.Root));
277 -- pragma Assert ((Left (Node) = null)
278 -- or else (Parent (Left (Node)) = Node));
279 -- pragma Assert ((Right (Node) = null)
280 -- or else (Parent (Right (Node)) = Node));
281 -- pragma Assert (((Parent (Node) = null) and then (Tree.Root = Node))
282 -- or else ((Parent (Node) /= null) and then
283 -- ((Left (Parent (Node)) = Node)
284 -- or else (Right (Parent (Node)) = Node))));
286 if Left (Z) = null then
287 if Right (Z) = null then
288 if Z = Tree.First then
289 Tree.First := Parent (Z);
290 end if;
292 if Z = Tree.Last then
293 Tree.Last := Parent (Z);
294 end if;
296 if Color (Z) = Black then
297 Delete_Fixup (Tree, Z);
298 end if;
300 pragma Assert (Left (Z) = null);
301 pragma Assert (Right (Z) = null);
303 if Z = Tree.Root then
304 pragma Assert (Tree.Length = 1);
305 pragma Assert (Parent (Z) = null);
306 Tree.Root := null;
307 elsif Z = Left (Parent (Z)) then
308 Set_Left (Parent (Z), null);
309 else
310 pragma Assert (Z = Right (Parent (Z)));
311 Set_Right (Parent (Z), null);
312 end if;
314 else
315 pragma Assert (Z /= Tree.Last);
317 X := Right (Z);
319 if Z = Tree.First then
320 Tree.First := Min (X);
321 end if;
323 if Z = Tree.Root then
324 Tree.Root := X;
325 elsif Z = Left (Parent (Z)) then
326 Set_Left (Parent (Z), X);
327 else
328 pragma Assert (Z = Right (Parent (Z)));
329 Set_Right (Parent (Z), X);
330 end if;
332 Set_Parent (X, Parent (Z));
334 if Color (Z) = Black then
335 Delete_Fixup (Tree, X);
336 end if;
337 end if;
339 elsif Right (Z) = null then
340 pragma Assert (Z /= Tree.First);
342 X := Left (Z);
344 if Z = Tree.Last then
345 Tree.Last := Max (X);
346 end if;
348 if Z = Tree.Root then
349 Tree.Root := X;
350 elsif Z = Left (Parent (Z)) then
351 Set_Left (Parent (Z), X);
352 else
353 pragma Assert (Z = Right (Parent (Z)));
354 Set_Right (Parent (Z), X);
355 end if;
357 Set_Parent (X, Parent (Z));
359 if Color (Z) = Black then
360 Delete_Fixup (Tree, X);
361 end if;
363 else
364 pragma Assert (Z /= Tree.First);
365 pragma Assert (Z /= Tree.Last);
367 Y := Next (Z);
368 pragma Assert (Left (Y) = null);
370 X := Right (Y);
372 if X = null then
373 if Y = Left (Parent (Y)) then
374 pragma Assert (Parent (Y) /= Z);
375 Delete_Swap (Tree, Z, Y);
376 Set_Left (Parent (Z), Z);
378 else
379 pragma Assert (Y = Right (Parent (Y)));
380 pragma Assert (Parent (Y) = Z);
381 Set_Parent (Y, Parent (Z));
383 if Z = Tree.Root then
384 Tree.Root := Y;
385 elsif Z = Left (Parent (Z)) then
386 Set_Left (Parent (Z), Y);
387 else
388 pragma Assert (Z = Right (Parent (Z)));
389 Set_Right (Parent (Z), Y);
390 end if;
392 Set_Left (Y, Left (Z));
393 Set_Parent (Left (Y), Y);
394 Set_Right (Y, Z);
395 Set_Parent (Z, Y);
396 Set_Left (Z, null);
397 Set_Right (Z, null);
399 declare
400 Y_Color : constant Color_Type := Color (Y);
401 begin
402 Set_Color (Y, Color (Z));
403 Set_Color (Z, Y_Color);
404 end;
405 end if;
407 if Color (Z) = Black then
408 Delete_Fixup (Tree, Z);
409 end if;
411 pragma Assert (Left (Z) = null);
412 pragma Assert (Right (Z) = null);
414 if Z = Right (Parent (Z)) then
415 Set_Right (Parent (Z), null);
416 else
417 pragma Assert (Z = Left (Parent (Z)));
418 Set_Left (Parent (Z), null);
419 end if;
421 else
422 if Y = Left (Parent (Y)) then
423 pragma Assert (Parent (Y) /= Z);
425 Delete_Swap (Tree, Z, Y);
427 Set_Left (Parent (Z), X);
428 Set_Parent (X, Parent (Z));
430 else
431 pragma Assert (Y = Right (Parent (Y)));
432 pragma Assert (Parent (Y) = Z);
434 Set_Parent (Y, Parent (Z));
436 if Z = Tree.Root then
437 Tree.Root := Y;
438 elsif Z = Left (Parent (Z)) then
439 Set_Left (Parent (Z), Y);
440 else
441 pragma Assert (Z = Right (Parent (Z)));
442 Set_Right (Parent (Z), Y);
443 end if;
445 Set_Left (Y, Left (Z));
446 Set_Parent (Left (Y), Y);
448 declare
449 Y_Color : constant Color_Type := Color (Y);
450 begin
451 Set_Color (Y, Color (Z));
452 Set_Color (Z, Y_Color);
453 end;
454 end if;
456 if Color (Z) = Black then
457 Delete_Fixup (Tree, X);
458 end if;
459 end if;
460 end if;
462 Tree.Length := Tree.Length - 1;
463 end Delete_Node_Sans_Free;
465 -----------------
466 -- Delete_Swap --
467 -----------------
469 procedure Delete_Swap
470 (Tree : in out Tree_Type;
471 Z, Y : Node_Access)
473 pragma Assert (Z /= Y);
474 pragma Assert (Parent (Y) /= Z);
476 Y_Parent : constant Node_Access := Parent (Y);
477 Y_Color : constant Color_Type := Color (Y);
479 begin
480 Set_Parent (Y, Parent (Z));
481 Set_Left (Y, Left (Z));
482 Set_Right (Y, Right (Z));
483 Set_Color (Y, Color (Z));
485 if Tree.Root = Z then
486 Tree.Root := Y;
487 elsif Right (Parent (Y)) = Z then
488 Set_Right (Parent (Y), Y);
489 else
490 pragma Assert (Left (Parent (Y)) = Z);
491 Set_Left (Parent (Y), Y);
492 end if;
494 if Right (Y) /= null then
495 Set_Parent (Right (Y), Y);
496 end if;
498 if Left (Y) /= null then
499 Set_Parent (Left (Y), Y);
500 end if;
502 Set_Parent (Z, Y_Parent);
503 Set_Color (Z, Y_Color);
504 Set_Left (Z, null);
505 Set_Right (Z, null);
506 end Delete_Swap;
508 --------------------
509 -- Generic_Adjust --
510 --------------------
512 procedure Generic_Adjust (Tree : in out Tree_Type) is
513 N : constant Count_Type := Tree.Length;
514 Root : constant Node_Access := Tree.Root;
516 begin
517 -- If the counts are nonzero, execution is technically erroneous, but
518 -- it seems friendly to allow things like concurrent "=" on shared
519 -- constants.
521 Zero_Counts (Tree.TC);
523 if N = 0 then
524 pragma Assert (Root = null);
525 return;
526 end if;
528 Tree.Root := null;
529 Tree.First := null;
530 Tree.Last := null;
531 Tree.Length := 0;
533 Tree.Root := Copy_Tree (Root);
534 Tree.First := Min (Tree.Root);
535 Tree.Last := Max (Tree.Root);
536 Tree.Length := N;
537 end Generic_Adjust;
539 -------------------
540 -- Generic_Clear --
541 -------------------
543 procedure Generic_Clear (Tree : in out Tree_Type) is
544 Root : Node_Access := Tree.Root;
545 begin
546 TC_Check (Tree.TC);
548 Tree := (First => null,
549 Last => null,
550 Root => null,
551 Length => 0,
552 TC => <>);
554 Delete_Tree (Root);
555 end Generic_Clear;
557 -----------------------
558 -- Generic_Copy_Tree --
559 -----------------------
561 function Generic_Copy_Tree (Source_Root : Node_Access) return Node_Access is
562 Target_Root : Node_Access := Copy_Node (Source_Root);
563 P, X : Node_Access;
565 begin
566 if Right (Source_Root) /= null then
567 Set_Right
568 (Node => Target_Root,
569 Right => Generic_Copy_Tree (Right (Source_Root)));
571 Set_Parent
572 (Node => Right (Target_Root),
573 Parent => Target_Root);
574 end if;
576 P := Target_Root;
578 X := Left (Source_Root);
579 while X /= null loop
580 declare
581 Y : constant Node_Access := Copy_Node (X);
582 begin
583 Set_Left (Node => P, Left => Y);
584 Set_Parent (Node => Y, Parent => P);
586 if Right (X) /= null then
587 Set_Right
588 (Node => Y,
589 Right => Generic_Copy_Tree (Right (X)));
591 Set_Parent
592 (Node => Right (Y),
593 Parent => Y);
594 end if;
596 P := Y;
597 X := Left (X);
598 end;
599 end loop;
601 return Target_Root;
603 exception
604 when others =>
605 Delete_Tree (Target_Root);
606 raise;
607 end Generic_Copy_Tree;
609 -------------------------
610 -- Generic_Delete_Tree --
611 -------------------------
613 procedure Generic_Delete_Tree (X : in out Node_Access) is
614 Y : Node_Access;
615 pragma Warnings (Off, Y);
616 begin
617 while X /= null loop
618 Y := Right (X);
619 Generic_Delete_Tree (Y);
620 Y := Left (X);
621 Free (X);
622 X := Y;
623 end loop;
624 end Generic_Delete_Tree;
626 -------------------
627 -- Generic_Equal --
628 -------------------
630 function Generic_Equal (Left, Right : Tree_Type) return Boolean is
631 begin
632 if Left.Length /= Right.Length then
633 return False;
634 end if;
636 -- If the containers are empty, return a result immediately, so as to
637 -- not manipulate the tamper bits unnecessarily.
639 if Left.Length = 0 then
640 return True;
641 end if;
643 declare
644 Lock_Left : With_Lock (Left.TC'Unrestricted_Access);
645 Lock_Right : With_Lock (Right.TC'Unrestricted_Access);
647 L_Node : Node_Access := Left.First;
648 R_Node : Node_Access := Right.First;
649 begin
650 while L_Node /= null loop
651 if not Is_Equal (L_Node, R_Node) then
652 return False;
653 end if;
655 L_Node := Next (L_Node);
656 R_Node := Next (R_Node);
657 end loop;
658 end;
660 return True;
661 end Generic_Equal;
663 -----------------------
664 -- Generic_Iteration --
665 -----------------------
667 procedure Generic_Iteration (Tree : Tree_Type) is
668 procedure Iterate (P : Node_Access);
670 -------------
671 -- Iterate --
672 -------------
674 procedure Iterate (P : Node_Access) is
675 X : Node_Access := P;
676 begin
677 while X /= null loop
678 Iterate (Left (X));
679 Process (X);
680 X := Right (X);
681 end loop;
682 end Iterate;
684 -- Start of processing for Generic_Iteration
686 begin
687 Iterate (Tree.Root);
688 end Generic_Iteration;
690 ------------------
691 -- Generic_Move --
692 ------------------
694 procedure Generic_Move (Target, Source : in out Tree_Type) is
695 begin
696 if Target'Address = Source'Address then
697 return;
698 end if;
700 TC_Check (Source.TC);
702 Clear (Target);
704 Target := Source;
706 Source := (First => null,
707 Last => null,
708 Root => null,
709 Length => 0,
710 TC => <>);
711 end Generic_Move;
713 ------------------
714 -- Generic_Read --
715 ------------------
717 procedure Generic_Read
718 (Stream : not null access Root_Stream_Type'Class;
719 Tree : in out Tree_Type)
721 N : Count_Type'Base;
723 Node, Last_Node : Node_Access;
725 begin
726 Clear (Tree);
728 Count_Type'Base'Read (Stream, N);
729 pragma Assert (N >= 0);
731 if N = 0 then
732 return;
733 end if;
735 Node := Read_Node (Stream);
736 pragma Assert (Node /= null);
737 pragma Assert (Color (Node) = Red);
739 Set_Color (Node, Black);
741 Tree.Root := Node;
742 Tree.First := Node;
743 Tree.Last := Node;
745 Tree.Length := 1;
747 for J in Count_Type range 2 .. N loop
748 Last_Node := Node;
749 pragma Assert (Last_Node = Tree.Last);
751 Node := Read_Node (Stream);
752 pragma Assert (Node /= null);
753 pragma Assert (Color (Node) = Red);
755 Set_Right (Node => Last_Node, Right => Node);
756 Tree.Last := Node;
757 Set_Parent (Node => Node, Parent => Last_Node);
758 Rebalance_For_Insert (Tree, Node);
759 Tree.Length := Tree.Length + 1;
760 end loop;
761 end Generic_Read;
763 -------------------------------
764 -- Generic_Reverse_Iteration --
765 -------------------------------
767 procedure Generic_Reverse_Iteration (Tree : Tree_Type)
769 procedure Iterate (P : Node_Access);
771 -------------
772 -- Iterate --
773 -------------
775 procedure Iterate (P : Node_Access) is
776 X : Node_Access := P;
777 begin
778 while X /= null loop
779 Iterate (Right (X));
780 Process (X);
781 X := Left (X);
782 end loop;
783 end Iterate;
785 -- Start of processing for Generic_Reverse_Iteration
787 begin
788 Iterate (Tree.Root);
789 end Generic_Reverse_Iteration;
791 -------------------
792 -- Generic_Write --
793 -------------------
795 procedure Generic_Write
796 (Stream : not null access Root_Stream_Type'Class;
797 Tree : Tree_Type)
799 procedure Process (Node : Node_Access);
800 pragma Inline (Process);
802 procedure Iterate is
803 new Generic_Iteration (Process);
805 -------------
806 -- Process --
807 -------------
809 procedure Process (Node : Node_Access) is
810 begin
811 Write_Node (Stream, Node);
812 end Process;
814 -- Start of processing for Generic_Write
816 begin
817 Count_Type'Base'Write (Stream, Tree.Length);
818 Iterate (Tree);
819 end Generic_Write;
821 -----------------
822 -- Left_Rotate --
823 -----------------
825 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access) is
827 -- CLR p266
829 Y : constant Node_Access := Right (X);
830 pragma Assert (Y /= null);
832 begin
833 Set_Right (X, Left (Y));
835 if Left (Y) /= null then
836 Set_Parent (Left (Y), X);
837 end if;
839 Set_Parent (Y, Parent (X));
841 if X = Tree.Root then
842 Tree.Root := Y;
843 elsif X = Left (Parent (X)) then
844 Set_Left (Parent (X), Y);
845 else
846 pragma Assert (X = Right (Parent (X)));
847 Set_Right (Parent (X), Y);
848 end if;
850 Set_Left (Y, X);
851 Set_Parent (X, Y);
852 end Left_Rotate;
854 ---------
855 -- Max --
856 ---------
858 function Max (Node : Node_Access) return Node_Access is
860 -- CLR p248
862 X : Node_Access := Node;
863 Y : Node_Access;
865 begin
866 loop
867 Y := Right (X);
869 if Y = null then
870 return X;
871 end if;
873 X := Y;
874 end loop;
875 end Max;
877 ---------
878 -- Min --
879 ---------
881 function Min (Node : Node_Access) return Node_Access is
883 -- CLR p248
885 X : Node_Access := Node;
886 Y : Node_Access;
888 begin
889 loop
890 Y := Left (X);
892 if Y = null then
893 return X;
894 end if;
896 X := Y;
897 end loop;
898 end Min;
900 ----------
901 -- Next --
902 ----------
904 function Next (Node : Node_Access) return Node_Access is
905 begin
906 -- CLR p249
908 if Node = null then
909 return null;
910 end if;
912 if Right (Node) /= null then
913 return Min (Right (Node));
914 end if;
916 declare
917 X : Node_Access := Node;
918 Y : Node_Access := Parent (Node);
920 begin
921 while Y /= null
922 and then X = Right (Y)
923 loop
924 X := Y;
925 Y := Parent (Y);
926 end loop;
928 return Y;
929 end;
930 end Next;
932 --------------
933 -- Previous --
934 --------------
936 function Previous (Node : Node_Access) return Node_Access is
937 begin
938 if Node = null then
939 return null;
940 end if;
942 if Left (Node) /= null then
943 return Max (Left (Node));
944 end if;
946 declare
947 X : Node_Access := Node;
948 Y : Node_Access := Parent (Node);
950 begin
951 while Y /= null
952 and then X = Left (Y)
953 loop
954 X := Y;
955 Y := Parent (Y);
956 end loop;
958 return Y;
959 end;
960 end Previous;
962 --------------------------
963 -- Rebalance_For_Insert --
964 --------------------------
966 procedure Rebalance_For_Insert
967 (Tree : in out Tree_Type;
968 Node : Node_Access)
970 -- CLR p.268
972 X : Node_Access := Node;
973 pragma Assert (X /= null);
974 pragma Assert (Color (X) = Red);
976 Y : Node_Access;
978 begin
979 while X /= Tree.Root and then Color (Parent (X)) = Red loop
980 if Parent (X) = Left (Parent (Parent (X))) then
981 Y := Right (Parent (Parent (X)));
983 if Y /= null and then Color (Y) = Red then
984 Set_Color (Parent (X), Black);
985 Set_Color (Y, Black);
986 Set_Color (Parent (Parent (X)), Red);
987 X := Parent (Parent (X));
989 else
990 if X = Right (Parent (X)) then
991 X := Parent (X);
992 Left_Rotate (Tree, X);
993 end if;
995 Set_Color (Parent (X), Black);
996 Set_Color (Parent (Parent (X)), Red);
997 Right_Rotate (Tree, Parent (Parent (X)));
998 end if;
1000 else
1001 pragma Assert (Parent (X) = Right (Parent (Parent (X))));
1003 Y := Left (Parent (Parent (X)));
1005 if Y /= null and then Color (Y) = Red then
1006 Set_Color (Parent (X), Black);
1007 Set_Color (Y, Black);
1008 Set_Color (Parent (Parent (X)), Red);
1009 X := Parent (Parent (X));
1011 else
1012 if X = Left (Parent (X)) then
1013 X := Parent (X);
1014 Right_Rotate (Tree, X);
1015 end if;
1017 Set_Color (Parent (X), Black);
1018 Set_Color (Parent (Parent (X)), Red);
1019 Left_Rotate (Tree, Parent (Parent (X)));
1020 end if;
1021 end if;
1022 end loop;
1024 Set_Color (Tree.Root, Black);
1025 end Rebalance_For_Insert;
1027 ------------------
1028 -- Right_Rotate --
1029 ------------------
1031 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access) is
1032 X : constant Node_Access := Left (Y);
1033 pragma Assert (X /= null);
1035 begin
1036 Set_Left (Y, Right (X));
1038 if Right (X) /= null then
1039 Set_Parent (Right (X), Y);
1040 end if;
1042 Set_Parent (X, Parent (Y));
1044 if Y = Tree.Root then
1045 Tree.Root := X;
1046 elsif Y = Left (Parent (Y)) then
1047 Set_Left (Parent (Y), X);
1048 else
1049 pragma Assert (Y = Right (Parent (Y)));
1050 Set_Right (Parent (Y), X);
1051 end if;
1053 Set_Right (X, Y);
1054 Set_Parent (Y, X);
1055 end Right_Rotate;
1057 ---------
1058 -- Vet --
1059 ---------
1061 function Vet (Tree : Tree_Type; Node : Node_Access) return Boolean is
1062 begin
1063 if Node = null then
1064 return True;
1065 end if;
1067 if Parent (Node) = Node
1068 or else Left (Node) = Node
1069 or else Right (Node) = Node
1070 then
1071 return False;
1072 end if;
1074 if Tree.Length = 0
1075 or else Tree.Root = null
1076 or else Tree.First = null
1077 or else Tree.Last = null
1078 then
1079 return False;
1080 end if;
1082 if Parent (Tree.Root) /= null then
1083 return False;
1084 end if;
1086 if Left (Tree.First) /= null then
1087 return False;
1088 end if;
1090 if Right (Tree.Last) /= null then
1091 return False;
1092 end if;
1094 if Tree.Length = 1 then
1095 if Tree.First /= Tree.Last
1096 or else Tree.First /= Tree.Root
1097 then
1098 return False;
1099 end if;
1101 if Node /= Tree.First then
1102 return False;
1103 end if;
1105 if Parent (Node) /= null
1106 or else Left (Node) /= null
1107 or else Right (Node) /= null
1108 then
1109 return False;
1110 end if;
1112 return True;
1113 end if;
1115 if Tree.First = Tree.Last then
1116 return False;
1117 end if;
1119 if Tree.Length = 2 then
1120 if Tree.First /= Tree.Root
1121 and then Tree.Last /= Tree.Root
1122 then
1123 return False;
1124 end if;
1126 if Tree.First /= Node
1127 and then Tree.Last /= Node
1128 then
1129 return False;
1130 end if;
1131 end if;
1133 if Left (Node) /= null
1134 and then Parent (Left (Node)) /= Node
1135 then
1136 return False;
1137 end if;
1139 if Right (Node) /= null
1140 and then Parent (Right (Node)) /= Node
1141 then
1142 return False;
1143 end if;
1145 if Parent (Node) = null then
1146 if Tree.Root /= Node then
1147 return False;
1148 end if;
1150 elsif Left (Parent (Node)) /= Node
1151 and then Right (Parent (Node)) /= Node
1152 then
1153 return False;
1154 end if;
1156 return True;
1157 end Vet;
1159 end Ada.Containers.Red_Black_Trees.Generic_Operations;