1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT LIBRARY COMPONENTS                          --
4--                                                                          --
5--           ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_SET_OPERATIONS          --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--          Copyright (C) 2004-2013, 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------------------------------------------------------------------------------
29
30with System; use type System.Address;
31
32package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
33
34   -----------------------
35   -- Local Subprograms --
36   -----------------------
37
38   procedure Clear (Tree : in out Tree_Type);
39
40   function Copy (Source : Tree_Type) return Tree_Type;
41
42   -----------
43   -- Clear --
44   -----------
45
46   procedure Clear (Tree : in out Tree_Type) is
47      pragma Assert (Tree.Busy = 0);
48      pragma Assert (Tree.Lock = 0);
49
50      Root : Node_Access := Tree.Root;
51      pragma Warnings (Off, Root);
52
53   begin
54      Tree.Root := null;
55      Tree.First := null;
56      Tree.Last := null;
57      Tree.Length := 0;
58
59      Delete_Tree (Root);
60   end Clear;
61
62   ----------
63   -- Copy --
64   ----------
65
66   function Copy (Source : Tree_Type) return Tree_Type is
67      Target : Tree_Type;
68
69   begin
70      if Source.Length = 0 then
71         return Target;
72      end if;
73
74      Target.Root := Copy_Tree (Source.Root);
75      Target.First := Tree_Operations.Min (Target.Root);
76      Target.Last := Tree_Operations.Max (Target.Root);
77      Target.Length := Source.Length;
78
79      return Target;
80   end Copy;
81
82   ----------------
83   -- Difference --
84   ----------------
85
86   procedure Difference (Target : in out Tree_Type; Source : Tree_Type) is
87      BT : Natural renames Target.Busy;
88      LT : Natural renames Target.Lock;
89
90      BS : Natural renames Source'Unrestricted_Access.Busy;
91      LS : Natural renames Source'Unrestricted_Access.Lock;
92
93      Tgt : Node_Access;
94      Src : Node_Access;
95
96      Compare : Integer;
97
98   begin
99      if Target'Address = Source'Address then
100         if Target.Busy > 0 then
101            raise Program_Error with
102              "attempt to tamper with cursors (container is busy)";
103         end if;
104
105         Clear (Target);
106         return;
107      end if;
108
109      if Source.Length = 0 then
110         return;
111      end if;
112
113      if Target.Busy > 0 then
114         raise Program_Error with
115           "attempt to tamper with cursors (container is busy)";
116      end if;
117
118      Tgt := Target.First;
119      Src := Source.First;
120      loop
121         if Tgt = null then
122            exit;
123         end if;
124
125         if Src = null then
126            exit;
127         end if;
128
129         --  Per AI05-0022, the container implementation is required to detect
130         --  element tampering by a generic actual subprogram.
131
132         begin
133            BT := BT + 1;
134            LT := LT + 1;
135
136            BS := BS + 1;
137            LS := LS + 1;
138
139            if Is_Less (Tgt, Src) then
140               Compare := -1;
141            elsif Is_Less (Src, Tgt) then
142               Compare := 1;
143            else
144               Compare := 0;
145            end if;
146
147            BT := BT - 1;
148            LT := LT - 1;
149
150            BS := BS - 1;
151            LS := LS - 1;
152
153         exception
154            when others =>
155               BT := BT - 1;
156               LT := LT - 1;
157
158               BS := BS - 1;
159               LS := LS - 1;
160
161               raise;
162         end;
163
164         if Compare < 0 then
165            Tgt := Tree_Operations.Next (Tgt);
166
167         elsif Compare > 0 then
168            Src := Tree_Operations.Next (Src);
169
170         else
171            declare
172               X : Node_Access := Tgt;
173            begin
174               Tgt := Tree_Operations.Next (Tgt);
175               Tree_Operations.Delete_Node_Sans_Free (Target, X);
176               Free (X);
177            end;
178
179            Src := Tree_Operations.Next (Src);
180         end if;
181      end loop;
182   end Difference;
183
184   function Difference (Left, Right : Tree_Type) return Tree_Type is
185   begin
186      if Left'Address = Right'Address then
187         return Tree_Type'(others => <>);  -- Empty set
188      end if;
189
190      if Left.Length = 0 then
191         return Tree_Type'(others => <>);  -- Empty set
192      end if;
193
194      if Right.Length = 0 then
195         return Copy (Left);
196      end if;
197
198      --  Per AI05-0022, the container implementation is required to detect
199      --  element tampering by a generic actual subprogram.
200
201      declare
202         BL : Natural renames Left'Unrestricted_Access.Busy;
203         LL : Natural renames Left'Unrestricted_Access.Lock;
204
205         BR : Natural renames Right'Unrestricted_Access.Busy;
206         LR : Natural renames Right'Unrestricted_Access.Lock;
207
208         Tree : Tree_Type;
209
210         L_Node : Node_Access;
211         R_Node : Node_Access;
212
213         Dst_Node : Node_Access;
214         pragma Warnings (Off, Dst_Node);
215
216      begin
217         BL := BL + 1;
218         LL := LL + 1;
219
220         BR := BR + 1;
221         LR := LR + 1;
222
223         L_Node := Left.First;
224         R_Node := Right.First;
225         loop
226            if L_Node = null then
227               exit;
228            end if;
229
230            if R_Node = null then
231               while L_Node /= null loop
232                  Insert_With_Hint
233                    (Dst_Tree => Tree,
234                     Dst_Hint => null,
235                     Src_Node => L_Node,
236                     Dst_Node => Dst_Node);
237
238                  L_Node := Tree_Operations.Next (L_Node);
239               end loop;
240
241               exit;
242            end if;
243
244            if Is_Less (L_Node, R_Node) then
245               Insert_With_Hint
246                 (Dst_Tree => Tree,
247                  Dst_Hint => null,
248                  Src_Node => L_Node,
249                  Dst_Node => Dst_Node);
250
251               L_Node := Tree_Operations.Next (L_Node);
252
253            elsif Is_Less (R_Node, L_Node) then
254               R_Node := Tree_Operations.Next (R_Node);
255
256            else
257               L_Node := Tree_Operations.Next (L_Node);
258               R_Node := Tree_Operations.Next (R_Node);
259            end if;
260         end loop;
261
262         BL := BL - 1;
263         LL := LL - 1;
264
265         BR := BR - 1;
266         LR := LR - 1;
267
268         return Tree;
269
270      exception
271         when others =>
272            BL := BL - 1;
273            LL := LL - 1;
274
275            BR := BR - 1;
276            LR := LR - 1;
277
278            Delete_Tree (Tree.Root);
279            raise;
280      end;
281   end Difference;
282
283   ------------------
284   -- Intersection --
285   ------------------
286
287   procedure Intersection
288     (Target : in out Tree_Type;
289      Source : Tree_Type)
290   is
291      BT : Natural renames Target.Busy;
292      LT : Natural renames Target.Lock;
293
294      BS : Natural renames Source'Unrestricted_Access.Busy;
295      LS : Natural renames Source'Unrestricted_Access.Lock;
296
297      Tgt : Node_Access;
298      Src : Node_Access;
299
300      Compare : Integer;
301
302   begin
303      if Target'Address = Source'Address then
304         return;
305      end if;
306
307      if Target.Busy > 0 then
308         raise Program_Error with
309           "attempt to tamper with cursors (container is busy)";
310      end if;
311
312      if Source.Length = 0 then
313         Clear (Target);
314         return;
315      end if;
316
317      Tgt := Target.First;
318      Src := Source.First;
319      while Tgt /= null
320        and then Src /= null
321      loop
322         --  Per AI05-0022, the container implementation is required to detect
323         --  element tampering by a generic actual subprogram.
324
325         begin
326            BT := BT + 1;
327            LT := LT + 1;
328
329            BS := BS + 1;
330            LS := LS + 1;
331
332            if Is_Less (Tgt, Src) then
333               Compare := -1;
334            elsif Is_Less (Src, Tgt) then
335               Compare := 1;
336            else
337               Compare := 0;
338            end if;
339
340            BT := BT - 1;
341            LT := LT - 1;
342
343            BS := BS - 1;
344            LS := LS - 1;
345
346         exception
347            when others =>
348               BT := BT - 1;
349               LT := LT - 1;
350
351               BS := BS - 1;
352               LS := LS - 1;
353
354               raise;
355         end;
356
357         if Compare < 0 then
358            declare
359               X : Node_Access := Tgt;
360            begin
361               Tgt := Tree_Operations.Next (Tgt);
362               Tree_Operations.Delete_Node_Sans_Free (Target, X);
363               Free (X);
364            end;
365
366         elsif Compare > 0 then
367            Src := Tree_Operations.Next (Src);
368
369         else
370            Tgt := Tree_Operations.Next (Tgt);
371            Src := Tree_Operations.Next (Src);
372         end if;
373      end loop;
374
375      while Tgt /= null loop
376         declare
377            X : Node_Access := Tgt;
378         begin
379            Tgt := Tree_Operations.Next (Tgt);
380            Tree_Operations.Delete_Node_Sans_Free (Target, X);
381            Free (X);
382         end;
383      end loop;
384   end Intersection;
385
386   function Intersection (Left, Right : Tree_Type) return Tree_Type is
387   begin
388      if Left'Address = Right'Address then
389         return Copy (Left);
390      end if;
391
392      --  Per AI05-0022, the container implementation is required to detect
393      --  element tampering by a generic actual subprogram.
394
395      declare
396         BL : Natural renames Left'Unrestricted_Access.Busy;
397         LL : Natural renames Left'Unrestricted_Access.Lock;
398
399         BR : Natural renames Right'Unrestricted_Access.Busy;
400         LR : Natural renames Right'Unrestricted_Access.Lock;
401
402         Tree : Tree_Type;
403
404         L_Node : Node_Access;
405         R_Node : Node_Access;
406
407         Dst_Node : Node_Access;
408         pragma Warnings (Off, Dst_Node);
409
410      begin
411         BL := BL + 1;
412         LL := LL + 1;
413
414         BR := BR + 1;
415         LR := LR + 1;
416
417         L_Node := Left.First;
418         R_Node := Right.First;
419         loop
420            if L_Node = null then
421               exit;
422            end if;
423
424            if R_Node = null then
425               exit;
426            end if;
427
428            if Is_Less (L_Node, R_Node) then
429               L_Node := Tree_Operations.Next (L_Node);
430
431            elsif Is_Less (R_Node, L_Node) then
432               R_Node := Tree_Operations.Next (R_Node);
433
434            else
435               Insert_With_Hint
436                 (Dst_Tree => Tree,
437                  Dst_Hint => null,
438                  Src_Node => L_Node,
439                  Dst_Node => Dst_Node);
440
441               L_Node := Tree_Operations.Next (L_Node);
442               R_Node := Tree_Operations.Next (R_Node);
443            end if;
444         end loop;
445
446         BL := BL - 1;
447         LL := LL - 1;
448
449         BR := BR - 1;
450         LR := LR - 1;
451
452         return Tree;
453
454      exception
455         when others =>
456            BL := BL - 1;
457            LL := LL - 1;
458
459            BR := BR - 1;
460            LR := LR - 1;
461
462            Delete_Tree (Tree.Root);
463            raise;
464      end;
465   end Intersection;
466
467   ---------------
468   -- Is_Subset --
469   ---------------
470
471   function Is_Subset
472     (Subset : Tree_Type;
473      Of_Set : Tree_Type) return Boolean
474   is
475   begin
476      if Subset'Address = Of_Set'Address then
477         return True;
478      end if;
479
480      if Subset.Length > Of_Set.Length then
481         return False;
482      end if;
483
484      --  Per AI05-0022, the container implementation is required to detect
485      --  element tampering by a generic actual subprogram.
486
487      declare
488         BL : Natural renames Subset'Unrestricted_Access.Busy;
489         LL : Natural renames Subset'Unrestricted_Access.Lock;
490
491         BR : Natural renames Of_Set'Unrestricted_Access.Busy;
492         LR : Natural renames Of_Set'Unrestricted_Access.Lock;
493
494         Subset_Node : Node_Access;
495         Set_Node    : Node_Access;
496
497         Result : Boolean;
498
499      begin
500         BL := BL + 1;
501         LL := LL + 1;
502
503         BR := BR + 1;
504         LR := LR + 1;
505
506         Subset_Node := Subset.First;
507         Set_Node    := Of_Set.First;
508         loop
509            if Set_Node = null then
510               Result := Subset_Node = null;
511               exit;
512            end if;
513
514            if Subset_Node = null then
515               Result := True;
516               exit;
517            end if;
518
519            if Is_Less (Subset_Node, Set_Node) then
520               Result := False;
521               exit;
522            end if;
523
524            if Is_Less (Set_Node, Subset_Node) then
525               Set_Node := Tree_Operations.Next (Set_Node);
526            else
527               Set_Node := Tree_Operations.Next (Set_Node);
528               Subset_Node := Tree_Operations.Next (Subset_Node);
529            end if;
530         end loop;
531
532         BL := BL - 1;
533         LL := LL - 1;
534
535         BR := BR - 1;
536         LR := LR - 1;
537
538         return Result;
539
540      exception
541         when others =>
542            BL := BL - 1;
543            LL := LL - 1;
544
545            BR := BR - 1;
546            LR := LR - 1;
547
548            raise;
549      end;
550   end Is_Subset;
551
552   -------------
553   -- Overlap --
554   -------------
555
556   function Overlap (Left, Right : Tree_Type) return Boolean is
557   begin
558      if Left'Address = Right'Address then
559         return Left.Length /= 0;
560      end if;
561
562      --  Per AI05-0022, the container implementation is required to detect
563      --  element tampering by a generic actual subprogram.
564
565      declare
566         BL : Natural renames Left'Unrestricted_Access.Busy;
567         LL : Natural renames Left'Unrestricted_Access.Lock;
568
569         BR : Natural renames Right'Unrestricted_Access.Busy;
570         LR : Natural renames Right'Unrestricted_Access.Lock;
571
572         L_Node : Node_Access;
573         R_Node : Node_Access;
574
575         Result : Boolean;
576
577      begin
578         BL := BL + 1;
579         LL := LL + 1;
580
581         BR := BR + 1;
582         LR := LR + 1;
583
584         L_Node := Left.First;
585         R_Node := Right.First;
586         loop
587            if L_Node = null
588              or else R_Node = null
589            then
590               Result := False;
591               exit;
592            end if;
593
594            if Is_Less (L_Node, R_Node) then
595               L_Node := Tree_Operations.Next (L_Node);
596
597            elsif Is_Less (R_Node, L_Node) then
598               R_Node := Tree_Operations.Next (R_Node);
599
600            else
601               Result := True;
602               exit;
603            end if;
604         end loop;
605
606         BL := BL - 1;
607         LL := LL - 1;
608
609         BR := BR - 1;
610         LR := LR - 1;
611
612         return Result;
613
614      exception
615         when others =>
616            BL := BL - 1;
617            LL := LL - 1;
618
619            BR := BR - 1;
620            LR := LR - 1;
621
622            raise;
623      end;
624   end Overlap;
625
626   --------------------------
627   -- Symmetric_Difference --
628   --------------------------
629
630   procedure Symmetric_Difference
631     (Target : in out Tree_Type;
632      Source : Tree_Type)
633   is
634      BT : Natural renames Target.Busy;
635      LT : Natural renames Target.Lock;
636
637      BS : Natural renames Source'Unrestricted_Access.Busy;
638      LS : Natural renames Source'Unrestricted_Access.Lock;
639
640      Tgt : Node_Access;
641      Src : Node_Access;
642
643      New_Tgt_Node : Node_Access;
644      pragma Warnings (Off, New_Tgt_Node);
645
646      Compare : Integer;
647
648   begin
649      if Target'Address = Source'Address then
650         Clear (Target);
651         return;
652      end if;
653
654      Tgt := Target.First;
655      Src := Source.First;
656      loop
657         if Tgt = null then
658            while Src /= null loop
659               Insert_With_Hint
660                 (Dst_Tree => Target,
661                  Dst_Hint => null,
662                  Src_Node => Src,
663                  Dst_Node => New_Tgt_Node);
664
665               Src := Tree_Operations.Next (Src);
666            end loop;
667
668            return;
669         end if;
670
671         if Src = null then
672            return;
673         end if;
674
675         --  Per AI05-0022, the container implementation is required to detect
676         --  element tampering by a generic actual subprogram.
677
678         begin
679            BT := BT + 1;
680            LT := LT + 1;
681
682            BS := BS + 1;
683            LS := LS + 1;
684
685            if Is_Less (Tgt, Src) then
686               Compare := -1;
687            elsif Is_Less (Src, Tgt) then
688               Compare := 1;
689            else
690               Compare := 0;
691            end if;
692
693            BT := BT - 1;
694            LT := LT - 1;
695
696            BS := BS - 1;
697            LS := LS - 1;
698
699         exception
700            when others =>
701               BT := BT - 1;
702               LT := LT - 1;
703
704               BS := BS - 1;
705               LS := LS - 1;
706
707               raise;
708         end;
709
710         if Compare < 0 then
711            Tgt := Tree_Operations.Next (Tgt);
712
713         elsif Compare > 0 then
714            Insert_With_Hint
715              (Dst_Tree => Target,
716               Dst_Hint => Tgt,
717               Src_Node => Src,
718               Dst_Node => New_Tgt_Node);
719
720            Src := Tree_Operations.Next (Src);
721
722         else
723            declare
724               X : Node_Access := Tgt;
725            begin
726               Tgt := Tree_Operations.Next (Tgt);
727               Tree_Operations.Delete_Node_Sans_Free (Target, X);
728               Free (X);
729            end;
730
731            Src := Tree_Operations.Next (Src);
732         end if;
733      end loop;
734   end Symmetric_Difference;
735
736   function Symmetric_Difference (Left, Right : Tree_Type) return Tree_Type is
737   begin
738      if Left'Address = Right'Address then
739         return Tree_Type'(others => <>);  -- Empty set
740      end if;
741
742      if Right.Length = 0 then
743         return Copy (Left);
744      end if;
745
746      if Left.Length = 0 then
747         return Copy (Right);
748      end if;
749
750      --  Per AI05-0022, the container implementation is required to detect
751      --  element tampering by a generic actual subprogram.
752
753      declare
754         BL : Natural renames Left'Unrestricted_Access.Busy;
755         LL : Natural renames Left'Unrestricted_Access.Lock;
756
757         BR : Natural renames Right'Unrestricted_Access.Busy;
758         LR : Natural renames Right'Unrestricted_Access.Lock;
759
760         Tree : Tree_Type;
761
762         L_Node : Node_Access;
763         R_Node : Node_Access;
764
765         Dst_Node : Node_Access;
766         pragma Warnings (Off, Dst_Node);
767
768      begin
769         BL := BL + 1;
770         LL := LL + 1;
771
772         BR := BR + 1;
773         LR := LR + 1;
774
775         L_Node := Left.First;
776         R_Node := Right.First;
777         loop
778            if L_Node = null then
779               while R_Node /= null loop
780                  Insert_With_Hint
781                    (Dst_Tree => Tree,
782                     Dst_Hint => null,
783                     Src_Node => R_Node,
784                     Dst_Node => Dst_Node);
785                  R_Node := Tree_Operations.Next (R_Node);
786               end loop;
787
788               exit;
789            end if;
790
791            if R_Node = null then
792               while L_Node /= null loop
793                  Insert_With_Hint
794                    (Dst_Tree => Tree,
795                     Dst_Hint => null,
796                     Src_Node => L_Node,
797                     Dst_Node => Dst_Node);
798
799                  L_Node := Tree_Operations.Next (L_Node);
800               end loop;
801
802               exit;
803            end if;
804
805            if Is_Less (L_Node, R_Node) then
806               Insert_With_Hint
807                 (Dst_Tree => Tree,
808                  Dst_Hint => null,
809                  Src_Node => L_Node,
810                  Dst_Node => Dst_Node);
811
812               L_Node := Tree_Operations.Next (L_Node);
813
814            elsif Is_Less (R_Node, L_Node) then
815               Insert_With_Hint
816                 (Dst_Tree => Tree,
817                  Dst_Hint => null,
818                  Src_Node => R_Node,
819                  Dst_Node => Dst_Node);
820
821               R_Node := Tree_Operations.Next (R_Node);
822
823            else
824               L_Node := Tree_Operations.Next (L_Node);
825               R_Node := Tree_Operations.Next (R_Node);
826            end if;
827         end loop;
828
829         BL := BL - 1;
830         LL := LL - 1;
831
832         BR := BR - 1;
833         LR := LR - 1;
834
835         return Tree;
836
837      exception
838         when others =>
839            BL := BL - 1;
840            LL := LL - 1;
841
842            BR := BR - 1;
843            LR := LR - 1;
844
845            Delete_Tree (Tree.Root);
846            raise;
847      end;
848   end Symmetric_Difference;
849
850   -----------
851   -- Union --
852   -----------
853
854   procedure Union (Target : in out Tree_Type; Source : Tree_Type) is
855      Hint : Node_Access;
856
857      procedure Process (Node : Node_Access);
858      pragma Inline (Process);
859
860      procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
861
862      -------------
863      -- Process --
864      -------------
865
866      procedure Process (Node : Node_Access) is
867      begin
868         Insert_With_Hint
869           (Dst_Tree => Target,
870            Dst_Hint => Hint,  -- use node most recently inserted as hint
871            Src_Node => Node,
872            Dst_Node => Hint);
873      end Process;
874
875   --  Start of processing for Union
876
877   begin
878      if Target'Address = Source'Address then
879         return;
880      end if;
881
882      --  Per AI05-0022, the container implementation is required to detect
883      --  element tampering by a generic actual subprogram.
884
885      declare
886         BS : Natural renames Source'Unrestricted_Access.Busy;
887         LS : Natural renames Source'Unrestricted_Access.Lock;
888
889      begin
890         BS := BS + 1;
891         LS := LS + 1;
892
893         Iterate (Source);
894
895         BS := BS - 1;
896         LS := LS - 1;
897
898      exception
899         when others =>
900            BS := BS - 1;
901            LS := LS - 1;
902
903            raise;
904      end;
905   end Union;
906
907   function Union (Left, Right : Tree_Type) return Tree_Type is
908   begin
909      if Left'Address = Right'Address then
910         return Copy (Left);
911      end if;
912
913      if Left.Length = 0 then
914         return Copy (Right);
915      end if;
916
917      if Right.Length = 0 then
918         return Copy (Left);
919      end if;
920
921      declare
922         BL : Natural renames Left'Unrestricted_Access.Busy;
923         LL : Natural renames Left'Unrestricted_Access.Lock;
924
925         BR : Natural renames Right'Unrestricted_Access.Busy;
926         LR : Natural renames Right'Unrestricted_Access.Lock;
927
928         Tree : Tree_Type := Copy (Left);
929
930         Hint : Node_Access;
931
932         procedure Process (Node : Node_Access);
933         pragma Inline (Process);
934
935         procedure Iterate is
936           new Tree_Operations.Generic_Iteration (Process);
937
938         -------------
939         -- Process --
940         -------------
941
942         procedure Process (Node : Node_Access) is
943         begin
944            Insert_With_Hint
945              (Dst_Tree => Tree,
946               Dst_Hint => Hint,  -- use node most recently inserted as hint
947               Src_Node => Node,
948               Dst_Node => Hint);
949         end Process;
950
951      --  Start of processing for Union
952
953      begin
954         BL := BL + 1;
955         LL := LL + 1;
956
957         BR := BR + 1;
958         LR := LR + 1;
959
960         Iterate (Right);
961
962         BL := BL - 1;
963         LL := LL - 1;
964
965         BR := BR - 1;
966         LR := LR - 1;
967
968         return Tree;
969
970      exception
971         when others =>
972            BL := BL - 1;
973            LL := LL - 1;
974
975            BR := BR - 1;
976            LR := LR - 1;
977
978            Delete_Tree (Tree.Root);
979            raise;
980      end;
981   end Union;
982
983end Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
984