OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [a-crbtgk.adb] - Blame information for rev 299

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT LIBRARY COMPONENTS                          --
4
--                                                                          --
5
--                ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_KEYS               --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 2004-2009, 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
 
30
package body Ada.Containers.Red_Black_Trees.Generic_Keys is
31
 
32
   package Ops renames Tree_Operations;
33
 
34
   -------------
35
   -- Ceiling --
36
   -------------
37
 
38
   --  AKA Lower_Bound
39
 
40
   function Ceiling (Tree : Tree_Type; Key : Key_Type) return Node_Access is
41
      Y : Node_Access;
42
      X : Node_Access;
43
 
44
   begin
45
      X := Tree.Root;
46
      while X /= null loop
47
         if Is_Greater_Key_Node (Key, X) then
48
            X := Ops.Right (X);
49
         else
50
            Y := X;
51
            X := Ops.Left (X);
52
         end if;
53
      end loop;
54
 
55
      return Y;
56
   end Ceiling;
57
 
58
   ----------
59
   -- Find --
60
   ----------
61
 
62
   function Find (Tree : Tree_Type; Key  : Key_Type) return Node_Access is
63
      Y : Node_Access;
64
      X : Node_Access;
65
 
66
   begin
67
      X := Tree.Root;
68
      while X /= null loop
69
         if Is_Greater_Key_Node (Key, X) then
70
            X := Ops.Right (X);
71
         else
72
            Y := X;
73
            X := Ops.Left (X);
74
         end if;
75
      end loop;
76
 
77
      if Y = null then
78
         return null;
79
      end if;
80
 
81
      if Is_Less_Key_Node (Key, Y) then
82
         return null;
83
      end if;
84
 
85
      return Y;
86
   end Find;
87
 
88
   -----------
89
   -- Floor --
90
   -----------
91
 
92
   function Floor (Tree : Tree_Type; Key  : Key_Type) return Node_Access is
93
      Y : Node_Access;
94
      X : Node_Access;
95
 
96
   begin
97
      X := Tree.Root;
98
      while X /= null loop
99
         if Is_Less_Key_Node (Key, X) then
100
            X := Ops.Left (X);
101
         else
102
            Y := X;
103
            X := Ops.Right (X);
104
         end if;
105
      end loop;
106
 
107
      return Y;
108
   end Floor;
109
 
110
   --------------------------------
111
   -- Generic_Conditional_Insert --
112
   --------------------------------
113
 
114
   procedure Generic_Conditional_Insert
115
     (Tree     : in out Tree_Type;
116
      Key      : Key_Type;
117
      Node     : out Node_Access;
118
      Inserted : out Boolean)
119
   is
120
      Y : Node_Access := null;
121
      X : Node_Access := Tree.Root;
122
 
123
   begin
124
      Inserted := True;
125
      while X /= null loop
126
         Y := X;
127
         Inserted := Is_Less_Key_Node (Key, X);
128
         X := (if Inserted then Ops.Left (X) else Ops.Right (X));
129
      end loop;
130
 
131
      --  If Inserted is True, then this means either that Tree is
132
      --  empty, or there was a least one node (strictly) greater than
133
      --  Key. Otherwise, it means that Key is equal to or greater than
134
      --  every node.
135
 
136
      if Inserted then
137
         if Y = Tree.First then
138
            Insert_Post (Tree, Y, True, Node);
139
            return;
140
         end if;
141
 
142
         Node := Ops.Previous (Y);
143
 
144
      else
145
         Node := Y;
146
      end if;
147
 
148
      --  Here Node has a value that is less than or equal to Key. We
149
      --  now have to resolve whether Key is equal to or greater than
150
      --  Node, which determines whether the insertion succeeds.
151
 
152
      if Is_Greater_Key_Node (Key, Node) then
153
         Insert_Post (Tree, Y, Inserted, Node);
154
         Inserted := True;
155
         return;
156
      end if;
157
 
158
      Inserted := False;
159
   end Generic_Conditional_Insert;
160
 
161
   ------------------------------------------
162
   -- Generic_Conditional_Insert_With_Hint --
163
   ------------------------------------------
164
 
165
   procedure Generic_Conditional_Insert_With_Hint
166
     (Tree      : in out Tree_Type;
167
      Position  : Node_Access;
168
      Key       : Key_Type;
169
      Node      : out Node_Access;
170
      Inserted  : out Boolean)
171
   is
172
   begin
173
      --  The purpose of a hint is to avoid a search from the root of
174
      --  tree. If we have it hint it means we only need to traverse the
