Merge from mainline (165734:167278).
[official-gcc/graphite-test-results.git] / gcc / ada / a-rbtgbk.adb
blobb12ae84107627ee85204f06ff0b1c876fe550ab5
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_BOUNDED_KEYS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2010, 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 package body Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys is
32 package Ops renames Tree_Operations;
34 -------------
35 -- Ceiling --
36 -------------
38 -- AKA Lower_Bound
40 function Ceiling
41 (Tree : Tree_Type'Class;
42 Key : Key_Type) return Count_Type
44 Y : Count_Type;
45 X : Count_Type;
46 N : Nodes_Type renames Tree.Nodes;
48 begin
49 Y := 0;
51 X := Tree.Root;
52 while X /= 0 loop
53 if Is_Greater_Key_Node (Key, N (X)) then
54 X := Ops.Right (N (X));
55 else
56 Y := X;
57 X := Ops.Left (N (X));
58 end if;
59 end loop;
61 return Y;
62 end Ceiling;
64 ----------
65 -- Find --
66 ----------
68 function Find
69 (Tree : Tree_Type'Class;
70 Key : Key_Type) return Count_Type
72 Y : Count_Type;
73 X : Count_Type;
74 N : Nodes_Type renames Tree.Nodes;
76 begin
77 Y := 0;
79 X := Tree.Root;
80 while X /= 0 loop
81 if Is_Greater_Key_Node (Key, N (X)) then
82 X := Ops.Right (N (X));
83 else
84 Y := X;
85 X := Ops.Left (N (X));
86 end if;
87 end loop;
89 if Y = 0 then
90 return 0;
91 end if;
93 if Is_Less_Key_Node (Key, N (Y)) then
94 return 0;
95 end if;
97 return Y;
98 end Find;
100 -----------
101 -- Floor --
102 -----------
104 function Floor
105 (Tree : Tree_Type'Class;
106 Key : Key_Type) return Count_Type
108 Y : Count_Type;
109 X : Count_Type;
110 N : Nodes_Type renames Tree.Nodes;
112 begin
113 Y := 0;
115 X := Tree.Root;
116 while X /= 0 loop
117 if Is_Less_Key_Node (Key, N (X)) then
118 X := Ops.Left (N (X));
119 else
120 Y := X;
121 X := Ops.Right (N (X));
122 end if;
123 end loop;
125 return Y;
126 end Floor;
128 --------------------------------
129 -- Generic_Conditional_Insert --
130 --------------------------------
132 procedure Generic_Conditional_Insert
133 (Tree : in out Tree_Type'Class;
134 Key : Key_Type;
135 Node : out Count_Type;
136 Inserted : out Boolean)
138 Y : Count_Type;
139 X : Count_Type;
140 N : Nodes_Type renames Tree.Nodes;
142 begin
143 Y := 0;
145 X := Tree.Root;
146 Inserted := True;
147 while X /= 0 loop
148 Y := X;
149 Inserted := Is_Less_Key_Node (Key, N (X));
150 X := (if Inserted then Ops.Left (N (X)) else Ops.Right (N (X)));
151 end loop;
153 -- If Inserted is True, then this means either that Tree is
154 -- empty, or there was a least one node (strictly) greater than
155 -- Key. Otherwise, it means that Key is equal to or greater than
156 -- every node.
158 if Inserted then
159 if Y = Tree.First then
160 Insert_Post (Tree, Y, True, Node);
161 return;
162 end if;
164 Node := Ops.Previous (Tree, Y);
166 else
167 Node := Y;
168 end if;
170 -- Here Node has a value that is less than or equal to Key. We
171 -- now have to resolve whether Key is equal to or greater than
172 -- Node, which determines whether the insertion succeeds.
174 if Is_Greater_Key_Node (Key, N (Node)) then
175 Insert_Post (Tree, Y, Inserted, Node);
176 Inserted := True;
177 return;
178 end if;
180 Inserted := False;
181 end Generic_Conditional_Insert;
183 ------------------------------------------
184 -- Generic_Conditional_Insert_With_Hint --
185 ------------------------------------------
187 procedure Generic_Conditional_Insert_With_Hint
188 (Tree : in out Tree_Type'Class;
189 Position : Count_Type;
190 Key : Key_Type;
191 Node : out Count_Type;
192 Inserted : out Boolean)
194 N : Nodes_Type renames Tree.Nodes;
196 begin
197 -- The purpose of a hint is to avoid a search from the root of
198 -- tree. If we have it hint it means we only need to traverse the
199 -- subtree rooted at the hint to find the nearest neighbor. Note
200 -- that finding the neighbor means merely walking the tree; this
201 -- is not a search and the only comparisons that occur are with
202 -- the hint and its neighbor.
204 -- If Position is 0, this is interpreted to mean that Key is
205 -- large relative to the nodes in the tree. If the tree is empty,
206 -- or Key is greater than the last node in the tree, then we're
207 -- done; otherwise the hint was "wrong" and we must search.
209 if Position = 0 then -- largest
210 if Tree.Last = 0
211 or else Is_Greater_Key_Node (Key, N (Tree.Last))
212 then
213 Insert_Post (Tree, Tree.Last, False, Node);
214 Inserted := True;
215 else
216 Conditional_Insert_Sans_Hint (Tree, Key, Node, Inserted);
217 end if;
219 return;
220 end if;
222 pragma Assert (Tree.Length > 0);
224 -- A hint can either name the node that immediately follows Key,
225 -- or immediately precedes Key. We first test whether Key is
226 -- less than the hint, and if so we compare Key to the node that
227 -- precedes the hint. If Key is both less than the hint and
228 -- greater than the hint's preceding neighbor, then we're done;
229 -- otherwise we must search.
231 -- Note also that a hint can either be an anterior node or a leaf
232 -- node. A new node is always inserted at the bottom of the tree
233 -- (at least prior to rebalancing), becoming the new left or
234 -- right child of leaf node (which prior to the insertion must
235 -- necessarily be null, since this is a leaf). If the hint names
236 -- an anterior node then its neighbor must be a leaf, and so
237 -- (here) we insert after the neighbor. If the hint names a leaf
238 -- then its neighbor must be anterior and so we insert before the
239 -- hint.
241 if Is_Less_Key_Node (Key, N (Position)) then
242 declare
243 Before : constant Count_Type := Ops.Previous (Tree, Position);
245 begin
246 if Before = 0 then
247 Insert_Post (Tree, Tree.First, True, Node);
248 Inserted := True;
250 elsif Is_Greater_Key_Node (Key, N (Before)) then
251 if Ops.Right (N (Before)) = 0 then
252 Insert_Post (Tree, Before, False, Node);
253 else
254 Insert_Post (Tree, Position, True, Node);
255 end if;
257 Inserted := True;
259 else
260 Conditional_Insert_Sans_Hint (Tree, Key, Node, Inserted);
261 end if;
262 end;
264 return;
265 end if;
267 -- We know that Key isn't less than the hint so we try again,
268 -- this time to see if it's greater than the hint. If so we
269 -- compare Key to the node that follows the hint. If Key is both
270 -- greater than the hint and less than the hint's next neighbor,
271 -- then we're done; otherwise we must search.
273 if Is_Greater_Key_Node (Key, N (Position)) then
274 declare
275 After : constant Count_Type := Ops.Next (Tree, Position);
277 begin
278 if After = 0 then
279 Insert_Post (Tree, Tree.Last, False, Node);
280 Inserted := True;
282 elsif Is_Less_Key_Node (Key, N (After)) then
283 if Ops.Right (N (Position)) = 0 then
284 Insert_Post (Tree, Position, False, Node);
285 else
286 Insert_Post (Tree, After, True, Node);
287 end if;
289 Inserted := True;
291 else
292 Conditional_Insert_Sans_Hint (Tree, Key, Node, Inserted);
293 end if;
294 end;
296 return;
297 end if;
299 -- We know that Key is neither less than the hint nor greater
300 -- than the hint, and that's the definition of equivalence.
301 -- There's nothing else we need to do, since a search would just
302 -- reach the same conclusion.
304 Node := Position;
305 Inserted := False;
306 end Generic_Conditional_Insert_With_Hint;
308 -------------------------
309 -- Generic_Insert_Post --
310 -------------------------
312 procedure Generic_Insert_Post
313 (Tree : in out Tree_Type'Class;
314 Y : Count_Type;
315 Before : Boolean;
316 Z : out Count_Type)
318 N : Nodes_Type renames Tree.Nodes;
320 begin
321 if Tree.Length >= Tree.Capacity then
322 raise Capacity_Error with "not enough capacity to insert new item";
323 end if;
325 if Tree.Busy > 0 then
326 raise Program_Error with
327 "attempt to tamper with cursors (container is busy)";
328 end if;
330 Z := New_Node;
331 pragma Assert (Z /= 0);
333 if Y = 0 then
334 pragma Assert (Tree.Length = 0);
335 pragma Assert (Tree.Root = 0);
336 pragma Assert (Tree.First = 0);
337 pragma Assert (Tree.Last = 0);
339 Tree.Root := Z;
340 Tree.First := Z;
341 Tree.Last := Z;
343 elsif Before then
344 pragma Assert (Ops.Left (N (Y)) = 0);
346 Ops.Set_Left (N (Y), Z);
348 if Y = Tree.First then
349 Tree.First := Z;
350 end if;
352 else
353 pragma Assert (Ops.Right (N (Y)) = 0);
355 Ops.Set_Right (N (Y), Z);
357 if Y = Tree.Last then
358 Tree.Last := Z;
359 end if;
360 end if;
362 Ops.Set_Color (N (Z), Red);
363 Ops.Set_Parent (N (Z), Y);
364 Ops.Rebalance_For_Insert (Tree, Z);
365 Tree.Length := Tree.Length + 1;
366 end Generic_Insert_Post;
368 -----------------------
369 -- Generic_Iteration --
370 -----------------------
372 procedure Generic_Iteration
373 (Tree : Tree_Type'Class;
374 Key : Key_Type)
376 procedure Iterate (Index : Count_Type);
378 -------------
379 -- Iterate --
380 -------------
382 procedure Iterate (Index : Count_Type) is
383 J : Count_Type;
384 N : Nodes_Type renames Tree.Nodes;
386 begin
387 J := Index;
388 while J /= 0 loop
389 if Is_Less_Key_Node (Key, N (J)) then
390 J := Ops.Left (N (J));
391 elsif Is_Greater_Key_Node (Key, N (J)) then
392 J := Ops.Right (N (J));
393 else
394 Iterate (Ops.Left (N (J)));
395 Process (J);
396 J := Ops.Right (N (J));
397 end if;
398 end loop;
399 end Iterate;
401 -- Start of processing for Generic_Iteration
403 begin
404 Iterate (Tree.Root);
405 end Generic_Iteration;
407 -------------------------------
408 -- Generic_Reverse_Iteration --
409 -------------------------------
411 procedure Generic_Reverse_Iteration
412 (Tree : Tree_Type'Class;
413 Key : Key_Type)
415 procedure Iterate (Index : Count_Type);
417 -------------
418 -- Iterate --
419 -------------
421 procedure Iterate (Index : Count_Type) is
422 J : Count_Type;
423 N : Nodes_Type renames Tree.Nodes;
425 begin
426 J := Index;
427 while J /= 0 loop
428 if Is_Less_Key_Node (Key, N (J)) then
429 J := Ops.Left (N (J));
430 elsif Is_Greater_Key_Node (Key, N (J)) then
431 J := Ops.Right (N (J));
432 else
433 Iterate (Ops.Right (N (J)));
434 Process (J);
435 J := Ops.Left (N (J));
436 end if;
437 end loop;
438 end Iterate;
440 -- Start of processing for Generic_Reverse_Iteration
442 begin
443 Iterate (Tree.Root);
444 end Generic_Reverse_Iteration;
446 ----------------------------------
447 -- Generic_Unconditional_Insert --
448 ----------------------------------
450 procedure Generic_Unconditional_Insert
451 (Tree : in out Tree_Type'Class;
452 Key : Key_Type;
453 Node : out Count_Type)
455 Y : Count_Type;
456 X : Count_Type;
457 N : Nodes_Type renames Tree.Nodes;
459 Before : Boolean;
461 begin
462 Y := 0;
463 Before := False;
465 X := Tree.Root;
466 while X /= 0 loop
467 Y := X;
468 Before := Is_Less_Key_Node (Key, N (X));
469 X := (if Before then Ops.Left (N (X)) else Ops.Right (N (X)));
470 end loop;
472 Insert_Post (Tree, Y, Before, Node);
473 end Generic_Unconditional_Insert;
475 --------------------------------------------
476 -- Generic_Unconditional_Insert_With_Hint --
477 --------------------------------------------
479 procedure Generic_Unconditional_Insert_With_Hint
480 (Tree : in out Tree_Type'Class;
481 Hint : Count_Type;
482 Key : Key_Type;
483 Node : out Count_Type)
485 N : Nodes_Type renames Tree.Nodes;
487 begin
488 -- There are fewer constraints for an unconditional insertion
489 -- than for a conditional insertion, since we allow duplicate
490 -- keys. So instead of having to check (say) whether Key is
491 -- (strictly) greater than the hint's previous neighbor, here we
492 -- allow Key to be equal to or greater than the previous node.
494 -- There is the issue of what to do if Key is equivalent to the
495 -- hint. Does the new node get inserted before or after the hint?
496 -- We decide that it gets inserted after the hint, reasoning that
497 -- this is consistent with behavior for non-hint insertion, which
498 -- inserts a new node after existing nodes with equivalent keys.
500 -- First we check whether the hint is null, which is interpreted
501 -- to mean that Key is large relative to existing nodes.
502 -- Following our rule above, if Key is equal to or greater than
503 -- the last node, then we insert the new node immediately after
504 -- last. (We don't have an operation for testing whether a key is
505 -- "equal to or greater than" a node, so we must say instead "not
506 -- less than", which is equivalent.)
508 if Hint = 0 then -- largest
509 if Tree.Last = 0 then
510 Insert_Post (Tree, 0, False, Node);
511 elsif Is_Less_Key_Node (Key, N (Tree.Last)) then
512 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
513 else
514 Insert_Post (Tree, Tree.Last, False, Node);
515 end if;
517 return;
518 end if;
520 pragma Assert (Tree.Length > 0);
522 -- We decide here whether to insert the new node prior to the
523 -- hint. Key could be equivalent to the hint, so in theory we
524 -- could write the following test as "not greater than" (same as
525 -- "less than or equal to"). If Key were equivalent to the hint,
526 -- that would mean that the new node gets inserted before an
527 -- equivalent node. That wouldn't break any container invariants,
528 -- but our rule above says that new nodes always get inserted
529 -- after equivalent nodes. So here we test whether Key is both
530 -- less than the hint and equal to or greater than the hint's
531 -- previous neighbor, and if so insert it before the hint.
533 if Is_Less_Key_Node (Key, N (Hint)) then
534 declare
535 Before : constant Count_Type := Ops.Previous (Tree, Hint);
536 begin
537 if Before = 0 then
538 Insert_Post (Tree, Hint, True, Node);
539 elsif Is_Less_Key_Node (Key, N (Before)) then
540 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
541 elsif Ops.Right (N (Before)) = 0 then
542 Insert_Post (Tree, Before, False, Node);
543 else
544 Insert_Post (Tree, Hint, True, Node);
545 end if;
546 end;
548 return;
549 end if;
551 -- We know that Key isn't less than the hint, so it must be equal
552 -- or greater. So we just test whether Key is less than or equal
553 -- to (same as "not greater than") the hint's next neighbor, and
554 -- if so insert it after the hint.
556 declare
557 After : constant Count_Type := Ops.Next (Tree, Hint);
558 begin
559 if After = 0 then
560 Insert_Post (Tree, Hint, False, Node);
561 elsif Is_Greater_Key_Node (Key, N (After)) then
562 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
563 elsif Ops.Right (N (Hint)) = 0 then
564 Insert_Post (Tree, Hint, False, Node);
565 else
566 Insert_Post (Tree, After, True, Node);
567 end if;
568 end;
569 end Generic_Unconditional_Insert_With_Hint;
571 -----------------
572 -- Upper_Bound --
573 -----------------
575 function Upper_Bound
576 (Tree : Tree_Type'Class;
577 Key : Key_Type) return Count_Type
579 Y : Count_Type;
580 X : Count_Type;
581 N : Nodes_Type renames Tree.Nodes;
583 begin
584 Y := 0;
586 X := Tree.Root;
587 while X /= 0 loop
588 if Is_Less_Key_Node (Key, N (X)) then
589 Y := X;
590 X := Ops.Left (N (X));
591 else
592 X := Ops.Right (N (X));
593 end if;
594 end loop;
596 return Y;
597 end Upper_Bound;
599 end Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;