losertree.h 25 KB

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