175
      --  subtree rooted at the hint to find the nearest neighbor. Note
176
      --  that finding the neighbor means merely walking the tree; this
177
      --  is not a search and the only comparisons that occur are with
178
      --  the hint and its neighbor.
179
 
180
      --  If Position is null, this is interpreted to mean that Key is
181
      --  large relative to the nodes in the tree. If the tree is empty,
182
      --  or Key is greater than the last node in the tree, then we're
183
      --  done; otherwise the hint was "wrong" and we must search.
184
 
185
      if Position = null then  -- largest
186
         if Tree.Last = null
187
           or else Is_Greater_Key_Node (Key, Tree.Last)
188
         then
189
            Insert_Post (Tree, Tree.Last, False, Node);
190
            Inserted := True;
191
         else
192
            Conditional_Insert_Sans_Hint (Tree, Key, Node, Inserted);
193
         end if;
194
 
195
         return;
196
      end if;
197
 
198
      pragma Assert (Tree.Length > 0);
199
 
200
      --  A hint can either name the node that immediately follows Key,
201
      --  or immediately precedes Key. We first test whether Key is
202
      --  less than the hint, and if so we compare Key to the node that
203
      --  precedes the hint. If Key is both less than the hint and
204
      --  greater than the hint's preceding neighbor, then we're done;
205
      --  otherwise we must search.
206
 
207
      --  Note also that a hint can either be an anterior node or a leaf
208
      --  node. A new node is always inserted at the bottom of the tree
209
      --  (at least prior to rebalancing), becoming the new left or
210
      --  right child of leaf node (which prior to the insertion must
211
      --  necessarily be null, since this is a leaf). If the hint names
212
      --  an anterior node then its neighbor must be a leaf, and so
213
      --  (here) we insert after the neighbor. If the hint names a leaf
214
      --  then its neighbor must be anterior and so we insert before the
215
      --  hint.
216
 
217
      if Is_Less_Key_Node (Key, Position) then
218
         declare
219
            Before : constant Node_Access := Ops.Previous (Position);
220
 
221
         begin
222
            if Before = null then
223
               Insert_Post (Tree, Tree.First, True, Node);
224
               Inserted := True;
225
 
226
            elsif Is_Greater_Key_Node (Key, Before) then
227
               if Ops.Right (Before) = null then
228
                  Insert_Post (Tree, Before, False, Node);
229
               else
230
                  Insert_Post (Tree, Position, True, Node);
231
               end if;
232
 
233
               Inserted := True;
234
 
235
            else
236
               Conditional_Insert_Sans_Hint (Tree, Key, Node, Inserted);
237
            end if;
238
         end;
239
 
240
         return;
241
      end if;
242
 
243
      --  We know that Key isn't less than the hint so we try again,
244
      --  this time to see if it's greater than the hint. If so we
245
      --  compare Key to the node that follows the hint. If Key is both
246
      --  greater than the hint and less than the hint's next neighbor,
247
      --  then we're done; otherwise we must search.
248
 
249
      if Is_Greater_Key_Node (Key, Position) then
250
         declare
251
            After : constant Node_Access := Ops.Next (Position);
252
 
253
         begin
254
            if After = null then
255
               Insert_Post (Tree, Tree.Last, False, Node);
256
               Inserted := True;
257
 
258
            elsif Is_Less_Key_Node (Key, After) then
259
               if Ops.Right (Position) = null then
260
                  Insert_Post (Tree, Position, False, Node);
261
               else
262
                  Insert_Post (Tree, After, True, Node);
263
               end if;
264
 
265
               Inserted := True;
266
 
267
            else
268
               Conditional_Insert_Sans_Hint (Tree, Key, Node, Inserted);
269
            end if;
270
         end;
271
 
272
         return;
273
      end if;
274
 
275
      --  We know that Key is neither less than the hint nor greater
276
      --  than the hint, and that's the definition of equivalence.
277
      --  There's nothing else we need to do, since a search would just
278
      --  reach the same conclusion.
279
 
280
      Node := Position;
281
      Inserted := False;
282
   end Generic_Conditional_Insert_With_Hint;
283
 
284
   -------------------------
285
   -- Generic_Insert_Post --
286
   -------------------------
287
 
288
   procedure Generic_Insert_Post
289
     (Tree   : in out Tree_Type;
290
      Y      : Node_Access;
291
      Before : Boolean;
292
      Z      : out Node_Access)
293
   is
294
   begin
295
      if Tree.Length = Count_Type'Last then
296
         raise Constraint_Error with "too many elements";
297
      end if;
298
 
299
      if Tree.Busy > 0 then
