* gcc.c (getenv_spec_function): New function.
[official-gcc.git] / gcc / ada / a-crbtgo.adb
bloba9f63942fe1c243670c783736ddaca9aa726c829
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S . --
6 -- G E N E R I C _ O P E R A T I O N S --
7 -- --
8 -- B o d y --
9 -- --
10 -- Copyright (C) 2004-2006, Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
21 -- Boston, MA 02110-1301, USA. --
22 -- --
23 -- As a special exception, if other files instantiate generics from this --
24 -- unit, or you link this unit with other files to produce an executable, --
25 -- this unit does not by itself cause the resulting executable to be --
26 -- covered by the GNU General Public License. This exception does not --
27 -- however invalidate any other reasons why the executable file might be --
28 -- covered by the GNU Public License. --
29 -- --
30 -- This unit was originally developed by Matthew J Heaney. --
31 ------------------------------------------------------------------------------
33 -- The references below to "CLR" refer to the following book, from which
34 -- several of the algorithms here were adapted:
35 -- Introduction to Algorithms
36 -- by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest
37 -- Publisher: The MIT Press (June 18, 1990)
38 -- ISBN: 0262031418
40 with System; use type System.Address;
42 package body Ada.Containers.Red_Black_Trees.Generic_Operations is
44 -----------------------
45 -- Local Subprograms --
46 -----------------------
48 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access);
50 procedure Delete_Swap (Tree : in out Tree_Type; Z, Y : Node_Access);
52 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access);
53 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access);
55 -- ---------------------
56 -- -- Check_Invariant --
57 -- ---------------------
59 -- procedure Check_Invariant (Tree : Tree_Type) is
60 -- Root : constant Node_Access := Tree.Root;
62 -- function Check (Node : Node_Access) return Natural;
64 -- -----------
65 -- -- Check --
66 -- -----------
68 -- function Check (Node : Node_Access) return Natural is
69 -- begin
70 -- if Node = null then
71 -- return 0;
72 -- end if;
74 -- if Color (Node) = Red then
75 -- declare
76 -- L : constant Node_Access := Left (Node);
77 -- begin
78 -- pragma Assert (L = null or else Color (L) = Black);
79 -- null;
80 -- end;
82 -- declare
83 -- R : constant Node_Access := Right (Node);
84 -- begin
85 -- pragma Assert (R = null or else Color (R) = Black);
86 -- null;
87 -- end;
89 -- declare
90 -- NL : constant Natural := Check (Left (Node));
91 -- NR : constant Natural := Check (Right (Node));
92 -- begin
93 -- pragma Assert (NL = NR);
94 -- return NL;
95 -- end;
96 -- end if;
98 -- declare
99 -- NL : constant Natural := Check (Left (Node));
100 -- NR : constant Natural := Check (Right (Node));
101 -- begin
102 -- pragma Assert (NL = NR);
103 -- return NL + 1;
104 -- end;
105 -- end Check;
107 -- -- Start of processing for Check_Invariant
109 -- begin
110 -- if Root = null then
111 -- pragma Assert (Tree.First = null);
112 -- pragma Assert (Tree.Last = null);
113 -- pragma Assert (Tree.Length = 0);
114 -- null;
116 -- else
117 -- pragma Assert (Color (Root) = Black);
118 -- pragma Assert (Tree.Length > 0);
119 -- pragma Assert (Tree.Root /= null);
120 -- pragma Assert (Tree.First /= null);
121 -- pragma Assert (Tree.Last /= null);
122 -- pragma Assert (Parent (Tree.Root) = null);
123 -- pragma Assert ((Tree.Length > 1)
124 -- or else (Tree.First = Tree.Last
125 -- and Tree.First = Tree.Root));
126 -- pragma Assert (Left (Tree.First) = null);
127 -- pragma Assert (Right (Tree.Last) = null);
129 -- declare
130 -- L : constant Node_Access := Left (Root);
131 -- R : constant Node_Access := Right (Root);
132 -- NL : constant Natural := Check (L);
133 -- NR : constant Natural := Check (R);
134 -- begin
135 -- pragma Assert (NL = NR);
136 -- null;
137 -- end;
138 -- end if;
139 -- end Check_Invariant;
141 ------------------
142 -- Delete_Fixup --
143 ------------------
145 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access) is
147 -- CLR p274
149 X : Node_Access := Node;
150 W : Node_Access;
152 begin
153 while X /= Tree.Root
154 and then Color (X) = Black
155 loop
156 if X = Left (Parent (X)) then
157 W := Right (Parent (X));
159 if Color (W) = Red then
160 Set_Color (W, Black);
161 Set_Color (Parent (X), Red);
162 Left_Rotate (Tree, Parent (X));
163 W := Right (Parent (X));
164 end if;
166 if (Left (W) = null or else Color (Left (W)) = Black)
167 and then
168 (Right (W) = null or else Color (Right (W)) = Black)
169 then
170 Set_Color (W, Red);
171 X := Parent (X);
173 else
174 if Right (W) = null
175 or else Color (Right (W)) = Black
176 then
177 if Left (W) /= null then
178 Set_Color (Left (W), Black);
179 end if;
181 Set_Color (W, Red);
182 Right_Rotate (Tree, W);
183 W := Right (Parent (X));
184 end if;
186 Set_Color (W, Color (Parent (X)));
187 Set_Color (Parent (X), Black);
188 Set_Color (Right (W), Black);
189 Left_Rotate (Tree, Parent (X));
190 X := Tree.Root;
191 end if;
193 else
194 pragma Assert (X = Right (Parent (X)));
196 W := Left (Parent (X));
198 if Color (W) = Red then
199 Set_Color (W, Black);
200 Set_Color (Parent (X), Red);
201 Right_Rotate (Tree, Parent (X));
202 W := Left (Parent (X));
203 end if;
205 if (Left (W) = null or else Color (Left (W)) = Black)
206 and then
207 (Right (W) = null or else Color (Right (W)) = Black)
208 then
209 Set_Color (W, Red);
210 X := Parent (X);
212 else
213 if Left (W) = null or else Color (Left (W)) = Black then
214 if Right (W) /= null then
215 Set_Color (Right (W), Black);
216 end if;
218 Set_Color (W, Red);
219 Left_Rotate (Tree, W);
220 W := Left (Parent (X));
221 end if;
223 Set_Color (W, Color (Parent (X)));
224 Set_Color (Parent (X), Black);
225 Set_Color (Left (W), Black);
226 Right_Rotate (Tree, Parent (X));
227 X := Tree.Root;
228 end if;
229 end if;
230 end loop;
232 Set_Color (X, Black);
233 end Delete_Fixup;
235 ---------------------------
236 -- Delete_Node_Sans_Free --
237 ---------------------------
239 procedure Delete_Node_Sans_Free
240 (Tree : in out Tree_Type;
241 Node : Node_Access)
243 -- CLR p273
245 X, Y : Node_Access;
247 Z : constant Node_Access := Node;
248 pragma Assert (Z /= null);
250 begin
251 if Tree.Busy > 0 then
252 raise Program_Error with
253 "attempt to tamper with cursors (container is busy)";
254 end if;
256 -- pragma Assert (Tree.Length > 0);
257 -- pragma Assert (Tree.Root /= null);
258 -- pragma Assert (Tree.First /= null);
259 -- pragma Assert (Tree.Last /= null);
260 -- pragma Assert (Parent (Tree.Root) = null);
261 -- pragma Assert ((Tree.Length > 1)
262 -- or else (Tree.First = Tree.Last
263 -- and then Tree.First = Tree.Root));
264 -- pragma Assert ((Left (Node) = null)
265 -- or else (Parent (Left (Node)) = Node));
266 -- pragma Assert ((Right (Node) = null)
267 -- or else (Parent (Right (Node)) = Node));
268 -- pragma Assert (((Parent (Node) = null) and then (Tree.Root = Node))
269 -- or else ((Parent (Node) /= null) and then
270 -- ((Left (Parent (Node)) = Node)
271 -- or else (Right (Parent (Node)) = Node))));
273 if Left (Z) = null then
274 if Right (Z) = null then
275 if Z = Tree.First then
276 Tree.First := Parent (Z);
277 end if;
279 if Z = Tree.Last then
280 Tree.Last := Parent (Z);
281 end if;
283 if Color (Z) = Black then
284 Delete_Fixup (Tree, Z);
285 end if;
287 pragma Assert (Left (Z) = null);
288 pragma Assert (Right (Z) = null);
290 if Z = Tree.Root then
291 pragma Assert (Tree.Length = 1);
292 pragma Assert (Parent (Z) = null);
293 Tree.Root := null;
294 elsif Z = Left (Parent (Z)) then
295 Set_Left (Parent (Z), null);
296 else
297 pragma Assert (Z = Right (Parent (Z)));
298 Set_Right (Parent (Z), null);
299 end if;
301 else
302 pragma Assert (Z /= Tree.Last);
304 X := Right (Z);
306 if Z = Tree.First then
307 Tree.First := Min (X);
308 end if;
310 if Z = Tree.Root then
311 Tree.Root := X;
312 elsif Z = Left (Parent (Z)) then
313 Set_Left (Parent (Z), X);
314 else
315 pragma Assert (Z = Right (Parent (Z)));
316 Set_Right (Parent (Z), X);
317 end if;
319 Set_Parent (X, Parent (Z));
321 if Color (Z) = Black then
322 Delete_Fixup (Tree, X);
323 end if;
324 end if;
326 elsif Right (Z) = null then
327 pragma Assert (Z /= Tree.First);
329 X := Left (Z);
331 if Z = Tree.Last then
332 Tree.Last := Max (X);
333 end if;
335 if Z = Tree.Root then
336 Tree.Root := X;
337 elsif Z = Left (Parent (Z)) then
338 Set_Left (Parent (Z), X);
339 else
340 pragma Assert (Z = Right (Parent (Z)));
341 Set_Right (Parent (Z), X);
342 end if;
344 Set_Parent (X, Parent (Z));
346 if Color (Z) = Black then
347 Delete_Fixup (Tree, X);
348 end if;
350 else
351 pragma Assert (Z /= Tree.First);
352 pragma Assert (Z /= Tree.Last);
354 Y := Next (Z);
355 pragma Assert (Left (Y) = null);
357 X := Right (Y);
359 if X = null then
360 if Y = Left (Parent (Y)) then
361 pragma Assert (Parent (Y) /= Z);
362 Delete_Swap (Tree, Z, Y);
363 Set_Left (Parent (Z), Z);
365 else
366 pragma Assert (Y = Right (Parent (Y)));
367 pragma Assert (Parent (Y) = Z);
368 Set_Parent (Y, Parent (Z));
370 if Z = Tree.Root then
371 Tree.Root := Y;
372 elsif Z = Left (Parent (Z)) then
373 Set_Left (Parent (Z), Y);
374 else
375 pragma Assert (Z = Right (Parent (Z)));
376 Set_Right (Parent (Z), Y);
377 end if;
379 Set_Left (Y, Left (Z));
380 Set_Parent (Left (Y), Y);
381 Set_Right (Y, Z);
382 Set_Parent (Z, Y);
383 Set_Left (Z, null);
384 Set_Right (Z, null);
386 declare
387 Y_Color : constant Color_Type := Color (Y);
388 begin
389 Set_Color (Y, Color (Z));
390 Set_Color (Z, Y_Color);
391 end;
392 end if;
394 if Color (Z) = Black then
395 Delete_Fixup (Tree, Z);
396 end if;
398 pragma Assert (Left (Z) = null);
399 pragma Assert (Right (Z) = null);
401 if Z = Right (Parent (Z)) then
402 Set_Right (Parent (Z), null);
403 else
404 pragma Assert (Z = Left (Parent (Z)));
405 Set_Left (Parent (Z), null);
406 end if;
408 else
409 if Y = Left (Parent (Y)) then
410 pragma Assert (Parent (Y) /= Z);
412 Delete_Swap (Tree, Z, Y);
414 Set_Left (Parent (Z), X);
415 Set_Parent (X, Parent (Z));
417 else
418 pragma Assert (Y = Right (Parent (Y)));
419 pragma Assert (Parent (Y) = Z);
421 Set_Parent (Y, Parent (Z));
423 if Z = Tree.Root then
424 Tree.Root := Y;
425 elsif Z = Left (Parent (Z)) then
426 Set_Left (Parent (Z), Y);
427 else
428 pragma Assert (Z = Right (Parent (Z)));
429 Set_Right (Parent (Z), Y);
430 end if;
432 Set_Left (Y, Left (Z));
433 Set_Parent (Left (Y), Y);
435 declare
436 Y_Color : constant Color_Type := Color (Y);
437 begin
438 Set_Color (Y, Color (Z));
439 Set_Color (Z, Y_Color);
440 end;
441 end if;
443 if Color (Z) = Black then
444 Delete_Fixup (Tree, X);
445 end if;
446 end if;
447 end if;
449 Tree.Length := Tree.Length - 1;
450 end Delete_Node_Sans_Free;
452 -----------------
453 -- Delete_Swap --
454 -----------------
456 procedure Delete_Swap
457 (Tree : in out Tree_Type;
458 Z, Y : Node_Access)
460 pragma Assert (Z /= Y);
461 pragma Assert (Parent (Y) /= Z);
463 Y_Parent : constant Node_Access := Parent (Y);
464 Y_Color : constant Color_Type := Color (Y);
466 begin
467 Set_Parent (Y, Parent (Z));
468 Set_Left (Y, Left (Z));
469 Set_Right (Y, Right (Z));
470 Set_Color (Y, Color (Z));
472 if Tree.Root = Z then
473 Tree.Root := Y;
474 elsif Right (Parent (Y)) = Z then
475 Set_Right (Parent (Y), Y);
476 else
477 pragma Assert (Left (Parent (Y)) = Z);
478 Set_Left (Parent (Y), Y);
479 end if;
481 if Right (Y) /= null then
482 Set_Parent (Right (Y), Y);
483 end if;
485 if Left (Y) /= null then
486 Set_Parent (Left (Y), Y);
487 end if;
489 Set_Parent (Z, Y_Parent);
490 Set_Color (Z, Y_Color);
491 Set_Left (Z, null);
492 Set_Right (Z, null);
493 end Delete_Swap;
495 --------------------
496 -- Generic_Adjust --
497 --------------------
499 procedure Generic_Adjust (Tree : in out Tree_Type) is
500 N : constant Count_Type := Tree.Length;
501 Root : constant Node_Access := Tree.Root;
503 begin
504 if N = 0 then
505 pragma Assert (Root = null);
506 pragma Assert (Tree.Busy = 0);
507 pragma Assert (Tree.Lock = 0);
508 return;
509 end if;
511 Tree.Root := null;
512 Tree.First := null;
513 Tree.Last := null;
514 Tree.Length := 0;
516 Tree.Root := Copy_Tree (Root);
517 Tree.First := Min (Tree.Root);
518 Tree.Last := Max (Tree.Root);
519 Tree.Length := N;
520 end Generic_Adjust;
522 -------------------
523 -- Generic_Clear --
524 -------------------
526 procedure Generic_Clear (Tree : in out Tree_Type) is
527 Root : Node_Access := Tree.Root;
528 begin
529 if Tree.Busy > 0 then
530 raise Program_Error with
531 "attempt to tamper with cursors (container is busy)";
532 end if;
534 Tree := (First => null,
535 Last => null,
536 Root => null,
537 Length => 0,
538 Busy => 0,
539 Lock => 0);
541 Delete_Tree (Root);
542 end Generic_Clear;
544 -----------------------
545 -- Generic_Copy_Tree --
546 -----------------------
548 function Generic_Copy_Tree (Source_Root : Node_Access) return Node_Access is
549 Target_Root : Node_Access := Copy_Node (Source_Root);
550 P, X : Node_Access;
552 begin
553 if Right (Source_Root) /= null then
554 Set_Right
555 (Node => Target_Root,
556 Right => Generic_Copy_Tree (Right (Source_Root)));
558 Set_Parent
559 (Node => Right (Target_Root),
560 Parent => Target_Root);
561 end if;
563 P := Target_Root;
565 X := Left (Source_Root);
566 while X /= null loop
567 declare
568 Y : constant Node_Access := Copy_Node (X);
569 begin
570 Set_Left (Node => P, Left => Y);
571 Set_Parent (Node => Y, Parent => P);
573 if Right (X) /= null then
574 Set_Right
575 (Node => Y,
576 Right => Generic_Copy_Tree (Right (X)));
578 Set_Parent
579 (Node => Right (Y),
580 Parent => Y);
581 end if;
583 P := Y;
584 X := Left (X);
585 end;
586 end loop;
588 return Target_Root;
589 exception
590 when others =>
591 Delete_Tree (Target_Root);
592 raise;
593 end Generic_Copy_Tree;
595 -------------------------
596 -- Generic_Delete_Tree --
597 -------------------------
599 procedure Generic_Delete_Tree (X : in out Node_Access) is
600 Y : Node_Access;
601 begin
602 while X /= null loop
603 Y := Right (X);
604 Generic_Delete_Tree (Y);
605 Y := Left (X);
606 Free (X);
607 X := Y;
608 end loop;
609 end Generic_Delete_Tree;
611 -------------------
612 -- Generic_Equal --
613 -------------------
615 function Generic_Equal (Left, Right : Tree_Type) return Boolean is
616 L_Node : Node_Access;
617 R_Node : Node_Access;
619 begin
620 if Left'Address = Right'Address then
621 return True;
622 end if;
624 if Left.Length /= Right.Length then
625 return False;
626 end if;
628 L_Node := Left.First;
629 R_Node := Right.First;
630 while L_Node /= null loop
631 if not Is_Equal (L_Node, R_Node) then
632 return False;
633 end if;
635 L_Node := Next (L_Node);
636 R_Node := Next (R_Node);
637 end loop;
639 return True;
640 end Generic_Equal;
642 -----------------------
643 -- Generic_Iteration --
644 -----------------------
646 procedure Generic_Iteration (Tree : Tree_Type) is
647 procedure Iterate (P : Node_Access);
649 -------------
650 -- Iterate --
651 -------------
653 procedure Iterate (P : Node_Access) is
654 X : Node_Access := P;
655 begin
656 while X /= null loop
657 Iterate (Left (X));
658 Process (X);
659 X := Right (X);
660 end loop;
661 end Iterate;
663 -- Start of processing for Generic_Iteration
665 begin
666 Iterate (Tree.Root);
667 end Generic_Iteration;
669 ------------------
670 -- Generic_Move --
671 ------------------
673 procedure Generic_Move (Target, Source : in out Tree_Type) is
674 begin
675 if Target'Address = Source'Address then
676 return;
677 end if;
679 if Source.Busy > 0 then
680 raise Program_Error with
681 "attempt to tamper with cursors (container is busy)";
682 end if;
684 Clear (Target);
686 Target := Source;
688 Source := (First => null,
689 Last => null,
690 Root => null,
691 Length => 0,
692 Busy => 0,
693 Lock => 0);
694 end Generic_Move;
696 ------------------
697 -- Generic_Read --
698 ------------------
700 procedure Generic_Read
701 (Stream : access Root_Stream_Type'Class;
702 Tree : in out Tree_Type)
704 N : Count_Type'Base;
706 Node, Last_Node : Node_Access;
708 begin
709 Clear (Tree);
711 Count_Type'Base'Read (Stream, N);
712 pragma Assert (N >= 0);
714 if N = 0 then
715 return;
716 end if;
718 Node := Read_Node (Stream);
719 pragma Assert (Node /= null);
720 pragma Assert (Color (Node) = Red);
722 Set_Color (Node, Black);
724 Tree.Root := Node;
725 Tree.First := Node;
726 Tree.Last := Node;
728 Tree.Length := 1;
730 for J in Count_Type range 2 .. N loop
731 Last_Node := Node;
732 pragma Assert (Last_Node = Tree.Last);
734 Node := Read_Node (Stream);
735 pragma Assert (Node /= null);
736 pragma Assert (Color (Node) = Red);
738 Set_Right (Node => Last_Node, Right => Node);
739 Tree.Last := Node;
740 Set_Parent (Node => Node, Parent => Last_Node);
741 Rebalance_For_Insert (Tree, Node);
742 Tree.Length := Tree.Length + 1;
743 end loop;
744 end Generic_Read;
746 -------------------------------
747 -- Generic_Reverse_Iteration --
748 -------------------------------
750 procedure Generic_Reverse_Iteration (Tree : Tree_Type)
752 procedure Iterate (P : Node_Access);
754 -------------
755 -- Iterate --
756 -------------
758 procedure Iterate (P : Node_Access) is
759 X : Node_Access := P;
760 begin
761 while X /= null loop
762 Iterate (Right (X));
763 Process (X);
764 X := Left (X);
765 end loop;
766 end Iterate;
768 -- Start of processing for Generic_Reverse_Iteration
770 begin
771 Iterate (Tree.Root);
772 end Generic_Reverse_Iteration;
774 -------------------
775 -- Generic_Write --
776 -------------------
778 procedure Generic_Write
779 (Stream : access Root_Stream_Type'Class;
780 Tree : Tree_Type)
782 procedure Process (Node : Node_Access);
783 pragma Inline (Process);
785 procedure Iterate is
786 new Generic_Iteration (Process);
788 -------------
789 -- Process --
790 -------------
792 procedure Process (Node : Node_Access) is
793 begin
794 Write_Node (Stream, Node);
795 end Process;
797 -- Start of processing for Generic_Write
799 begin
800 Count_Type'Base'Write (Stream, Tree.Length);
801 Iterate (Tree);
802 end Generic_Write;
804 -----------------
805 -- Left_Rotate --
806 -----------------
808 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access) is
810 -- CLR p266
812 Y : constant Node_Access := Right (X);
813 pragma Assert (Y /= null);
815 begin
816 Set_Right (X, Left (Y));
818 if Left (Y) /= null then
819 Set_Parent (Left (Y), X);
820 end if;
822 Set_Parent (Y, Parent (X));
824 if X = Tree.Root then
825 Tree.Root := Y;
826 elsif X = Left (Parent (X)) then
827 Set_Left (Parent (X), Y);
828 else
829 pragma Assert (X = Right (Parent (X)));
830 Set_Right (Parent (X), Y);
831 end if;
833 Set_Left (Y, X);
834 Set_Parent (X, Y);
835 end Left_Rotate;
837 ---------
838 -- Max --
839 ---------
841 function Max (Node : Node_Access) return Node_Access is
843 -- CLR p248
845 X : Node_Access := Node;
846 Y : Node_Access;
848 begin
849 loop
850 Y := Right (X);
852 if Y = null then
853 return X;
854 end if;
856 X := Y;
857 end loop;
858 end Max;
860 ---------
861 -- Min --
862 ---------
864 function Min (Node : Node_Access) return Node_Access is
866 -- CLR p248
868 X : Node_Access := Node;
869 Y : Node_Access;
871 begin
872 loop
873 Y := Left (X);
875 if Y = null then
876 return X;
877 end if;
879 X := Y;
880 end loop;
881 end Min;
883 ----------
884 -- Next --
885 ----------
887 function Next (Node : Node_Access) return Node_Access is
888 begin
889 -- CLR p249
891 if Node = null then
892 return null;
893 end if;
895 if Right (Node) /= null then
896 return Min (Right (Node));
897 end if;
899 declare
900 X : Node_Access := Node;
901 Y : Node_Access := Parent (Node);
903 begin
904 while Y /= null
905 and then X = Right (Y)
906 loop
907 X := Y;
908 Y := Parent (Y);
909 end loop;
911 return Y;
912 end;
913 end Next;
915 --------------
916 -- Previous --
917 --------------
919 function Previous (Node : Node_Access) return Node_Access is
920 begin
921 if Node = null then
922 return null;
923 end if;
925 if Left (Node) /= null then
926 return Max (Left (Node));
927 end if;
929 declare
930 X : Node_Access := Node;
931 Y : Node_Access := Parent (Node);
933 begin
934 while Y /= null
935 and then X = Left (Y)
936 loop
937 X := Y;
938 Y := Parent (Y);
939 end loop;
941 return Y;
942 end;
943 end Previous;
945 --------------------------
946 -- Rebalance_For_Insert --
947 --------------------------
949 procedure Rebalance_For_Insert
950 (Tree : in out Tree_Type;
951 Node : Node_Access)
953 -- CLR p.268
955 X : Node_Access := Node;
956 pragma Assert (X /= null);
957 pragma Assert (Color (X) = Red);
959 Y : Node_Access;
961 begin
962 while X /= Tree.Root and then Color (Parent (X)) = Red loop
963 if Parent (X) = Left (Parent (Parent (X))) then
964 Y := Right (Parent (Parent (X)));
966 if Y /= null and then Color (Y) = Red then
967 Set_Color (Parent (X), Black);
968 Set_Color (Y, Black);
969 Set_Color (Parent (Parent (X)), Red);
970 X := Parent (Parent (X));
972 else
973 if X = Right (Parent (X)) then
974 X := Parent (X);
975 Left_Rotate (Tree, X);
976 end if;
978 Set_Color (Parent (X), Black);
979 Set_Color (Parent (Parent (X)), Red);
980 Right_Rotate (Tree, Parent (Parent (X)));
981 end if;
983 else
984 pragma Assert (Parent (X) = Right (Parent (Parent (X))));
986 Y := Left (Parent (Parent (X)));
988 if Y /= null and then Color (Y) = Red then
989 Set_Color (Parent (X), Black);
990 Set_Color (Y, Black);
991 Set_Color (Parent (Parent (X)), Red);
992 X := Parent (Parent (X));
994 else
995 if X = Left (Parent (X)) then
996 X := Parent (X);
997 Right_Rotate (Tree, X);
998 end if;
1000 Set_Color (Parent (X), Black);
1001 Set_Color (Parent (Parent (X)), Red);
1002 Left_Rotate (Tree, Parent (Parent (X)));
1003 end if;
1004 end if;
1005 end loop;
1007 Set_Color (Tree.Root, Black);
1008 end Rebalance_For_Insert;
1010 ------------------
1011 -- Right_Rotate --
1012 ------------------
1014 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access) is
1015 X : constant Node_Access := Left (Y);
1016 pragma Assert (X /= null);
1018 begin
1019 Set_Left (Y, Right (X));
1021 if Right (X) /= null then
1022 Set_Parent (Right (X), Y);
1023 end if;
1025 Set_Parent (X, Parent (Y));
1027 if Y = Tree.Root then
1028 Tree.Root := X;
1029 elsif Y = Left (Parent (Y)) then
1030 Set_Left (Parent (Y), X);
1031 else
1032 pragma Assert (Y = Right (Parent (Y)));
1033 Set_Right (Parent (Y), X);
1034 end if;
1036 Set_Right (X, Y);
1037 Set_Parent (Y, X);
1038 end Right_Rotate;
1040 ---------
1041 -- Vet --
1042 ---------
1044 function Vet (Tree : Tree_Type; Node : Node_Access) return Boolean is
1045 begin
1046 if Node = null then
1047 return True;
1048 end if;
1050 if Parent (Node) = Node
1051 or else Left (Node) = Node
1052 or else Right (Node) = Node
1053 then
1054 return False;
1055 end if;
1057 if Tree.Length = 0
1058 or else Tree.Root = null
1059 or else Tree.First = null
1060 or else Tree.Last = null
1061 then
1062 return False;
1063 end if;
1065 if Parent (Tree.Root) /= null then
1066 return False;
1067 end if;
1069 if Left (Tree.First) /= null then
1070 return False;
1071 end if;
1073 if Right (Tree.Last) /= null then
1074 return False;
1075 end if;
1077 if Tree.Length = 1 then
1078 if Tree.First /= Tree.Last
1079 or else Tree.First /= Tree.Root
1080 then
1081 return False;
1082 end if;
1084 if Node /= Tree.First then
1085 return False;
1086 end if;
1088 if Parent (Node) /= null
1089 or else Left (Node) /= null
1090 or else Right (Node) /= null
1091 then
1092 return False;
1093 end if;
1095 return True;
1096 end if;
1098 if Tree.First = Tree.Last then
1099 return False;
1100 end if;
1102 if Tree.Length = 2 then
1103 if Tree.First /= Tree.Root
1104 and then Tree.Last /= Tree.Root
1105 then
1106 return False;
1107 end if;
1109 if Tree.First /= Node
1110 and then Tree.Last /= Node
1111 then
1112 return False;
1113 end if;
1114 end if;
1116 if Left (Node) /= null
1117 and then Parent (Left (Node)) /= Node
1118 then
1119 return False;
1120 end if;
1122 if Right (Node) /= null
1123 and then Parent (Right (Node)) /= Node
1124 then
1125 return False;
1126 end if;
1128 if Parent (Node) = null then
1129 if Tree.Root /= Node then
1130 return False;
1131 end if;
1133 elsif Left (Parent (Node)) /= Node
1134 and then Right (Parent (Node)) /= Node
1135 then
1136 return False;
1137 end if;
1139 return True;
1140 end Vet;
1142 end Ada.Containers.Red_Black_Trees.Generic_Operations;