1------------------------------------------------------------------------------ 2-- -- 3-- GNAT LIBRARY COMPONENTS -- 4-- -- 5-- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_BOUNDED_OPERATIONS -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 2004-2019, 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-- The references in this file to "CLR" refer to the following book, from 31-- which several of the algorithms here were adapted: 32 33-- Introduction to Algorithms 34-- by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest 35-- Publisher: The MIT Press (June 18, 1990) 36-- ISBN: 0262031418 37 38with System; use type System.Address; 39 40package body Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations is 41 42 pragma Warnings (Off, "variable ""Busy*"" is not referenced"); 43 pragma Warnings (Off, "variable ""Lock*"" is not referenced"); 44 -- See comment in Ada.Containers.Helpers 45 46 ----------------------- 47 -- Local Subprograms -- 48 ----------------------- 49 50 procedure Delete_Fixup (Tree : in out Tree_Type'Class; Node : Count_Type); 51 procedure Delete_Swap (Tree : in out Tree_Type'Class; Z, Y : Count_Type); 52 53 procedure Left_Rotate (Tree : in out Tree_Type'Class; X : Count_Type); 54 procedure Right_Rotate (Tree : in out Tree_Type'Class; Y : Count_Type); 55 56 ---------------- 57 -- Clear_Tree -- 58 ---------------- 59 60 procedure Clear_Tree (Tree : in out Tree_Type'Class) is 61 begin 62 TC_Check (Tree.TC); 63 64 Tree.First := 0; 65 Tree.Last := 0; 66 Tree.Root := 0; 67 Tree.Length := 0; 68 Tree.Free := -1; 69 end Clear_Tree; 70 71 ------------------ 72 -- Delete_Fixup -- 73 ------------------ 74 75 procedure Delete_Fixup 76 (Tree : in out Tree_Type'Class; 77 Node : Count_Type) 78 is 79 -- CLR p. 274 80 81 X : Count_Type; 82 W : Count_Type; 83 N : Nodes_Type renames Tree.Nodes; 84 85 begin 86 X := Node; 87 while X /= Tree.Root and then Color (N (X)) = Black loop 88 if X = Left (N (Parent (N (X)))) then 89 W := Right (N (Parent (N (X)))); 90 91 if Color (N (W)) = Red then 92 Set_Color (N (W), Black); 93 Set_Color (N (Parent (N (X))), Red); 94 Left_Rotate (Tree, Parent (N (X))); 95 W := Right (N (Parent (N (X)))); 96 end if; 97 98 if (Left (N (W)) = 0 or else Color (N (Left (N (W)))) = Black) 99 and then 100 (Right (N (W)) = 0 or else Color (N (Right (N (W)))) = Black) 101 then 102 Set_Color (N (W), Red); 103 X := Parent (N (X)); 104 105 else 106 if Right (N (W)) = 0 107 or else Color (N (Right (N (W)))) = Black 108 then 109 -- As a condition for setting the color of the left child to 110 -- black, the left child access value must be non-null. A 111 -- truth table analysis shows that if we arrive here, that 112 -- condition holds, so there's no need for an explicit test. 113 -- The assertion is here to document what we know is true. 114 115 pragma Assert (Left (N (W)) /= 0); 116 Set_Color (N (Left (N (W))), Black); 117 118 Set_Color (N (W), Red); 119 Right_Rotate (Tree, W); 120 W := Right (N (Parent (N (X)))); 121 end if; 122 123 Set_Color (N (W), Color (N (Parent (N (X))))); 124 Set_Color (N (Parent (N (X))), Black); 125 Set_Color (N (Right (N (W))), Black); 126 Left_Rotate (Tree, Parent (N (X))); 127 X := Tree.Root; 128 end if; 129 130 else 131 pragma Assert (X = Right (N (Parent (N (X))))); 132 133 W := Left (N (Parent (N (X)))); 134 135 if Color (N (W)) = Red then 136 Set_Color (N (W), Black); 137 Set_Color (N (Parent (N (X))), Red); 138 Right_Rotate (Tree, Parent (N (X))); 139 W := Left (N (Parent (N (X)))); 140 end if; 141 142 if (Left (N (W)) = 0 or else Color (N (Left (N (W)))) = Black) 143 and then 144 (Right (N (W)) = 0 or else Color (N (Right (N (W)))) = Black) 145 then 146 Set_Color (N (W), Red); 147 X := Parent (N (X)); 148 149 else 150 if Left (N (W)) = 0 151 or else Color (N (Left (N (W)))) = Black 152 then 153 -- As a condition for setting the color of the right child 154 -- to black, the right child access value must be non-null. 155 -- A truth table analysis shows that if we arrive here, that 156 -- condition holds, so there's no need for an explicit test. 157 -- The assertion is here to document what we know is true. 158 159 pragma Assert (Right (N (W)) /= 0); 160 Set_Color (N (Right (N (W))), Black); 161 162 Set_Color (N (W), Red); 163 Left_Rotate (Tree, W); 164 W := Left (N (Parent (N (X)))); 165 end if; 166 167 Set_Color (N (W), Color (N (Parent (N (X))))); 168 Set_Color (N (Parent (N (X))), Black); 169 Set_Color (N (Left (N (W))), Black); 170 Right_Rotate (Tree, Parent (N (X))); 171 X := Tree.Root; 172 end if; 173 end if; 174 end loop; 175 176 Set_Color (N (X), Black); 177 end Delete_Fixup; 178 179 --------------------------- 180 -- Delete_Node_Sans_Free -- 181 --------------------------- 182 183 procedure Delete_Node_Sans_Free 184 (Tree : in out Tree_Type'Class; 185 Node : Count_Type) 186 is 187 -- CLR p. 273 188 189 X, Y : Count_Type; 190 191 Z : constant Count_Type := Node; 192 193 N : Nodes_Type renames Tree.Nodes; 194 195 begin 196 TC_Check (Tree.TC); 197 198 -- If node is not present, return (exception will be raised in caller) 199 200 if Z = 0 then 201 return; 202 end if; 203 204 pragma Assert (Tree.Length > 0); 205 pragma Assert (Tree.Root /= 0); 206 pragma Assert (Tree.First /= 0); 207 pragma Assert (Tree.Last /= 0); 208 pragma Assert (Parent (N (Tree.Root)) = 0); 209 210 pragma Assert ((Tree.Length > 1) 211 or else (Tree.First = Tree.Last 212 and then Tree.First = Tree.Root)); 213 214 pragma Assert ((Left (N (Node)) = 0) 215 or else (Parent (N (Left (N (Node)))) = Node)); 216 217 pragma Assert ((Right (N (Node)) = 0) 218 or else (Parent (N (Right (N (Node)))) = Node)); 219 220 pragma Assert (((Parent (N (Node)) = 0) and then (Tree.Root = Node)) 221 or else ((Parent (N (Node)) /= 0) and then 222 ((Left (N (Parent (N (Node)))) = Node) 223 or else 224 (Right (N (Parent (N (Node)))) = Node)))); 225 226 if Left (N (Z)) = 0 then 227 if Right (N (Z)) = 0 then 228 if Z = Tree.First then 229 Tree.First := Parent (N (Z)); 230 end if; 231 232 if Z = Tree.Last then 233 Tree.Last := Parent (N (Z)); 234 end if; 235 236 if Color (N (Z)) = Black then 237 Delete_Fixup (Tree, Z); 238 end if; 239 240 pragma Assert (Left (N (Z)) = 0); 241 pragma Assert (Right (N (Z)) = 0); 242 243 if Z = Tree.Root then 244 pragma Assert (Tree.Length = 1); 245 pragma Assert (Parent (N (Z)) = 0); 246 Tree.Root := 0; 247 elsif Z = Left (N (Parent (N (Z)))) then 248 Set_Left (N (Parent (N (Z))), 0); 249 else 250 pragma Assert (Z = Right (N (Parent (N (Z))))); 251 Set_Right (N (Parent (N (Z))), 0); 252 end if; 253 254 else 255 pragma Assert (Z /= Tree.Last); 256 257 X := Right (N (Z)); 258 259 if Z = Tree.First then 260 Tree.First := Min (Tree, X); 261 end if; 262 263 if Z = Tree.Root then 264 Tree.Root := X; 265 elsif Z = Left (N (Parent (N (Z)))) then 266 Set_Left (N (Parent (N (Z))), X); 267 else 268 pragma Assert (Z = Right (N (Parent (N (Z))))); 269 Set_Right (N (Parent (N (Z))), X); 270 end if; 271 272 Set_Parent (N (X), Parent (N (Z))); 273 274 if Color (N (Z)) = Black then 275 Delete_Fixup (Tree, X); 276 end if; 277 end if; 278 279 elsif Right (N (Z)) = 0 then 280 pragma Assert (Z /= Tree.First); 281 282 X := Left (N (Z)); 283 284 if Z = Tree.Last then 285 Tree.Last := Max (Tree, X); 286 end if; 287 288 if Z = Tree.Root then 289 Tree.Root := X; 290 elsif Z = Left (N (Parent (N (Z)))) then 291 Set_Left (N (Parent (N (Z))), X); 292 else 293 pragma Assert (Z = Right (N (Parent (N (Z))))); 294 Set_Right (N (Parent (N (Z))), X); 295 end if; 296 297 Set_Parent (N (X), Parent (N (Z))); 298 299 if Color (N (Z)) = Black then 300 Delete_Fixup (Tree, X); 301 end if; 302 303 else 304 pragma Assert (Z /= Tree.First); 305 pragma Assert (Z /= Tree.Last); 306 307 Y := Next (Tree, Z); 308 pragma Assert (Left (N (Y)) = 0); 309 310 X := Right (N (Y)); 311 312 if X = 0 then 313 if Y = Left (N (Parent (N (Y)))) then 314 pragma Assert (Parent (N (Y)) /= Z); 315 Delete_Swap (Tree, Z, Y); 316 Set_Left (N (Parent (N (Z))), Z); 317 318 else 319 pragma Assert (Y = Right (N (Parent (N (Y))))); 320 pragma Assert (Parent (N (Y)) = Z); 321 Set_Parent (N (Y), Parent (N (Z))); 322 323 if Z = Tree.Root then 324 Tree.Root := Y; 325 elsif Z = Left (N (Parent (N (Z)))) then 326 Set_Left (N (Parent (N (Z))), Y); 327 else 328 pragma Assert (Z = Right (N (Parent (N (Z))))); 329 Set_Right (N (Parent (N (Z))), Y); 330 end if; 331 332 Set_Left (N (Y), Left (N (Z))); 333 Set_Parent (N (Left (N (Y))), Y); 334 Set_Right (N (Y), Z); 335 336 Set_Parent (N (Z), Y); 337 Set_Left (N (Z), 0); 338 Set_Right (N (Z), 0); 339 340 declare 341 Y_Color : constant Color_Type := Color (N (Y)); 342 begin 343 Set_Color (N (Y), Color (N (Z))); 344 Set_Color (N (Z), Y_Color); 345 end; 346 end if; 347 348 if Color (N (Z)) = Black then 349 Delete_Fixup (Tree, Z); 350 end if; 351 352 pragma Assert (Left (N (Z)) = 0); 353 pragma Assert (Right (N (Z)) = 0); 354 355 if Z = Right (N (Parent (N (Z)))) then 356 Set_Right (N (Parent (N (Z))), 0); 357 else 358 pragma Assert (Z = Left (N (Parent (N (Z))))); 359 Set_Left (N (Parent (N (Z))), 0); 360 end if; 361 362 else 363 if Y = Left (N (Parent (N (Y)))) then 364 pragma Assert (Parent (N (Y)) /= Z); 365 366 Delete_Swap (Tree, Z, Y); 367 368 Set_Left (N (Parent (N (Z))), X); 369 Set_Parent (N (X), Parent (N (Z))); 370 371 else 372 pragma Assert (Y = Right (N (Parent (N (Y))))); 373 pragma Assert (Parent (N (Y)) = Z); 374 375 Set_Parent (N (Y), Parent (N (Z))); 376 377 if Z = Tree.Root then 378 Tree.Root := Y; 379 elsif Z = Left (N (Parent (N (Z)))) then 380 Set_Left (N (Parent (N (Z))), Y); 381 else 382 pragma Assert (Z = Right (N (Parent (N (Z))))); 383 Set_Right (N (Parent (N (Z))), Y); 384 end if; 385 386 Set_Left (N (Y), Left (N (Z))); 387 Set_Parent (N (Left (N (Y))), Y); 388 389 declare 390 Y_Color : constant Color_Type := Color (N (Y)); 391 begin 392 Set_Color (N (Y), Color (N (Z))); 393 Set_Color (N (Z), Y_Color); 394 end; 395 end if; 396 397 if Color (N (Z)) = Black then 398 Delete_Fixup (Tree, X); 399 end if; 400 end if; 401 end if; 402 403 Tree.Length := Tree.Length - 1; 404 end Delete_Node_Sans_Free; 405 406 ----------------- 407 -- Delete_Swap -- 408 ----------------- 409 410 procedure Delete_Swap 411 (Tree : in out Tree_Type'Class; 412 Z, Y : Count_Type) 413 is 414 N : Nodes_Type renames Tree.Nodes; 415 416 pragma Assert (Z /= Y); 417 pragma Assert (Parent (N (Y)) /= Z); 418 419 Y_Parent : constant Count_Type := Parent (N (Y)); 420 Y_Color : constant Color_Type := Color (N (Y)); 421 422 begin 423 Set_Parent (N (Y), Parent (N (Z))); 424 Set_Left (N (Y), Left (N (Z))); 425 Set_Right (N (Y), Right (N (Z))); 426 Set_Color (N (Y), Color (N (Z))); 427 428 if Tree.Root = Z then 429 Tree.Root := Y; 430 elsif Right (N (Parent (N (Y)))) = Z then 431 Set_Right (N (Parent (N (Y))), Y); 432 else 433 pragma Assert (Left (N (Parent (N (Y)))) = Z); 434 Set_Left (N (Parent (N (Y))), Y); 435 end if; 436 437 if Right (N (Y)) /= 0 then 438 Set_Parent (N (Right (N (Y))), Y); 439 end if; 440 441 if Left (N (Y)) /= 0 then 442 Set_Parent (N (Left (N (Y))), Y); 443 end if; 444 445 Set_Parent (N (Z), Y_Parent); 446 Set_Color (N (Z), Y_Color); 447 Set_Left (N (Z), 0); 448 Set_Right (N (Z), 0); 449 end Delete_Swap; 450 451 ---------- 452 -- Free -- 453 ---------- 454 455 procedure Free (Tree : in out Tree_Type'Class; X : Count_Type) is 456 pragma Assert (X > 0); 457 pragma Assert (X <= Tree.Capacity); 458 459 N : Nodes_Type renames Tree.Nodes; 460 -- pragma Assert (N (X).Prev >= 0); -- node is active 461 -- Find a way to mark a node as active vs. inactive; we could 462 -- use a special value in Color_Type for this. ??? 463 464 begin 465 -- The set container actually contains two data structures: a list for 466 -- the "active" nodes that contain elements that have been inserted 467 -- onto the tree, and another for the "inactive" nodes of the free 468 -- store. 469 -- 470 -- We desire that merely declaring an object should have only minimal 471 -- cost; specially, we want to avoid having to initialize the free 472 -- store (to fill in the links), especially if the capacity is large. 473 -- 474 -- The head of the free list is indicated by Container.Free. If its 475 -- value is non-negative, then the free store has been initialized 476 -- in the "normal" way: Container.Free points to the head of the list 477 -- of free (inactive) nodes, and the value 0 means the free list is 478 -- empty. Each node on the free list has been initialized to point 479 -- to the next free node (via its Parent component), and the value 0 480 -- means that this is the last free node. 481 -- 482 -- If Container.Free is negative, then the links on the free store 483 -- have not been initialized. In this case the link values are 484 -- implied: the free store comprises the components of the node array 485 -- started with the absolute value of Container.Free, and continuing 486 -- until the end of the array (Nodes'Last). 487 -- 488 -- ??? 489 -- It might be possible to perform an optimization here. Suppose that 490 -- the free store can be represented as having two parts: one 491 -- comprising the non-contiguous inactive nodes linked together 492 -- in the normal way, and the other comprising the contiguous 493 -- inactive nodes (that are not linked together, at the end of the 494 -- nodes array). This would allow us to never have to initialize 495 -- the free store, except in a lazy way as nodes become inactive. 496 497 -- When an element is deleted from the list container, its node 498 -- becomes inactive, and so we set its Prev component to a negative 499 -- value, to indicate that it is now inactive. This provides a useful 500 -- way to detect a dangling cursor reference. 501 502 -- The comment above is incorrect; we need some other way to 503 -- indicate a node is inactive, for example by using a special 504 -- Color_Type value. ??? 505 -- N (X).Prev := -1; -- Node is deallocated (not on active list) 506 507 if Tree.Free >= 0 then 508 -- The free store has previously been initialized. All we need to 509 -- do here is link the newly-free'd node onto the free list. 510 511 Set_Parent (N (X), Tree.Free); 512 Tree.Free := X; 513 514 elsif X + 1 = abs Tree.Free then 515 -- The free store has not been initialized, and the node becoming 516 -- inactive immediately precedes the start of the free store. All 517 -- we need to do is move the start of the free store back by one. 518 519 Tree.Free := Tree.Free + 1; 520 521 else 522 -- The free store has not been initialized, and the node becoming 523 -- inactive does not immediately precede the free store. Here we 524 -- first initialize the free store (meaning the links are given 525 -- values in the traditional way), and then link the newly-free'd 526 -- node onto the head of the free store. 527 528 -- ??? 529 -- See the comments above for an optimization opportunity. If the 530 -- next link for a node on the free store is negative, then this 531 -- means the remaining nodes on the free store are physically 532 -- contiguous, starting as the absolute value of that index value. 533 534 Tree.Free := abs Tree.Free; 535 536 if Tree.Free > Tree.Capacity then 537 Tree.Free := 0; 538 539 else 540 for I in Tree.Free .. Tree.Capacity - 1 loop 541 Set_Parent (N (I), I + 1); 542 end loop; 543 544 Set_Parent (N (Tree.Capacity), 0); 545 end if; 546 547 Set_Parent (N (X), Tree.Free); 548 Tree.Free := X; 549 end if; 550 end Free; 551 552 ----------------------- 553 -- Generic_Allocate -- 554 ----------------------- 555 556 procedure Generic_Allocate 557 (Tree : in out Tree_Type'Class; 558 Node : out Count_Type) 559 is 560 N : Nodes_Type renames Tree.Nodes; 561 562 begin 563 if Tree.Free >= 0 then 564 Node := Tree.Free; 565 566 -- We always perform the assignment first, before we 567 -- change container state, in order to defend against 568 -- exceptions duration assignment. 569 570 Set_Element (N (Node)); 571 Tree.Free := Parent (N (Node)); 572 573 else 574 -- A negative free store value means that the links of the nodes 575 -- in the free store have not been initialized. In this case, the 576 -- nodes are physically contiguous in the array, starting at the 577 -- index that is the absolute value of the Container.Free, and 578 -- continuing until the end of the array (Nodes'Last). 579 580 Node := abs Tree.Free; 581 582 -- As above, we perform this assignment first, before modifying 583 -- any container state. 584 585 Set_Element (N (Node)); 586 Tree.Free := Tree.Free - 1; 587 end if; 588 589 -- When a node is allocated from the free store, its pointer components 590 -- (the links to other nodes in the tree) must also be initialized (to 591 -- 0, the equivalent of null). This simplifies the post-allocation 592 -- handling of nodes inserted into terminal positions. 593 594 Set_Parent (N (Node), Parent => 0); 595 Set_Left (N (Node), Left => 0); 596 Set_Right (N (Node), Right => 0); 597 end Generic_Allocate; 598 599 ------------------- 600 -- Generic_Equal -- 601 ------------------- 602 603 function Generic_Equal (Left, Right : Tree_Type'Class) return Boolean is 604 -- Per AI05-0022, the container implementation is required to detect 605 -- element tampering by a generic actual subprogram. 606 607 Lock_Left : With_Lock (Left.TC'Unrestricted_Access); 608 Lock_Right : With_Lock (Right.TC'Unrestricted_Access); 609 610 L_Node : Count_Type; 611 R_Node : Count_Type; 612 613 begin 614 if Left'Address = Right'Address then 615 return True; 616 end if; 617 618 if Left.Length /= Right.Length then 619 return False; 620 end if; 621 622 -- If the containers are empty, return a result immediately, so as to 623 -- not manipulate the tamper bits unnecessarily. 624 625 if Left.Length = 0 then 626 return True; 627 end if; 628 629 L_Node := Left.First; 630 R_Node := Right.First; 631 while L_Node /= 0 loop 632 if not Is_Equal (Left.Nodes (L_Node), Right.Nodes (R_Node)) then 633 return False; 634 end if; 635 636 L_Node := Next (Left, L_Node); 637 R_Node := Next (Right, R_Node); 638 end loop; 639 640 return True; 641 end Generic_Equal; 642 643 ----------------------- 644 -- Generic_Iteration -- 645 ----------------------- 646 647 procedure Generic_Iteration (Tree : Tree_Type'Class) is 648 procedure Iterate (P : Count_Type); 649 650 ------------- 651 -- Iterate -- 652 ------------- 653 654 procedure Iterate (P : Count_Type) is 655 X : Count_Type := P; 656 begin 657 while X /= 0 loop 658 Iterate (Left (Tree.Nodes (X))); 659 Process (X); 660 X := Right (Tree.Nodes (X)); 661 end loop; 662 end Iterate; 663 664 -- Start of processing for Generic_Iteration 665 666 begin 667 Iterate (Tree.Root); 668 end Generic_Iteration; 669 670 ------------------ 671 -- Generic_Read -- 672 ------------------ 673 674 procedure Generic_Read 675 (Stream : not null access Root_Stream_Type'Class; 676 Tree : in out Tree_Type'Class) 677 is 678 Len : Count_Type'Base; 679 680 Node, Last_Node : Count_Type; 681 682 N : Nodes_Type renames Tree.Nodes; 683 684 begin 685 Clear_Tree (Tree); 686 Count_Type'Base'Read (Stream, Len); 687 688 if Checks and then Len < 0 then 689 raise Program_Error with "bad container length (corrupt stream)"; 690 end if; 691 692 if Len = 0 then 693 return; 694 end if; 695 696 if Checks and then Len > Tree.Capacity then 697 raise Constraint_Error with "length exceeds capacity"; 698 end if; 699 700 -- Use Unconditional_Insert_With_Hint here instead ??? 701 702 Allocate (Tree, Node); 703 pragma Assert (Node /= 0); 704 705 Set_Color (N (Node), Black); 706 707 Tree.Root := Node; 708 Tree.First := Node; 709 Tree.Last := Node; 710 Tree.Length := 1; 711 712 for J in Count_Type range 2 .. Len loop 713 Last_Node := Node; 714 pragma Assert (Last_Node = Tree.Last); 715 716 Allocate (Tree, Node); 717 pragma Assert (Node /= 0); 718 719 Set_Color (N (Node), Red); 720 Set_Right (N (Last_Node), Right => Node); 721 Tree.Last := Node; 722 Set_Parent (N (Node), Parent => Last_Node); 723 724 Rebalance_For_Insert (Tree, Node); 725 Tree.Length := Tree.Length + 1; 726 end loop; 727 end Generic_Read; 728 729 ------------------------------- 730 -- Generic_Reverse_Iteration -- 731 ------------------------------- 732 733 procedure Generic_Reverse_Iteration (Tree : Tree_Type'Class) is 734 procedure Iterate (P : Count_Type); 735 736 ------------- 737 -- Iterate -- 738 ------------- 739 740 procedure Iterate (P : Count_Type) is 741 X : Count_Type := P; 742 begin 743 while X /= 0 loop 744 Iterate (Right (Tree.Nodes (X))); 745 Process (X); 746 X := Left (Tree.Nodes (X)); 747 end loop; 748 end Iterate; 749 750 -- Start of processing for Generic_Reverse_Iteration 751 752 begin 753 Iterate (Tree.Root); 754 end Generic_Reverse_Iteration; 755 756 ------------------- 757 -- Generic_Write -- 758 ------------------- 759 760 procedure Generic_Write 761 (Stream : not null access Root_Stream_Type'Class; 762 Tree : Tree_Type'Class) 763 is 764 procedure Process (Node : Count_Type); 765 pragma Inline (Process); 766 767 procedure Iterate is new Generic_Iteration (Process); 768 769 ------------- 770 -- Process -- 771 ------------- 772 773 procedure Process (Node : Count_Type) is 774 begin 775 Write_Node (Stream, Tree.Nodes (Node)); 776 end Process; 777 778 -- Start of processing for Generic_Write 779 780 begin 781 Count_Type'Base'Write (Stream, Tree.Length); 782 Iterate (Tree); 783 end Generic_Write; 784 785 ----------------- 786 -- Left_Rotate -- 787 ----------------- 788 789 procedure Left_Rotate (Tree : in out Tree_Type'Class; X : Count_Type) is 790 791 -- CLR p. 266 792 793 N : Nodes_Type renames Tree.Nodes; 794 795 Y : constant Count_Type := Right (N (X)); 796 pragma Assert (Y /= 0); 797 798 begin 799 Set_Right (N (X), Left (N (Y))); 800 801 if Left (N (Y)) /= 0 then 802 Set_Parent (N (Left (N (Y))), X); 803 end if; 804 805 Set_Parent (N (Y), Parent (N (X))); 806 807 if X = Tree.Root then 808 Tree.Root := Y; 809 elsif X = Left (N (Parent (N (X)))) then 810 Set_Left (N (Parent (N (X))), Y); 811 else 812 pragma Assert (X = Right (N (Parent (N (X))))); 813 Set_Right (N (Parent (N (X))), Y); 814 end if; 815 816 Set_Left (N (Y), X); 817 Set_Parent (N (X), Y); 818 end Left_Rotate; 819 820 --------- 821 -- Max -- 822 --------- 823 824 function Max 825 (Tree : Tree_Type'Class; 826 Node : Count_Type) return Count_Type 827 is 828 -- CLR p. 248 829 830 X : Count_Type := Node; 831 Y : Count_Type; 832 833 begin 834 loop 835 Y := Right (Tree.Nodes (X)); 836 837 if Y = 0 then 838 return X; 839 end if; 840 841 X := Y; 842 end loop; 843 end Max; 844 845 --------- 846 -- Min -- 847 --------- 848 849 function Min 850 (Tree : Tree_Type'Class; 851 Node : Count_Type) return Count_Type 852 is 853 -- CLR p. 248 854 855 X : Count_Type := Node; 856 Y : Count_Type; 857 858 begin 859 loop 860 Y := Left (Tree.Nodes (X)); 861 862 if Y = 0 then 863 return X; 864 end if; 865 866 X := Y; 867 end loop; 868 end Min; 869 870 ---------- 871 -- Next -- 872 ---------- 873 874 function Next 875 (Tree : Tree_Type'Class; 876 Node : Count_Type) return Count_Type 877 is 878 begin 879 -- CLR p. 249 880 881 if Node = 0 then 882 return 0; 883 end if; 884 885 if Right (Tree.Nodes (Node)) /= 0 then 886 return Min (Tree, Right (Tree.Nodes (Node))); 887 end if; 888 889 declare 890 X : Count_Type := Node; 891 Y : Count_Type := Parent (Tree.Nodes (Node)); 892 893 begin 894 while Y /= 0 and then X = Right (Tree.Nodes (Y)) loop 895 X := Y; 896 Y := Parent (Tree.Nodes (Y)); 897 end loop; 898 899 return Y; 900 end; 901 end Next; 902 903 -------------- 904 -- Previous -- 905 -------------- 906 907 function Previous 908 (Tree : Tree_Type'Class; 909 Node : Count_Type) return Count_Type 910 is 911 begin 912 if Node = 0 then 913 return 0; 914 end if; 915 916 if Left (Tree.Nodes (Node)) /= 0 then 917 return Max (Tree, Left (Tree.Nodes (Node))); 918 end if; 919 920 declare 921 X : Count_Type := Node; 922 Y : Count_Type := Parent (Tree.Nodes (Node)); 923 924 begin 925 while Y /= 0 and then X = Left (Tree.Nodes (Y)) loop 926 X := Y; 927 Y := Parent (Tree.Nodes (Y)); 928 end loop; 929 930 return Y; 931 end; 932 end Previous; 933 934 -------------------------- 935 -- Rebalance_For_Insert -- 936 -------------------------- 937 938 procedure Rebalance_For_Insert 939 (Tree : in out Tree_Type'Class; 940 Node : Count_Type) 941 is 942 -- CLR p. 268 943 944 N : Nodes_Type renames Tree.Nodes; 945 946 X : Count_Type := Node; 947 pragma Assert (X /= 0); 948 pragma Assert (Color (N (X)) = Red); 949 950 Y : Count_Type; 951 952 begin 953 while X /= Tree.Root and then Color (N (Parent (N (X)))) = Red loop 954 if Parent (N (X)) = Left (N (Parent (N (Parent (N (X)))))) then 955 Y := Right (N (Parent (N (Parent (N (X)))))); 956 957 if Y /= 0 and then Color (N (Y)) = Red then 958 Set_Color (N (Parent (N (X))), Black); 959 Set_Color (N (Y), Black); 960 Set_Color (N (Parent (N (Parent (N (X))))), Red); 961 X := Parent (N (Parent (N (X)))); 962 963 else 964 if X = Right (N (Parent (N (X)))) then 965 X := Parent (N (X)); 966 Left_Rotate (Tree, X); 967 end if; 968 969 Set_Color (N (Parent (N (X))), Black); 970 Set_Color (N (Parent (N (Parent (N (X))))), Red); 971 Right_Rotate (Tree, Parent (N (Parent (N (X))))); 972 end if; 973 974 else 975 pragma Assert (Parent (N (X)) = 976 Right (N (Parent (N (Parent (N (X))))))); 977 978 Y := Left (N (Parent (N (Parent (N (X)))))); 979 980 if Y /= 0 and then Color (N (Y)) = Red then 981 Set_Color (N (Parent (N (X))), Black); 982 Set_Color (N (Y), Black); 983 Set_Color (N (Parent (N (Parent (N (X))))), Red); 984 X := Parent (N (Parent (N (X)))); 985 986 else 987 if X = Left (N (Parent (N (X)))) then 988 X := Parent (N (X)); 989 Right_Rotate (Tree, X); 990 end if; 991 992 Set_Color (N (Parent (N (X))), Black); 993 Set_Color (N (Parent (N (Parent (N (X))))), Red); 994 Left_Rotate (Tree, Parent (N (Parent (N (X))))); 995 end if; 996 end if; 997 end loop; 998 999 Set_Color (N (Tree.Root), Black); 1000 end Rebalance_For_Insert; 1001 1002 ------------------ 1003 -- Right_Rotate -- 1004 ------------------ 1005 1006 procedure Right_Rotate (Tree : in out Tree_Type'Class; Y : Count_Type) is 1007 N : Nodes_Type renames Tree.Nodes; 1008 1009 X : constant Count_Type := Left (N (Y)); 1010 pragma Assert (X /= 0); 1011 1012 begin 1013 Set_Left (N (Y), Right (N (X))); 1014 1015 if Right (N (X)) /= 0 then 1016 Set_Parent (N (Right (N (X))), Y); 1017 end if; 1018 1019 Set_Parent (N (X), Parent (N (Y))); 1020 1021 if Y = Tree.Root then 1022 Tree.Root := X; 1023 elsif Y = Left (N (Parent (N (Y)))) then 1024 Set_Left (N (Parent (N (Y))), X); 1025 else 1026 pragma Assert (Y = Right (N (Parent (N (Y))))); 1027 Set_Right (N (Parent (N (Y))), X); 1028 end if; 1029 1030 Set_Right (N (X), Y); 1031 Set_Parent (N (Y), X); 1032 end Right_Rotate; 1033 1034 --------- 1035 -- Vet -- 1036 --------- 1037 1038 function Vet (Tree : Tree_Type'Class; Index : Count_Type) return Boolean is 1039 Nodes : Nodes_Type renames Tree.Nodes; 1040 Node : Node_Type renames Nodes (Index); 1041 1042 begin 1043 if Parent (Node) = Index 1044 or else Left (Node) = Index 1045 or else Right (Node) = Index 1046 then 1047 return False; 1048 end if; 1049 1050 if Tree.Length = 0 1051 or else Tree.Root = 0 1052 or else Tree.First = 0 1053 or else Tree.Last = 0 1054 then 1055 return False; 1056 end if; 1057 1058 if Parent (Nodes (Tree.Root)) /= 0 then 1059 return False; 1060 end if; 1061 1062 if Left (Nodes (Tree.First)) /= 0 then 1063 return False; 1064 end if; 1065 1066 if Right (Nodes (Tree.Last)) /= 0 then 1067 return False; 1068 end if; 1069 1070 if Tree.Length = 1 then 1071 if Tree.First /= Tree.Last 1072 or else Tree.First /= Tree.Root 1073 then 1074 return False; 1075 end if; 1076 1077 if Index /= Tree.First then 1078 return False; 1079 end if; 1080 1081 if Parent (Node) /= 0 1082 or else Left (Node) /= 0 1083 or else Right (Node) /= 0 1084 then 1085 return False; 1086 end if; 1087 1088 return True; 1089 end if; 1090 1091 if Tree.First = Tree.Last then 1092 return False; 1093 end if; 1094 1095 if Tree.Length = 2 then 1096 if Tree.First /= Tree.Root and then Tree.Last /= Tree.Root then 1097 return False; 1098 end if; 1099 1100 if Tree.First /= Index and then Tree.Last /= Index then 1101 return False; 1102 end if; 1103 end if; 1104 1105 if Left (Node) /= 0 and then Parent (Nodes (Left (Node))) /= Index then 1106 return False; 1107 end if; 1108 1109 if Right (Node) /= 0 and then Parent (Nodes (Right (Node))) /= Index then 1110 return False; 1111 end if; 1112 1113 if Parent (Node) = 0 then 1114 if Tree.Root /= Index then 1115 return False; 1116 end if; 1117 1118 elsif Left (Nodes (Parent (Node))) /= Index 1119 and then Right (Nodes (Parent (Node))) /= Index 1120 then 1121 return False; 1122 end if; 1123 1124 return True; 1125 end Vet; 1126 1127end Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations; 1128