300
         raise Program_Error with
301
           "attempt to tamper with cursors (container is busy)";
302
      end if;
303
 
304
      Z := New_Node;
305
      pragma Assert (Z /= null);
306
      pragma Assert (Ops.Color (Z) = Red);
307
 
308
      if Y = null then
309
         pragma Assert (Tree.Length = 0);
310
         pragma Assert (Tree.Root = null);
311
         pragma Assert (Tree.First = null);
312
         pragma Assert (Tree.Last = null);
313
 
314
         Tree.Root := Z;
315
         Tree.First := Z;
316
         Tree.Last := Z;
317
 
318
      elsif Before then
319
         pragma Assert (Ops.Left (Y) = null);
320
 
321
         Ops.Set_Left (Y, Z);
322
 
323
         if Y = Tree.First then
324
            Tree.First := Z;
325
         end if;
326
 
327
      else
328
         pragma Assert (Ops.Right (Y) = null);
329
 
330
         Ops.Set_Right (Y, Z);
331
 
332
         if Y = Tree.Last then
333
            Tree.Last := Z;
334
         end if;
335
      end if;
336
 
337
      Ops.Set_Parent (Z, Y);
338
      Ops.Rebalance_For_Insert (Tree, Z);
339
      Tree.Length := Tree.Length + 1;
340
   end Generic_Insert_Post;
341
 
342
   -----------------------
343
   -- Generic_Iteration --
344
   -----------------------
345
 
346
   procedure Generic_Iteration
347
     (Tree : Tree_Type;
348
      Key  : Key_Type)
349
   is
350
      procedure Iterate (Node : Node_Access);
351
 
352
      -------------
353
      -- Iterate --
354
      -------------
355
 
356
      procedure Iterate (Node : Node_Access) is
357
         N : Node_Access;
358
      begin
359
         N := Node;
360
         while N /= null loop
361
            if Is_Less_Key_Node (Key, N) then
362
               N := Ops.Left (N);
363
            elsif Is_Greater_Key_Node (Key, N) then
364
               N := Ops.Right (N);
365
            else
366
               Iterate (Ops.Left (N));
367
               Process (N);
368
               N := Ops.Right (N);
369
            end if;
370
         end loop;
371
      end Iterate;
372
 
373
   --  Start of processing for Generic_Iteration
374
 
375
   begin
376
      Iterate (Tree.Root);
377
   end Generic_Iteration;
378
 
379
   -------------------------------
380
   -- Generic_Reverse_Iteration --
381
   -------------------------------
382
 
383
   procedure Generic_Reverse_Iteration
384
     (Tree : Tree_Type;
385
      Key  : Key_Type)
386
   is
387
      procedure Iterate (Node : Node_Access);
388
 
389
      -------------
390
      -- Iterate --
391
      -------------
392
 
393
      procedure Iterate (Node : Node_Access) is
394
         N : Node_Access;
395
      begin
396
         N := Node;
397
         while N /= null loop
398
            if Is_Less_Key_Node (Key, N) then
399
               N := Ops.Left (N);
400
            elsif Is_Greater_Key_Node (Key, N) then
401
               N := Ops.Right (N);
402
            else
403
               Iterate (Ops.Right (N));
404
               Process (N);
405
               N := Ops.Left (N);
406
            end if;
407
         end loop;
408
      end Iterate;
409
 
410
   --  Start of processing for Generic_Reverse_Iteration
411
 
412
   begin
413
      Iterate (Tree.Root);
414
   end Generic_Reverse_Iteration;
415
 
416
   ----------------------------------
417
   -- Generic_Unconditional_Insert --
418
   ----------------------------------
419
 
420
   procedure Generic_Unconditional_Insert
421
     (Tree : in out Tree_Type;
422
      Key  : Key_Type;
423
      Node : out Node_Access)
424
   is
425
      Y : Node_Access;
426
      X : Node_Access;
427
 
428
      Before : Boolean;
429
 
430
   begin
431
      Y := null;
432
      Before := False;
433
 
434
      X := Tree.Root;
435
      while X /= null loop
436
         Y := X;
437
         Before := Is_Less_Key_Node (Key, X);
438
         X := (if Before then Ops.Left (X) else Ops.Right (X));
439
      end loop;
440
 
441
      Insert_Post (Tree, Y, Before, Node);
442
   end Generic_Unconditional_Insert;
443
 
444
   --------------------------------------------
445
   -- Generic_Unconditional_Insert_With_Hint --
446
   --------------------------------------------
447
 
448
   procedure Generic_Unconditional_Insert_With_Hint
