1 // -*- C++ -*- 2 3 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the terms 7 // of the GNU General Public License as published by the Free Software 8 // Foundation; either version 3, or (at your option) any later 9 // version. 10 11 // This library is distributed in the hope that it will be useful, but 12 // WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file parallel/losertree.h 26 * @brief Many generic loser tree variants. 27 * This file is a GNU parallel extension to the Standard C++ Library. 28 */ 29 30 // Written by Johannes Singler. 31 32 #ifndef _GLIBCXX_PARALLEL_LOSERTREE_H 33 #define _GLIBCXX_PARALLEL_LOSERTREE_H 1 34 35 #include <functional> 36 37 #include <bits/stl_algobase.h> 38 #include <parallel/features.h> 39 #include <parallel/base.h> 40 41 namespace __gnu_parallel 42 { 43 44 /** 45 * @brief Guarded loser/tournament tree. 46 * 47 * The smallest element is at the top. 48 * 49 * Guarding is done explicitly through one flag sup per element, 50 * inf is not needed due to a better initialization routine. This 51 * is a well-performing variant. 52 * 53 * @param T the element type 54 * @param Comparator the comparator to use, defaults to std::less<T> 55 */ 56 template<typename T, typename Comparator> 57 class LoserTreeBase 58 { 59 protected: 60 /** @brief Internal representation of a LoserTree element. */ 61 struct Loser 62 { 63 /** @brief flag, true iff this is a "maximum" sentinel. */ 64 bool sup; 65 /** @brief index of the source sequence. */ 66 int source; 67 /** @brief key of the element in the LoserTree. */ 68 T key; 69 }; 70 71 unsigned int ik, k, offset; 72 73 /** log_2{k} */ 74 unsigned int _M_log_k; 75 76 /** @brief LoserTree elements. */ 77 Loser* losers; 78 79 /** @brief Comparator to use. */ 80 Comparator comp; 81 82 /** 83 * @brief State flag that determines whether the LoserTree is empty. 84 * 85 * Only used for building the LoserTree. 86 */ 87 bool first_insert; 88 89 public: 90 /** 91 * @brief The constructor. 92 * 93 * @param _k The number of sequences to merge. 94 * @param _comp The comparator to use. 95 */ 96 LoserTreeBase(unsigned int _k, Comparator _comp) 97 : comp(_comp) 98 { 99 ik = _k; 100 101 // Compute log_2{k} for the Loser Tree 102 _M_log_k = __log2(ik - 1) + 1; 103 104 // Next greater power of 2. 105 k = 1 << _M_log_k; 106 offset = k; 107 108 // Avoid default-constructing losers[].key 109 losers = static_cast<Loser*>(::operator new(2 * k * sizeof(Loser))); 110 for (unsigned int i = ik - 1; i < k; ++i) 111 losers[i + k].sup = true; 112 113 first_insert = true; 114 } 115 116 /** 117 * @brief The destructor. 118 */ 119 ~LoserTreeBase() 120 { ::operator delete(losers); } 121 122 /** 123 * @brief Initializes the sequence "source" with the element "key". 124 * 125 * @param key the element to insert 126 * @param source index of the source sequence 127 * @param sup flag that determines whether the value to insert is an 128 * explicit supremum. 129 */ 130 inline void 131 insert_start(const T& key, int source, bool sup) 132 { 133 unsigned int pos = k + source; 134 135 if(first_insert) 136 { 137 // Construct all keys, so we can easily deconstruct them. 138 for (unsigned int i = 0; i < (2 * k); ++i) 139 new(&(losers[i].key)) T(key); 140 first_insert = false; 141 } 142 else 143 new(&(losers[pos].key)) T(key); 144 145 losers[pos].sup = sup; 146 losers[pos].source = source; 147 } 148 149 /** 150 * @return the index of the sequence with the smallest element. 151 */ 152 int get_min_source() 153 { return losers[0].source; } 154 }; 155 156 /** 157 * @brief Stable LoserTree variant. 158 * 159 * Provides the stable implementations of insert_start, init_winner, 160 * init and delete_min_insert. 161 * 162 * Unstable variant is done using partial specialisation below. 163 */ 164 template<bool stable/* default == true */, typename T, typename Comparator> 165 class LoserTree : public LoserTreeBase<T, Comparator> 166 { 167 typedef LoserTreeBase<T, Comparator> Base; 168 using Base::k; 169 using Base::losers; 170 using Base::first_insert; 171 172 public: 173 LoserTree(unsigned int _k, Comparator _comp) 174 : Base::LoserTreeBase(_k, _comp) 175 {} 176 177 unsigned int 178 init_winner(unsigned int root) 179 { 180 if (root >= k) 181 { 182 return root; 183 } 184 else 185 { 186 unsigned int left = init_winner (2 * root); 187 unsigned int right = init_winner (2 * root + 1); 188 if (losers[right].sup 189 || (!losers[left].sup 190 && !comp(losers[right].key, losers[left].key))) 191 { 192 // Left one is less or equal. 193 losers[root] = losers[right]; 194 return left; 195 } 196 else 197 { 198 // Right one is less. 199 losers[root] = losers[left]; 200 return right; 201 } 202 } 203 } 204 205 void init() 206 { losers[0] = losers[init_winner(1)]; } 207 208 /** 209 * @brief Delete the smallest element and insert a new element from 210 * the previously smallest element's sequence. 211 * 212 * This implementation is stable. 213 */ 214 // Do not pass a const reference since key will be used as local variable. 215 void delete_min_insert(T key, bool sup) 216 { 217 #if _GLIBCXX_ASSERTIONS 218 // no dummy sequence can ever be at the top! 219 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 220 #endif 221 222 int source = losers[0].source; 223 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 224 { 225 // The smaller one gets promoted, ties are broken by source. 226 if ((sup && (!losers[pos].sup || losers[pos].source < source)) 227 || (!sup && !losers[pos].sup 228 && ((comp(losers[pos].key, key)) 229 || (!comp(key, losers[pos].key) 230 && losers[pos].source < source)))) 231 { 232 // The other one is smaller. 233 std::swap(losers[pos].sup, sup); 234 std::swap(losers[pos].source, source); 235 std::swap(losers[pos].key, key); 236 } 237 } 238 239 losers[0].sup = sup; 240 losers[0].source = source; 241 losers[0].key = key; 242 } 243 }; 244 245 /** 246 * @brief Unstable LoserTree variant. 247 * 248 * Stability (non-stable here) is selected with partial specialization. 249 */ 250 template<typename T, typename Comparator> 251 class LoserTree</* stable == */false, T, Comparator> : 252 public LoserTreeBase<T, Comparator> 253 { 254 typedef LoserTreeBase<T, Comparator> Base; 255 using Base::_M_log_k; 256 using Base::k; 257 using Base::losers; 258 using Base::first_insert; 259 260 public: 261 LoserTree(unsigned int _k, Comparator _comp) 262 : Base::LoserTreeBase(_k, _comp) 263 {} 264 265 /** 266 * Computes the winner of the competition at position "root". 267 * 268 * Called recursively (starting at 0) to build the initial tree. 269 * 270 * @param root index of the "game" to start. 271 */ 272 unsigned int 273 init_winner (unsigned int root) 274 { 275 if (root >= k) 276 { 277 return root; 278 } 279 else 280 { 281 unsigned int left = init_winner (2 * root); 282 unsigned int right = init_winner (2 * root + 1); 283 if (losers[right].sup || 284 (!losers[left].sup 285 && !comp(losers[right].key, losers[left].key))) 286 { 287 // Left one is less or equal. 288 losers[root] = losers[right]; 289 return left; 290 } 291 else 292 { 293 // Right one is less. 294 losers[root] = losers[left]; 295 return right; 296 } 297 } 298 } 299 300 inline void 301 init() 302 { losers[0] = losers[init_winner(1)]; } 303 304 /** 305 * Delete the key smallest element and insert the element key instead. 306 * 307 * @param key the key to insert 308 * @param sup true iff key is an explicitly marked supremum 309 */ 310 // Do not pass a const reference since key will be used as local variable. 311 inline void 312 delete_min_insert(T key, bool sup) 313 { 314 #if _GLIBCXX_ASSERTIONS 315 // no dummy sequence can ever be at the top! 316 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 317 #endif 318 319 int source = losers[0].source; 320 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 321 { 322 // The smaller one gets promoted. 323 if (sup || (!losers[pos].sup && comp(losers[pos].key, key))) 324 { 325 // The other one is smaller. 326 std::swap(losers[pos].sup, sup); 327 std::swap(losers[pos].source, source); 328 std::swap(losers[pos].key, key); 329 } 330 } 331 332 losers[0].sup = sup; 333 losers[0].source = source; 334 losers[0].key = key; 335 } 336 }; 337 338 339 /** 340 * @brief Base class of Loser Tree implementation using pointers. 341 */ 342 template<typename T, typename Comparator> 343 class LoserTreePointerBase 344 { 345 protected: 346 /** @brief Internal representation of LoserTree elements. */ 347 struct Loser 348 { 349 bool sup; 350 int source; 351 const T* keyp; 352 }; 353 354 unsigned int ik, k, offset; 355 Loser* losers; 356 Comparator comp; 357 358 public: 359 LoserTreePointerBase(unsigned int _k, Comparator _comp = std::less<T>()) 360 : comp(_comp) 361 { 362 ik = _k; 363 364 // Next greater power of 2. 365 k = 1 << (__log2(ik - 1) + 1); 366 offset = k; 367 losers = new Loser[k * 2]; 368 for (unsigned int i = ik - 1; i < k; i++) 369 losers[i + k].sup = true; 370 } 371 372 ~LoserTreePointerBase() 373 { ::operator delete[](losers); } 374 375 int get_min_source() 376 { return losers[0].source; } 377 378 void insert_start(const T& key, int source, bool sup) 379 { 380 unsigned int pos = k + source; 381 382 losers[pos].sup = sup; 383 losers[pos].source = source; 384 losers[pos].keyp = &key; 385 } 386 }; 387 388 /** 389 * @brief Stable LoserTree implementation. 390 * 391 * The unstable variant is implemented using partial instantiation below. 392 */ 393 template<bool stable/* default == true */, typename T, typename Comparator> 394 class LoserTreePointer : public LoserTreePointerBase<T, Comparator> 395 { 396 typedef LoserTreePointerBase<T, Comparator> Base; 397 using Base::k; 398 using Base::losers; 399 400 public: 401 LoserTreePointer(unsigned int _k, Comparator _comp = std::less<T>()) 402 : Base::LoserTreePointerBase(_k, _comp) 403 {} 404 405 unsigned int 406 init_winner(unsigned int root) 407 { 408 if (root >= k) 409 { 410 return root; 411 } 412 else 413 { 414 unsigned int left = init_winner (2 * root); 415 unsigned int right = init_winner (2 * root + 1); 416 if (losers[right].sup 417 || (!losers[left].sup && !comp(*losers[right].keyp, 418 *losers[left].keyp))) 419 { 420 // Left one is less or equal. 421 losers[root] = losers[right]; 422 return left; 423 } 424 else 425 { 426 // Right one is less. 427 losers[root] = losers[left]; 428 return right; 429 } 430 } 431 } 432 433 void init() 434 { losers[0] = losers[init_winner(1)]; } 435 436 void delete_min_insert(const T& key, bool sup) 437 { 438 #if _GLIBCXX_ASSERTIONS 439 // no dummy sequence can ever be at the top! 440 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 441 #endif 442 443 const T* keyp = &key; 444 int source = losers[0].source; 445 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 446 { 447 // The smaller one gets promoted, ties are broken by source. 448 if ((sup && (!losers[pos].sup || losers[pos].source < source)) || 449 (!sup && !losers[pos].sup && 450 ((comp(*losers[pos].keyp, *keyp)) || 451 (!comp(*keyp, *losers[pos].keyp) 452 && losers[pos].source < source)))) 453 { 454 // The other one is smaller. 455 std::swap(losers[pos].sup, sup); 456 std::swap(losers[pos].source, source); 457 std::swap(losers[pos].keyp, keyp); 458 } 459 } 460 461 losers[0].sup = sup; 462 losers[0].source = source; 463 losers[0].keyp = keyp; 464 } 465 }; 466 467 /** 468 * @brief Unstable LoserTree implementation. 469 * 470 * The stable variant is above. 471 */ 472 template<typename T, typename Comparator> 473 class LoserTreePointer</* stable == */false, T, Comparator> : 474 public LoserTreePointerBase<T, Comparator> 475 { 476 typedef LoserTreePointerBase<T, Comparator> Base; 477 using Base::k; 478 using Base::losers; 479 480 public: 481 LoserTreePointer(unsigned int _k, Comparator _comp = std::less<T>()) 482 : Base::LoserTreePointerBase(_k, _comp) 483 {} 484 485 unsigned int 486 init_winner(unsigned int root) 487 { 488 if (root >= k) 489 { 490 return root; 491 } 492 else 493 { 494 unsigned int left = init_winner (2 * root); 495 unsigned int right = init_winner (2 * root + 1); 496 if (losers[right].sup 497 || (!losers[left].sup 498 && !comp(*losers[right].keyp, *losers[left].keyp))) 499 { 500 // Left one is less or equal. 501 losers[root] = losers[right]; 502 return left; 503 } 504 else 505 { 506 // Right one is less. 507 losers[root] = losers[left]; 508 return right; 509 } 510 } 511 } 512 513 void init() 514 { losers[0] = losers[init_winner(1)]; } 515 516 void delete_min_insert(const T& key, bool sup) 517 { 518 #if _GLIBCXX_ASSERTIONS 519 // no dummy sequence can ever be at the top! 520 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 521 #endif 522 523 const T* keyp = &key; 524 int source = losers[0].source; 525 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 526 { 527 // The smaller one gets promoted. 528 if (sup || (!losers[pos].sup && comp(*losers[pos].keyp, *keyp))) 529 { 530 // The other one is smaller. 531 std::swap(losers[pos].sup, sup); 532 std::swap(losers[pos].source, source); 533 std::swap(losers[pos].keyp, keyp); 534 } 535 } 536 537 losers[0].sup = sup; 538 losers[0].source = source; 539 losers[0].keyp = keyp; 540 } 541 }; 542 543 /** @brief Base class for unguarded LoserTree implementation. 544 * 545 * The whole element is copied into the tree structure. 546 * 547 * No guarding is done, therefore not a single input sequence must 548 * run empty. Unused sequence heads are marked with a sentinel which 549 * is > all elements that are to be merged. 550 * 551 * This is a very fast variant. 552 */ 553 template<typename T, typename Comparator> 554 class LoserTreeUnguardedBase 555 { 556 protected: 557 struct Loser 558 { 559 int source; 560 T key; 561 }; 562 563 unsigned int ik, k, offset; 564 Loser* losers; 565 Comparator comp; 566 567 public: 568 inline 569 LoserTreeUnguardedBase(unsigned int _k, const T _sentinel, 570 Comparator _comp = std::less<T>()) 571 : comp(_comp) 572 { 573 ik = _k; 574 575 // Next greater power of 2. 576 k = 1 << (__log2(ik - 1) + 1); 577 offset = k; 578 // Avoid default-constructing losers[].key 579 losers = static_cast<Loser*>(::operator new(2 * k * sizeof(Loser))); 580 581 for (unsigned int i = k + ik - 1; i < (2 * k); ++i) 582 { 583 losers[i].key = _sentinel; 584 losers[i].source = -1; 585 } 586 } 587 588 inline ~LoserTreeUnguardedBase() 589 { ::operator delete(losers); } 590 591 inline int 592 get_min_source() 593 { 594 #if _GLIBCXX_ASSERTIONS 595 // no dummy sequence can ever be at the top! 596 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 597 #endif 598 return losers[0].source; 599 } 600 601 inline void 602 insert_start(const T& key, int source, bool) 603 { 604 unsigned int pos = k + source; 605 606 new(&(losers[pos].key)) T(key); 607 losers[pos].source = source; 608 } 609 }; 610 611 /** 612 * @brief Stable implementation of unguarded LoserTree. 613 * 614 * Unstable variant is selected below with partial specialization. 615 */ 616 template<bool stable/* default == true */, typename T, typename Comparator> 617 class LoserTreeUnguarded : public LoserTreeUnguardedBase<T, Comparator> 618 { 619 typedef LoserTreeUnguardedBase<T, Comparator> Base; 620 using Base::k; 621 using Base::losers; 622 623 public: 624 LoserTreeUnguarded(unsigned int _k, const T _sentinel, 625 Comparator _comp = std::less<T>()) 626 : Base::LoserTreeUnguardedBase(_k, _sentinel, _comp) 627 {} 628 629 unsigned int 630 init_winner(unsigned int root) 631 { 632 if (root >= k) 633 { 634 return root; 635 } 636 else 637 { 638 unsigned int left = init_winner (2 * root); 639 unsigned int right = init_winner (2 * root + 1); 640 if (!comp(losers[right].key, losers[left].key)) 641 { 642 // Left one is less or equal. 643 losers[root] = losers[right]; 644 return left; 645 } 646 else 647 { 648 // Right one is less. 649 losers[root] = losers[left]; 650 return right; 651 } 652 } 653 } 654 655 inline void 656 init() 657 { 658 losers[0] = losers[init_winner(1)]; 659 660 #if _GLIBCXX_ASSERTIONS 661 // no dummy sequence can ever be at the top at the beginning (0 sequences!) 662 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 663 #endif 664 } 665 666 // Do not pass a const reference since key will be used as local variable. 667 inline void 668 delete_min_insert(T key, bool) 669 { 670 #if _GLIBCXX_ASSERTIONS 671 // no dummy sequence can ever be at the top! 672 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 673 #endif 674 675 int source = losers[0].source; 676 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 677 { 678 // The smaller one gets promoted, ties are broken by source. 679 if (comp(losers[pos].key, key) 680 || (!comp(key, losers[pos].key) && losers[pos].source < source)) 681 { 682 // The other one is smaller. 683 std::swap(losers[pos].source, source); 684 std::swap(losers[pos].key, key); 685 } 686 } 687 688 losers[0].source = source; 689 losers[0].key = key; 690 } 691 }; 692 693 /** 694 * @brief Non-Stable implementation of unguarded LoserTree. 695 * 696 * Stable implementation is above. 697 */ 698 template<typename T, typename Comparator> 699 class LoserTreeUnguarded</* stable == */false, T, Comparator> : 700 public LoserTreeUnguardedBase<T, Comparator> 701 { 702 typedef LoserTreeUnguardedBase<T, Comparator> Base; 703 using Base::k; 704 using Base::losers; 705 706 public: 707 LoserTreeUnguarded(unsigned int _k, const T _sentinel, 708 Comparator _comp = std::less<T>()) 709 : Base::LoserTreeUnguardedBase(_k, _sentinel, _comp) 710 {} 711 712 unsigned int 713 init_winner (unsigned int root) 714 { 715 if (root >= k) 716 { 717 return root; 718 } 719 else 720 { 721 unsigned int left = init_winner (2 * root); 722 unsigned int right = init_winner (2 * root + 1); 723 724 #if _GLIBCXX_ASSERTIONS 725 // If left one is sentinel then right one must be, too. 726 if (losers[left].source == -1) 727 _GLIBCXX_PARALLEL_ASSERT(losers[right].source == -1); 728 #endif 729 730 if (!comp(losers[right].key, losers[left].key)) 731 { 732 // Left one is less or equal. 733 losers[root] = losers[right]; 734 return left; 735 } 736 else 737 { 738 // Right one is less. 739 losers[root] = losers[left]; 740 return right; 741 } 742 } 743 } 744 745 inline void 746 init() 747 { 748 losers[0] = losers[init_winner(1)]; 749 750 #if _GLIBCXX_ASSERTIONS 751 // no dummy sequence can ever be at the top at the beginning (0 sequences!) 752 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 753 #endif 754 } 755 756 // Do not pass a const reference since key will be used as local variable. 757 inline void 758 delete_min_insert(T key, bool) 759 { 760 #if _GLIBCXX_ASSERTIONS 761 // no dummy sequence can ever be at the top! 762 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 763 #endif 764 765 int source = losers[0].source; 766 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 767 { 768 // The smaller one gets promoted. 769 if (comp(losers[pos].key, key)) 770 { 771 // The other one is smaller. 772 std::swap(losers[pos].source, source); 773 std::swap(losers[pos].key, key); 774 } 775 } 776 777 losers[0].source = source; 778 losers[0].key = key; 779 } 780 }; 781 782 /** @brief Unguarded loser tree, keeping only pointers to the 783 * elements in the tree structure. 784 * 785 * No guarding is done, therefore not a single input sequence must 786 * run empty. This is a very fast variant. 787 */ 788 template<typename T, typename Comparator> 789 class LoserTreePointerUnguardedBase 790 { 791 protected: 792 struct Loser 793 { 794 int source; 795 const T* keyp; 796 }; 797 798 unsigned int ik, k, offset; 799 Loser* losers; 800 Comparator comp; 801 802 public: 803 804 inline 805 LoserTreePointerUnguardedBase(unsigned int _k, const T& _sentinel, 806 Comparator _comp = std::less<T>()) 807 : comp(_comp) 808 { 809 ik = _k; 810 811 // Next greater power of 2. 812 k = 1 << (__log2(ik - 1) + 1); 813 offset = k; 814 // Avoid default-constructing losers[].key 815 losers = new Loser[2 * k]; 816 817 for (unsigned int i = k + ik - 1; i < (2 * k); ++i) 818 { 819 losers[i].keyp = &_sentinel; 820 losers[i].source = -1; 821 } 822 } 823 824 inline ~LoserTreePointerUnguardedBase() 825 { delete[] losers; } 826 827 inline int 828 get_min_source() 829 { 830 #if _GLIBCXX_ASSERTIONS 831 // no dummy sequence can ever be at the top! 832 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 833 #endif 834 return losers[0].source; 835 } 836 837 inline void 838 insert_start(const T& key, int source, bool) 839 { 840 unsigned int pos = k + source; 841 842 losers[pos].keyp = &key; 843 losers[pos].source = source; 844 } 845 }; 846 847 /** 848 * @brief Stable unguarded LoserTree variant storing pointers. 849 * 850 * Unstable variant is implemented below using partial specialization. 851 */ 852 template<bool stable/* default == true */, typename T, typename Comparator> 853 class LoserTreePointerUnguarded : 854 public LoserTreePointerUnguardedBase<T, Comparator> 855 { 856 typedef LoserTreePointerUnguardedBase<T, Comparator> Base; 857 using Base::k; 858 using Base::losers; 859 860 public: 861 LoserTreePointerUnguarded(unsigned int _k, const T& _sentinel, 862 Comparator _comp = std::less<T>()) 863 : Base::LoserTreePointerUnguardedBase(_k, _sentinel, _comp) 864 {} 865 866 unsigned int 867 init_winner(unsigned int root) 868 { 869 if (root >= k) 870 { 871 return root; 872 } 873 else 874 { 875 unsigned int left = init_winner (2 * root); 876 unsigned int right = init_winner (2 * root + 1); 877 if (!comp(*losers[right].keyp, *losers[left].keyp)) 878 { 879 // Left one is less or equal. 880 losers[root] = losers[right]; 881 return left; 882 } 883 else 884 { 885 // Right one is less. 886 losers[root] = losers[left]; 887 return right; 888 } 889 } 890 } 891 892 inline void 893 init() 894 { 895 losers[0] = losers[init_winner(1)]; 896 897 #if _GLIBCXX_ASSERTIONS 898 // no dummy sequence can ever be at the top at the beginning (0 sequences!) 899 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 900 #endif 901 } 902 903 inline void 904 delete_min_insert(const T& key, bool sup) 905 { 906 #if _GLIBCXX_ASSERTIONS 907 // no dummy sequence can ever be at the top! 908 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 909 #endif 910 911 const T* keyp = &key; 912 int source = losers[0].source; 913 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 914 { 915 // The smaller one gets promoted, ties are broken by source. 916 if (comp(*losers[pos].keyp, *keyp) 917 || (!comp(*keyp, *losers[pos].keyp) && losers[pos].source < source)) 918 { 919 // The other one is smaller. 920 std::swap(losers[pos].source, source); 921 std::swap(losers[pos].keyp, keyp); 922 } 923 } 924 925 losers[0].source = source; 926 losers[0].keyp = keyp; 927 } 928 }; 929 930 /** 931 * @brief Unstable unguarded LoserTree variant storing pointers. 932 * 933 * Stable variant is above. 934 */ 935 template<typename T, typename Comparator> 936 class LoserTreePointerUnguarded</* stable == */false, T, Comparator> : 937 public LoserTreePointerUnguardedBase<T, Comparator> 938 { 939 typedef LoserTreePointerUnguardedBase<T, Comparator> Base; 940 using Base::k; 941 using Base::losers; 942 943 public: 944 LoserTreePointerUnguarded(unsigned int _k, const T& _sentinel, 945 Comparator _comp = std::less<T>()) 946 : Base::LoserTreePointerUnguardedBase(_k, _sentinel, _comp) 947 {} 948 949 unsigned int 950 init_winner(unsigned int root) 951 { 952 if (root >= k) 953 { 954 return root; 955 } 956 else 957 { 958 unsigned int left = init_winner (2 * root); 959 unsigned int right = init_winner (2 * root + 1); 960 961 #if _GLIBCXX_ASSERTIONS 962 // If left one is sentinel then right one must be, too. 963 if (losers[left].source == -1) 964 _GLIBCXX_PARALLEL_ASSERT(losers[right].source == -1); 965 #endif 966 967 if (!comp(*losers[right].keyp, *losers[left].keyp)) 968 { 969 // Left one is less or equal. 970 losers[root] = losers[right]; 971 return left; 972 } 973 else 974 { 975 // Right one is less. 976 losers[root] = losers[left]; 977 return right; 978 } 979 } 980 } 981 982 inline void 983 init() 984 { 985 losers[0] = losers[init_winner(1)]; 986 987 #if _GLIBCXX_ASSERTIONS 988 // no dummy sequence can ever be at the top at the beginning (0 sequences!) 989 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 990 #endif 991 } 992 993 inline void 994 delete_min_insert(const T& key, bool sup) 995 { 996 #if _GLIBCXX_ASSERTIONS 997 // no dummy sequence can ever be at the top! 998 _GLIBCXX_PARALLEL_ASSERT(losers[0].source != -1); 999 #endif 1000 1001 const T* keyp = &key; 1002 int source = losers[0].source; 1003 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2) 1004 { 1005 // The smaller one gets promoted. 1006 if (comp(*(losers[pos].keyp), *keyp)) 1007 { 1008 // The other one is smaller. 1009 std::swap(losers[pos].source, source); 1010 std::swap(losers[pos].keyp, keyp); 1011 } 1012 } 1013 1014 losers[0].source = source; 1015 losers[0].keyp = keyp; 1016 } 1017 }; 1018 1019 } // namespace __gnu_parallel 1020 1021 #endif /* _GLIBCXX_PARALLEL_LOSERTREE_H */ 1022