STXXL  1.4-dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
losertree.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/parallel/losertree.h
3  *
4  * Many generic loser tree variants.
5  * Extracted from MCSTL - http://algo2.iti.uni-karlsruhe.de/singler/mcstl/
6  *
7  * Part of the STXXL. See http://stxxl.sourceforge.net
8  *
9  * Copyright (C) 2007 Johannes Singler <[email protected]>
10  * Copyright (C) 2014-2015 Timo Bingmann <[email protected]>
11  *
12  * Distributed under the Boost Software License, Version 1.0.
13  * (See accompanying file LICENSE_1_0.txt or copy at
14  * http://www.boost.org/LICENSE_1_0.txt)
15  **************************************************************************/
16 
17 #ifndef STXXL_PARALLEL_LOSERTREE_HEADER
18 #define STXXL_PARALLEL_LOSERTREE_HEADER
19 
20 #include <stxxl/bits/namespace.h>
21 #include <stxxl/bits/noncopyable.h>
24 #include <functional>
25 
27 
28 namespace parallel {
29 
30 /**
31  * Guarded loser tree/tournament tree, either copying the whole element into
32  * the tree structure, or looking up the element via the index.
33  *
34  * This is a base class for the LoserTreeCopy<true> and <false> classes.
35  *
36  * Guarding is done explicitly through one flag sup per element, inf is not
37  * needed due to a better initialization routine. This is a well-performing
38  * variant.
39  *
40  * \tparam ValueType the element type
41  * \tparam Comparator comparator to use for binary comparisons.
42  */
43 template <typename ValueType, typename Comparator = std::less<ValueType> >
45 {
46 public:
47  //! size of counters and array indexes
48  typedef unsigned int size_type;
49  //! type of the source field
50  typedef int source_type;
51 
52 protected:
53  //! Internal representation of a loser tree player/node
54  struct Loser
55  {
56  //! flag, true iff is a virtual maximum sentinel
57  bool sup;
58  //! index of source
60  //! copy of key value of the element in this node
61  ValueType key;
62  };
63 
64  //! number of nodes
65  const size_type ik;
66  //! log_2(ik) next greater power of 2
67  const size_type k;
68  //! array containing loser tree nodes
70  //! the comparator object
71  Comparator comp;
72  //! still have to construct keys
74 
75 public:
77  Comparator _comp = std::less<ValueType>())
78  : ik(_k),
80  comp(_comp),
81  first_insert(true)
82  {
83  // avoid default-constructing losers[].key
84  losers = static_cast<Loser*>(operator new (2 * k * sizeof(Loser)));
85 
86  for (size_type i = ik - 1; i < k; ++i)
87  {
88  losers[i + k].sup = true;
89  losers[i + k].source = (source_type)(-1);
90  }
91  }
92 
94  {
95  for (size_type i = 0; i < (2 * k); ++i)
96  losers[i].~Loser();
97 
98  delete losers;
99  }
100 
101  void print(std::ostream& os)
102  {
103  for (size_type i = 0; i < (k * 2); i++)
104  os << i << " " << losers[i].key << " from " << losers[i].source << ", " << losers[i].sup << "\n";
105  }
106 
107  //! return the index of the player with the smallest element.
109  {
110  return losers[0].source;
111  }
112 
113  /**
114  * Initializes the player source with the element key.
115  *
116  * \param key the element to insert
117  * \param source index of the player
118  * \param sup flag that determines whether the value to insert is an
119  * explicit supremum sentinel.
120  */
121  void insert_start(const ValueType& key, source_type source, bool sup)
122  {
123  size_type pos = k + source;
124 
125  losers[pos].sup = sup;
126  losers[pos].source = source;
127 
128  if (UNLIKELY(first_insert))
129  {
130  // copy construct all keys from this first key
131  for (size_type i = 0; i < (2 * k); ++i)
132  new (&(losers[i].key))ValueType(key);
133  first_insert = false;
134  }
135  else
136  losers[pos].key = key;
137  }
138 
139  /**
140  * Computes the winner of the competition at player root. Called
141  * recursively (starting at 0) to build the initial tree.
142  *
143  * \param root index of the game to start.
144  */
146  {
147  if (root >= k)
148  {
149  return root;
150  }
151  else
152  {
153  size_type left = init_winner(2 * root);
154  size_type right = init_winner(2 * root + 1);
155  if (losers[right].sup ||
156  (!losers[left].sup && !comp(losers[right].key, losers[left].key)))
157  { //left one is less or equal
158  losers[root] = losers[right];
159  return left;
160  }
161  else
162  { //right one is less
163  losers[root] = losers[left];
164  return right;
165  }
166  }
167  }
168 
169  void init()
170  {
171  losers[0] = losers[init_winner(1)];
172  }
173 };
174 
175 /**
176  * Guarded loser tree/tournament tree, either copying the whole element into
177  * the tree structure, or looking up the element via the index.
178  *
179  * Unstable specialization of LoserTreeCopyBase.
180  *
181  * Guarding is done explicitly through one flag sup per element, inf is not
182  * needed due to a better initialization routine. This is a well-performing
183  * variant.
184  *
185  * \tparam ValueType the element type
186  * \tparam Comparator comparator to use for binary comparisons.
187  */
188 template <bool Stable /* == false */,
189  typename ValueType, typename Comparator = std::less<ValueType> >
190 class LoserTreeCopy : public LoserTreeCopyBase<ValueType, Comparator>
191 {
192 public:
194 
195  typedef typename base_type::size_type size_type;
197  using base_type::k;
198  using base_type::losers;
199  using base_type::comp;
200 
201  LoserTreeCopy(size_type _k, Comparator _comp = std::less<ValueType>())
202  : base_type(_k, _comp)
203  { }
204 
205  // do not pass const reference since key will be used as local variable
206  void delete_min_insert(ValueType key, bool sup)
207  {
208  using std::swap;
209 
210  source_type source = losers[0].source;
211  for (size_type pos = (k + source) / 2; pos > 0; pos /= 2)
212  {
213  // the smaller one gets promoted
214  if (sup ||
215  (!losers[pos].sup && comp(losers[pos].key, key)))
216  {
217  // the other one is smaller
218  swap(losers[pos].sup, sup);
219  swap(losers[pos].source, source);
220  swap(losers[pos].key, key);
221  }
222  }
223 
224  losers[0].sup = sup;
225  losers[0].source = source;
226  losers[0].key = key;
227  }
228 };
229 
230 /**
231  * Guarded loser tree/tournament tree, either copying the whole element into
232  * the tree structure, or looking up the element via the index.
233  *
234  * Stable specialization of LoserTreeCopyBase.
235  *
236  * Guarding is done explicitly through one flag sup per element, inf is not
237  * needed due to a better initialization routine. This is a well-performing
238  * variant.
239  *
240  * \tparam ValueType the element type
241  * \tparam Comparator comparator to use for binary comparisons.
242  */
243 template <typename ValueType, typename Comparator>
244 class LoserTreeCopy</* Stable == */ true, ValueType, Comparator>
245  : public LoserTreeCopyBase<ValueType, Comparator>
246 {
247 public:
249 
250  typedef typename base_type::size_type size_type;
252  using base_type::k;
253  using base_type::losers;
254  using base_type::comp;
255 
256  LoserTreeCopy(size_type _k, Comparator _comp = std::less<ValueType>())
257  : base_type(_k, _comp)
258  { }
259 
260  // do not pass const reference since key will be used as local variable
261  void delete_min_insert(ValueType key, bool sup)
262  {
263  using std::swap;
264 
265  source_type source = losers[0].source;
266  for (size_type pos = (k + source) / 2; pos > 0; pos /= 2)
267  {
268  if ((sup && (!losers[pos].sup || losers[pos].source < source)) ||
269  (!sup && !losers[pos].sup &&
270  ((comp(losers[pos].key, key)) ||
271  (!comp(key, losers[pos].key) && losers[pos].source < source))))
272  {
273  // the other one is smaller
274  swap(losers[pos].sup, sup);
275  swap(losers[pos].source, source);
276  swap(losers[pos].key, key);
277  }
278  }
279 
280  losers[0].sup = sup;
281  losers[0].source = source;
282  losers[0].key = key;
283  }
284 };
285 
286 /** Guarded loser tree, either copying the whole element into the tree structure, or looking up the element via the index.
287  *
288  * Guarding is done explicitly through one flag sup per element, inf is not needed due to a better initialization routine.
289  * This is a well-performing variant.
290  */
291 template <typename T, typename Comparator = std::less<T> >
293 {
294 #undef COPY
295 #ifdef COPY
296  #define KEY(i) losers[i].key
297  #define KEY_SOURCE(i) key
298 #else
299  #define KEY(i) keys[losers[i].source]
300  #define KEY_SOURCE(i) keys[i]
301 #endif
302 
303 private:
304  struct Loser
305  {
306  bool sup;
307  int source;
308 #ifdef COPY
309  T key;
310 #endif
311  };
312 
313  unsigned int ik, k;
315 #ifndef COPY
316  T* keys;
317 #endif
318  Comparator comp;
319 
320 public:
321  LoserTreeReference(unsigned int _k, Comparator _comp = std::less<T>()) : comp(_comp)
322  {
323  ik = _k;
324  k = round_up_to_power_of_two(ik);
325  losers = new Loser[k * 2];
326 #ifndef COPY
327  keys = new T[ik];
328 #endif
329  for (unsigned int i = ik - 1; i < k; i++)
330  losers[i + k].sup = true;
331  }
332 
334  {
335  delete[] losers;
336 #ifndef COPY
337  delete[] keys;
338 #endif
339  }
340 
341  void print(std::ostream& os)
342  {
343  for (unsigned int i = 0; i < (k * 2); i++)
344  os << i << " " << KEY(i) << " from " << losers[i].source << ", " << losers[i].sup << "\n";
345  }
346 
348  {
349  return losers[0].source;
350  }
351 
352  void insert_start(T key, int source, bool sup)
353  {
354  unsigned int pos = k + source;
355 
356  losers[pos].sup = sup;
357  losers[pos].source = source;
358  KEY(pos) = key;
359  }
360 
361  unsigned int init_winner(unsigned int root)
362  {
363  if (root >= k)
364  {
365  return root;
366  }
367  else
368  {
369  unsigned int left = init_winner(2 * root);
370  unsigned int right = init_winner(2 * root + 1);
371  if (losers[right].sup ||
372  (!losers[left].sup && !comp(KEY(right), KEY(left))))
373  { //left one is less or equal
374  losers[root] = losers[right];
375  return left;
376  }
377  else
378  { //right one is less
379  losers[root] = losers[left];
380  return right;
381  }
382  }
383  }
384 
385  void init()
386  {
387  losers[0] = losers[init_winner(1)];
388  }
389 
390  void delete_min_insert(T /* key */, bool sup)
391  {
392  using std::swap;
393 
394  int source = losers[0].source;
395  for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
396  {
397  //the smaller one gets promoted
398  if (sup ||
399  (!losers[pos].sup && comp(KEY(pos), KEY_SOURCE(source))))
400  { //the other one is smaller
401  swap(losers[pos].sup, sup);
402  swap(losers[pos].source, source);
403 #ifdef COPY
404  swap(KEY(pos), KEY_SOURCE(source));
405 #endif
406  }
407  }
408 
409  losers[0].sup = sup;
410  losers[0].source = source;
411 #ifdef COPY
412  KEY(0) = KEY_SOURCE(source);
413 #endif
414  }
415 
416  void insert_start_stable(T key, int source, bool sup)
417  {
418  return insert_start(key, source, sup);
419  }
420 
421  unsigned int init_winner_stable(unsigned int root)
422  {
423  if (root >= k)
424  {
425  return root;
426  }
427  else
428  {
429  unsigned int left = init_winner(2 * root);
430  unsigned int right = init_winner(2 * root + 1);
431  if (losers[right].sup ||
432  (!losers[left].sup && !comp(KEY(right), KEY(left))))
433  { //left one is less or equal
434  losers[root] = losers[right];
435  return left;
436  }
437  else
438  { //right one is less
439  losers[root] = losers[left];
440  return right;
441  }
442  }
443  }
444 
445  void init_stable()
446  {
447  losers[0] = losers[init_winner_stable(1)];
448  }
449 
450  void delete_min_insert_stable(T /* key */, bool sup)
451  {
452  using std::swap;
453 
454  int source = losers[0].source;
455  for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
456  {
457  //the smaller one gets promoted, ties are broken by source
458  if ((sup && (!losers[pos].sup || losers[pos].source < source)) ||
459  (!sup && !losers[pos].sup &&
460  ((comp(KEY(pos), KEY_SOURCE(source))) ||
461  (!comp(KEY_SOURCE(source), KEY(pos)) && losers[pos].source < source))))
462  { //the other one is smaller
463  swap(losers[pos].sup, sup);
464  swap(losers[pos].source, source);
465 #ifdef COPY
466  swap(KEY(pos), KEY_SOURCE(source));
467 #endif
468  }
469  }
470 
471  losers[0].sup = sup;
472  losers[0].source = source;
473 #ifdef COPY
474  KEY(0) = KEY_SOURCE(source);
475 #endif
476  }
477 };
478 #undef KEY
479 #undef KEY_SOURCE
480 
481 /**
482  * Guarded loser tree, using pointers to the elements instead of copying them
483  * into the tree nodes.
484  *
485  * This is a base class for the LoserTreePointer<true> and <false> classes.
486  *
487  * Guarding is done explicitly through one flag sup per element, inf is not
488  * needed due to a better initialization routine. This is a well-performing
489  * variant.
490  */
491 template <typename ValueType, typename Comparator = std::less<ValueType> >
493 {
494 public:
495  //! size of counters and array indexes
498  //! type of the source field
501 
502 protected:
503  //! Internal representation of a loser tree player/node
504  struct Loser
505  {
506  //! flag, true iff is a virtual maximum sentinel
507  bool sup;
508  //! index of source
510  //! pointer to key value of the element in this node
511  const ValueType* keyp;
512  };
513 
514  //! number of nodes
515  const size_type ik;
516  //! log_2(ik) next greater power of 2
517  const size_type k;
518  //! array containing loser tree nodes
520  //! the comparator object
521  Comparator comp;
522 
523 public:
525  Comparator _comp = std::less<ValueType>())
526  : ik(_k),
528  losers(new Loser[k * 2]),
529  comp(_comp)
530  {
531  for (size_type i = ik - 1; i < k; i++)
532  {
533  losers[i + k].sup = true;
534  losers[i + k].source = (source_type)(-1);
535  }
536  }
537 
539  {
540  delete[] losers;
541  }
542 
543  void print(std::ostream& os)
544  {
545  for (size_type i = 0; i < (k * 2); i++)
546  os << i << " " << losers[i].keyp << " from " << losers[i].source << ", " << losers[i].sup << "\n";
547  }
548 
549  //! return the index of the player with the smallest element.
551  {
552  return losers[0].source;
553  }
554 
555  /**
556  * Initializes the player source with the element key.
557  *
558  * \param key the element to insert
559  * \param source index of the player
560  * \param sup flag that determines whether the value to insert is an
561  * explicit supremum sentinel.
562  */
563  void insert_start(const ValueType& key, source_type source, bool sup)
564  {
565  size_type pos = k + source;
566 
567  losers[pos].sup = sup;
568  losers[pos].source = source;
569  losers[pos].keyp = &key;
570  }
571 
572  /**
573  * Computes the winner of the competition at player root. Called
574  * recursively (starting at 0) to build the initial tree.
575  *
576  * \param root index of the game to start.
577  */
579  {
580  if (root >= k)
581  {
582  return root;
583  }
584  else
585  {
586  size_type left = init_winner(2 * root);
587  size_type right = init_winner(2 * root + 1);
588  if (losers[right].sup ||
589  (!losers[left].sup && !comp(*losers[right].keyp, *losers[left].keyp)))
590  { //left one is less or equal
591  losers[root] = losers[right];
592  return left;
593  }
594  else
595  { //right one is less
596  losers[root] = losers[left];
597  return right;
598  }
599  }
600  }
601 
602  void init()
603  {
604  losers[0] = losers[init_winner(1)];
605  }
606 };
607 
608 /**
609  * Guarded loser tree, using pointers to the elements instead of copying them
610  * into the tree nodes.
611  *
612  * Unstable specialization of LoserTreeCopyBase.
613  *
614  * Guarding is done explicitly through one flag sup per element, inf is not
615  * needed due to a better initialization routine. This is a well-performing
616  * variant.
617  */
618 template <bool Stable /* == false */,
619  typename ValueType, typename Comparator = std::less<ValueType> >
620 class LoserTreePointer : public LoserTreePointerBase<ValueType, Comparator>
621 {
622 public:
624 
625  typedef typename base_type::size_type size_type;
627  using base_type::k;
628  using base_type::losers;
629  using base_type::comp;
630 
631  LoserTreePointer(size_type _k, Comparator _comp = std::less<ValueType>())
632  : base_type(_k, _comp)
633  { }
634 
635  void delete_min_insert(const ValueType& key, bool sup)
636  {
637  using std::swap;
638 
639  const ValueType* keyp = &key;
640  source_type source = losers[0].source;
641  for (size_type pos = (k + source) / 2; pos > 0; pos /= 2)
642  {
643  //the smaller one gets promoted
644  if (sup ||
645  (!losers[pos].sup && comp(*losers[pos].keyp, *keyp)))
646  { //the other one is smaller
647  swap(losers[pos].sup, sup);
648  swap(losers[pos].source, source);
649  swap(losers[pos].keyp, keyp);
650  }
651  }
652 
653  losers[0].sup = sup;
654  losers[0].source = source;
655  losers[0].keyp = keyp;
656  }
657 };
658 
659 /**
660  * Guarded loser tree, using pointers to the elements instead of copying them
661  * into the tree nodes.
662  *
663  * Unstable specialization of LoserTreeCopyBase.
664  *
665  * Guarding is done explicitly through one flag sup per element, inf is not
666  * needed due to a better initialization routine. This is a well-performing
667  * variant.
668  */
669 template <typename ValueType, typename Comparator>
670 class LoserTreePointer</* Stable == */ true, ValueType, Comparator>
671  : public LoserTreePointerBase<ValueType, Comparator>
672 {
673 public:
675 
676  typedef typename base_type::size_type size_type;
678  using base_type::k;
679  using base_type::losers;
680  using base_type::comp;
681 
682  LoserTreePointer(size_type _k, Comparator _comp = std::less<ValueType>())
683  : base_type(_k, _comp)
684  { }
685 
686  void delete_min_insert(const ValueType& key, bool sup)
687  {
688  using std::swap;
689 
690  const ValueType* keyp = &key;
691  source_type source = losers[0].source;
692  for (size_type pos = (k + source) / 2; pos > 0; pos /= 2)
693  {
694  //the smaller one gets promoted, ties are broken by source
695  if ((sup && (!losers[pos].sup || losers[pos].source < source)) ||
696  (!sup && !losers[pos].sup &&
697  ((comp(*losers[pos].keyp, *keyp)) ||
698  (!comp(*keyp, *losers[pos].keyp) && losers[pos].source < source))))
699  { //the other one is smaller
700  swap(losers[pos].sup, sup);
701  swap(losers[pos].source, source);
702  swap(losers[pos].keyp, keyp);
703  }
704  }
705 
706  losers[0].sup = sup;
707  losers[0].source = source;
708  losers[0].keyp = keyp;
709  }
710 };
711 
712 /**
713  * Unguarded loser tree, copying the whole element into the tree structure.
714  *
715  * This is a base class for the LoserTreeCopyUnguarded<true> and <false>
716  * classes.
717  *
718  * No guarding is done, therefore not a single input sequence must run empty.
719  * This is a very fast variant.
720  */
721 template <typename ValueType, typename Comparator = std::less<ValueType> >
723 {
724 protected:
725  //! Internal representation of a loser tree player/node
726  struct Loser
727  {
728  //! index of source
729  int source;
730  //! copy of key value of the element in this node
731  ValueType key;
732  };
733 
734  //! number of nodes
735  unsigned int ik;
736  //! log_2(ik) next greater power of 2
737  unsigned int k;
738  //! array containing loser tree nodes
740  //! the comparator object
741  Comparator comp;
742 
743 public:
744  LoserTreeCopyUnguardedBase(unsigned int _k, const ValueType& _sentinel,
745  Comparator _comp = std::less<ValueType>())
746  : ik(_k),
748  losers(new Loser[k * 2]),
749  comp(_comp)
750  {
751  for (unsigned int i = 0; i < 2 * k; i++)
752  {
753  losers[i].source = -1;
754  losers[i].key = _sentinel;
755  }
756  }
757 
759  {
760  delete[] losers;
761  }
762 
763  void print(std::ostream& os)
764  {
765  for (unsigned int i = 0; i < k + ik; i++)
766  os << i << " " << losers[i].key << " from " << losers[i].source << "\n";
767  }
768 
769  //! return the index of the player with the smallest element.
771  {
772  assert(losers[0].source != -1 && "Data underrun in unguarded merging.");
773  return losers[0].source;
774  }
775 
776  void insert_start(const ValueType& key, int source)
777  {
778  unsigned int pos = k + source;
779 
780  losers[pos].source = source;
781  losers[pos].key = key;
782  }
783 
784  unsigned int init_winner(unsigned int root)
785  {
786  if (root >= k)
787  {
788  return root;
789  }
790  else
791  {
792  unsigned int left = init_winner(2 * root);
793  unsigned int right = init_winner(2 * root + 1);
794  if (!comp(losers[right].key, losers[left].key))
795  { //left one is less or equal
796  losers[root] = losers[right];
797  return left;
798  }
799  else
800  { //right one is less
801  losers[root] = losers[left];
802  return right;
803  }
804  }
805  }
806 
807  void init()
808  {
809  losers[0] = losers[init_winner(1)];
810  }
811 };
812 
813 template <bool Stable /* == false */,
814  typename ValueType, typename Comparator = std::less<ValueType> >
815 class LoserTreeCopyUnguarded : public LoserTreeCopyUnguardedBase<ValueType, Comparator>
816 {
817 protected:
819 
820  using base_type::k;
821  using base_type::losers;
822  using base_type::comp;
823 
824 public:
825  LoserTreeCopyUnguarded(unsigned int _k, const ValueType& _sentinel,
826  Comparator _comp = std::less<ValueType>())
827  : base_type(_k, _sentinel, _comp)
828  { }
829 
830  // do not pass const reference since key will be used as local variable
831  void delete_min_insert(ValueType key)
832  {
833  using std::swap;
834 
835  int source = losers[0].source;
836  for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
837  {
838  // the smaller one gets promoted
839  if (comp(losers[pos].key, key))
840  {
841  // the other one is smaller
842  swap(losers[pos].source, source);
843  swap(losers[pos].key, key);
844  }
845  }
846 
847  losers[0].source = source;
848  losers[0].key = key;
849  }
850 };
851 
852 template <typename ValueType, typename Comparator>
853 class LoserTreeCopyUnguarded</* Stable == */ true, ValueType, Comparator>
854  : public LoserTreeCopyUnguardedBase<ValueType, Comparator>
855 {
856 protected:
858 
859  using base_type::k;
860  using base_type::losers;
861  using base_type::comp;
862 
863 public:
864  LoserTreeCopyUnguarded(unsigned int _k, const ValueType& _sentinel,
865  Comparator _comp = std::less<ValueType>())
866  : base_type(_k, _sentinel, _comp)
867  { }
868 
869  // do not pass const reference since key will be used as local variable
870  void delete_min_insert(ValueType key)
871  {
872  using std::swap;
873 
874  int source = losers[0].source;
875  for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
876  {
877  if (!comp(key, losers[pos].key) && losers[pos].source < source)
878  {
879  // the other one is smaller
880  swap(losers[pos].source, source);
881  swap(losers[pos].key, key);
882  }
883  }
884 
885  losers[0].source = source;
886  losers[0].key = key;
887  }
888 };
889 
890 /**
891  * Unguarded loser tree, keeping only pointers to the elements in the tree
892  * structure.
893  *
894  * This is a base class for the LoserTreePointerUnguarded<true> and <false>
895  * classes.
896  *
897  * No guarding is done, therefore not a single input sequence must run empty.
898  * This is a very fast variant.
899  */
900 template <typename ValueType, typename Comparator = std::less<ValueType> >
902 {
903 protected:
904  //! Internal representation of a loser tree player/node
905  struct Loser
906  {
907  //! index of source
908  int source;
909  //! copy of key value of the element in this node
910  const ValueType* keyp;
911  };
912 
913  //! number of nodes
914  unsigned int ik;
915  //! log_2(ik) next greater power of 2
916  unsigned int k;
917  //! array containing loser tree nodes
919  //! the comparator object
920  Comparator comp;
921 
922 public:
923  LoserTreePointerUnguardedBase(unsigned int _k, const ValueType& _sentinel,
924  Comparator _comp = std::less<ValueType>())
925  : ik(_k),
927  losers(new Loser[k * 2]),
928  comp(_comp)
929  {
930  for (unsigned int i = ik - 1; i < k; i++)
931  {
932  losers[i + k].source = -1;
933  losers[i + k].keyp = &_sentinel;
934  }
935  }
936 
938  {
939  delete[] losers;
940  }
941 
942  void print(std::ostream& os)
943  {
944  for (unsigned int i = 0; i < k + ik; i++)
945  os << i << " " << *losers[i].keyp << " from " << losers[i].source << "\n";
946  }
947 
949  {
950  return losers[0].source;
951  }
952 
953  void insert_start(const ValueType& key, int source)
954  {
955  unsigned int pos = k + source;
956 
957  losers[pos].source = source;
958  losers[pos].keyp = &key;
959  }
960 
961  unsigned int init_winner(unsigned int root)
962  {
963  if (root >= k)
964  {
965  return root;
966  }
967  else
968  {
969  unsigned int left = init_winner(2 * root);
970  unsigned int right = init_winner(2 * root + 1);
971  if (!comp(*losers[right].keyp, *losers[left].keyp))
972  { //left one is less or equal
973  losers[root] = losers[right];
974  return left;
975  }
976  else
977  { //right one is less
978  losers[root] = losers[left];
979  return right;
980  }
981  }
982  }
983 
984  void init()
985  {
986  losers[0] = losers[init_winner(1)];
987  }
988 };
989 
990 template <bool Stable /* == false */,
991  typename ValueType, typename Comparator = std::less<ValueType> >
993  : public LoserTreePointerUnguardedBase<ValueType, Comparator>
994 {
995 protected:
997 
998  using base_type::k;
999  using base_type::losers;
1000  using base_type::comp;
1001 
1002 public:
1003  LoserTreePointerUnguarded(unsigned int _k, const ValueType& _sentinel,
1004  Comparator _comp = std::less<ValueType>())
1005  : base_type(_k, _sentinel, _comp)
1006  { }
1007 
1008  void delete_min_insert(const ValueType& key)
1009  {
1010  using std::swap;
1011 
1012  const ValueType* keyp = &key;
1013  int source = losers[0].source;
1014  for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
1015  {
1016  //the smaller one gets promoted
1017  if (comp(*losers[pos].keyp, *keyp))
1018  {
1019  //the other one is smaller
1020  swap(losers[pos].source, source);
1021  swap(losers[pos].keyp, keyp);
1022  }
1023  }
1024 
1025  losers[0].source = source;
1026  losers[0].keyp = keyp;
1027  }
1028 };
1029 
1030 template <typename ValueType, typename Comparator>
1031 class LoserTreePointerUnguarded</* Stable == */ true, ValueType, Comparator>
1032  : public LoserTreePointerUnguardedBase<ValueType, Comparator>
1033 {
1034 protected:
1036 
1037  using base_type::k;
1038  using base_type::losers;
1039  using base_type::comp;
1040 
1041 public:
1042  LoserTreePointerUnguarded(unsigned int _k, const ValueType& _sentinel,
1043  Comparator _comp = std::less<ValueType>())
1044  : base_type(_k, _sentinel, _comp)
1045  { }
1046 
1047  void delete_min_insert(const ValueType& key)
1048  {
1049  using std::swap;
1050 
1051  const ValueType* keyp = &key;
1052  int source = losers[0].source;
1053  for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
1054  {
1055  //the smaller one gets promoted, ties are broken by source
1056  if (comp(*losers[pos].keyp, *keyp) ||
1057  (!comp(*keyp, *losers[pos].keyp) && losers[pos].source < source))
1058  {
1059  //the other one is smaller
1060  swap(losers[pos].source, source);
1061  swap(losers[pos].keyp, keyp);
1062  }
1063  }
1064 
1065  losers[0].source = source;
1066  losers[0].keyp = keyp;
1067  }
1068 };
1069 
1070 } // namespace parallel
1071 
1073 
1074 #endif // !STXXL_PARALLEL_LOSERTREE_HEADER
void insert_start(T key, int source, bool sup)
Definition: losertree.h:352
unsigned int init_winner(unsigned int root)
Definition: losertree.h:961
LoserTreePointerUnguardedBase< ValueType, Comparator > base_type
Definition: losertree.h:1035
Loser * losers
array containing loser tree nodes
Definition: losertree.h:918
source_type get_min_source()
return the index of the player with the smallest element.
Definition: losertree.h:108
base_type::source_type source_type
Definition: losertree.h:626
const size_type k
log_2(ik) next greater power of 2
Definition: losertree.h:67
Internal representation of a loser tree player/node.
Definition: losertree.h:54
const size_type k
log_2(ik) next greater power of 2
Definition: losertree.h:517
source_type source
index of source
Definition: losertree.h:509
Internal representation of a loser tree player/node.
Definition: losertree.h:726
Loser * losers
array containing loser tree nodes
Definition: losertree.h:519
base_type::size_type size_type
Definition: losertree.h:625
Comparator comp
the comparator object
Definition: losertree.h:71
bool sup
flag, true iff is a virtual maximum sentinel
Definition: losertree.h:507
void insert_start(const ValueType &key, int source)
Definition: losertree.h:776
unsigned int init_winner(unsigned int root)
Definition: losertree.h:784
source_type get_min_source()
return the index of the player with the smallest element.
Definition: losertree.h:550
LoserTreeCopyUnguarded(unsigned int _k, const ValueType &_sentinel, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:825
LoserTreePointerUnguarded(unsigned int _k, const ValueType &_sentinel, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:1042
LoserTreeCopyUnguardedBase(unsigned int _k, const ValueType &_sentinel, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:744
LoserTreePointerBase< ValueType, Comparator > base_type
Definition: losertree.h:674
LoserTreePointerUnguarded(unsigned int _k, const ValueType &_sentinel, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:1003
base_type::size_type size_type
Definition: losertree.h:195
void print(std::ostream &os)
Definition: losertree.h:341
void print(std::ostream &os)
Definition: losertree.h:101
LoserTreePointerBase(size_type _k, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:524
LoserTreeCopyBase< ValueType, Comparator >::size_type size_type
size of counters and array indexes
Definition: losertree.h:497
ValueType key
copy of key value of the element in this node
Definition: losertree.h:731
#define KEY(i)
Definition: losertree.h:299
bool first_insert
still have to construct keys
Definition: losertree.h:73
void delete_min_insert(T, bool sup)
Definition: losertree.h:390
#define KEY_SOURCE(i)
Definition: losertree.h:300
unsigned int k
log_2(ik) next greater power of 2
Definition: losertree.h:916
LoserTreeCopyBase< ValueType, Comparator > base_type
Definition: losertree.h:248
ValueType key
copy of key value of the element in this node
Definition: losertree.h:61
LoserTreeCopyUnguarded(unsigned int _k, const ValueType &_sentinel, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:864
LoserTreeCopyUnguardedBase< ValueType, Comparator > base_type
Definition: losertree.h:857
#define UNLIKELY(c)
Definition: utils.h:225
LoserTreePointerBase< ValueType, Comparator > base_type
Definition: losertree.h:623
LoserTreeReference(unsigned int _k, Comparator _comp=std::less< T >())
Definition: losertree.h:321
LoserTreeCopyBase< ValueType, Comparator > base_type
Definition: losertree.h:193
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
void insert_start(const ValueType &key, source_type source, bool sup)
Definition: losertree.h:121
unsigned int size_type
size of counters and array indexes
Definition: losertree.h:48
LoserTreeCopyBase(size_type _k, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:76
int source_type
type of the source field
Definition: losertree.h:50
LoserTreePointerUnguardedBase(unsigned int _k, const ValueType &_sentinel, Comparator _comp=std::less< ValueType >())
Definition: losertree.h:923
Loser * losers
array containing loser tree nodes
Definition: losertree.h:69
void delete_min_insert(const ValueType &key)
Definition: losertree.h:1008
const size_type ik
number of nodes
Definition: losertree.h:515
unsigned int ik
number of nodes
Definition: losertree.h:735
void insert_start_stable(T key, int source, bool sup)
Definition: losertree.h:416
unsigned int init_winner(unsigned int root)
Definition: losertree.h:361
const ValueType * keyp
copy of key value of the element in this node
Definition: losertree.h:910
Comparator comp
the comparator object
Definition: losertree.h:920
LoserTreePointerUnguardedBase< ValueType, Comparator > base_type
Definition: losertree.h:996
Comparator comp
the comparator object
Definition: losertree.h:741
size_type init_winner(size_type root)
Definition: losertree.h:145
LoserTreeCopyBase< ValueType, Comparator >::source_type source_type
type of the source field
Definition: losertree.h:500
Loser * losers
array containing loser tree nodes
Definition: losertree.h:739
void insert_start(const ValueType &key, source_type source, bool sup)
Definition: losertree.h:563
LoserTreeCopyUnguardedBase< ValueType, Comparator > base_type
Definition: losertree.h:818
unsigned int k
log_2(ik) next greater power of 2
Definition: losertree.h:737
const size_type ik
number of nodes
Definition: losertree.h:65
void print(std::ostream &os)
Definition: losertree.h:543
const ValueType * keyp
pointer to key value of the element in this node
Definition: losertree.h:511
size_type init_winner(size_type root)
Definition: losertree.h:578
void delete_min_insert(ValueType key)
Definition: losertree.h:831
bool sup
flag, true iff is a virtual maximum sentinel
Definition: losertree.h:57
source_type source
index of source
Definition: losertree.h:59
Internal representation of a loser tree player/node.
Definition: losertree.h:905
Comparator comp
the comparator object
Definition: losertree.h:521
void delete_min_insert_stable(T, bool sup)
Definition: losertree.h:450
static Integral round_up_to_power_of_two(Integral n)
Definition: utils.h:255
Internal representation of a loser tree player/node.
Definition: losertree.h:504
unsigned int init_winner_stable(unsigned int root)
Definition: losertree.h:421
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
base_type::source_type source_type
Definition: losertree.h:196
int get_min_source()
return the index of the player with the smallest element.
Definition: losertree.h:770
void insert_start(const ValueType &key, int source)
Definition: losertree.h:953