449
     (Tree : in out Tree_Type;
450
      Hint : Node_Access;
451
      Key  : Key_Type;
452
      Node : out Node_Access)
453
   is
454
   begin
455
      --  There are fewer constraints for an unconditional insertion
456
      --  than for a conditional insertion, since we allow duplicate
457
      --  keys. So instead of having to check (say) whether Key is
458
      --  (strictly) greater than the hint's previous neighbor, here we
459
      --  allow Key to be equal to or greater than the previous node.
460
 
461
      --  There is the issue of what to do if Key is equivalent to the
462
      --  hint. Does the new node get inserted before or after the hint?
463
      --  We decide that it gets inserted after the hint, reasoning that
464
      --  this is consistent with behavior for non-hint insertion, which
465
      --  inserts a new node after existing nodes with equivalent keys.
466
 
467
      --  First we check whether the hint is null, which is interpreted
468
      --  to mean that Key is large relative to existing nodes.
469
      --  Following our rule above, if Key is equal to or greater than
470
      --  the last node, then we insert the new node immediately after
471
      --  last. (We don't have an operation for testing whether a key is
472
      --  "equal to or greater than" a node, so we must say instead "not
473
      --  less than", which is equivalent.)
474
 
475
      if Hint = null then  -- largest
476
         if Tree.Last = null then
477
            Insert_Post (Tree, null, False, Node);
478
         elsif Is_Less_Key_Node (Key, Tree.Last) then
479
            Unconditional_Insert_Sans_Hint (Tree, Key, Node);
480
         else
481
            Insert_Post (Tree, Tree.Last, False, Node);
482
         end if;
483
 
484
         return;
485
      end if;
486
 
487
      pragma Assert (Tree.Length > 0);
488
 
489
      --  We decide here whether to insert the new node prior to the
490
      --  hint. Key could be equivalent to the hint, so in theory we
491
      --  could write the following test as "not greater than" (same as
492
      --  "less than or equal to"). If Key were equivalent to the hint,
493
      --  that would mean that the new node gets inserted before an
494
      --  equivalent node. That wouldn't break any container invariants,
495
      --  but our rule above says that new nodes always get inserted
496
      --  after equivalent nodes. So here we test whether Key is both
497
      --  less than the hint and equal to or greater than the hint's
498
      --  previous neighbor, and if so insert it before the hint.
499
 
500
      if Is_Less_Key_Node (Key, Hint) then
501
         declare
502
            Before : constant Node_Access := Ops.Previous (Hint);
503
         begin
504
            if Before = null then
505
               Insert_Post (Tree, Hint, True, Node);
506
            elsif Is_Less_Key_Node (Key, Before) then
507
               Unconditional_Insert_Sans_Hint (Tree, Key, Node);
508
            elsif Ops.Right (Before) = null then
509
               Insert_Post (Tree, Before, False, Node);
510
            else
511
               Insert_Post (Tree, Hint, True, Node);
512
            end if;
513
         end;
514
 
515
         return;
516
      end if;
517
 
518
      --  We know that Key isn't less than the hint, so it must be equal
519
      --  or greater. So we just test whether Key is less than or equal
520
      --  to (same as "not greater than") the hint's next neighbor, and
521
      --  if so insert it after the hint.
522
 
523
      declare
524
         After : constant Node_Access := Ops.Next (Hint);
525
      begin
526
         if After = null then
527
            Insert_Post (Tree, Hint, False, Node);
528
         elsif Is_Greater_Key_Node (Key, After) then
529
            Unconditional_Insert_Sans_Hint (Tree, Key, Node);
530
         elsif Ops.Right (Hint) = null then
531
            Insert_Post (Tree, Hint, False, Node);
532
         else
533
            Insert_Post (Tree, After, True, Node);
534
         end if;
535
      end;
536
   end Generic_Unconditional_Insert_With_Hint;
537
 
538
   -----------------
539
   -- Upper_Bound --
540
   -----------------
541
 
542
   function Upper_Bound
543
     (Tree : Tree_Type;
544
      Key  : Key_Type) return Node_Access
545
   is
546
      Y : Node_Access;
547
      X : Node_Access;
548
 
549
   begin
550
      X := Tree.Root;
551
      while X /= null loop
552
         if Is_Less_Key_Node (Key, X) then
553
            Y := X;
554
            X := Ops.Left (X);
555
         else
556
            X := Ops.Right (X);
557
         end if;
558
      end loop;
559
 
560
      return Y;
561
   end Upper_Bound;
562
 
563
end Ada.Containers.Red_Black_Trees.Generic_Keys;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.