losertree.h 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  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 */