COMBINATORIAL_BLAS  1.6
knheap.h
Go to the documentation of this file.
1 // hierarchical memory priority queue data structure
2 #ifndef KNHEAP
3 #define KNHEAP
4 #include "util.h"
5 
6 const int KNBufferSize1 = 32; // equalize procedure call overheads etc.
7 const int KNN = 128; // bandwidth (also size of the binary heap)
8 const int KNKMAX = 128; // maximal arity
9 const int KNLevels = 4; // overall capacity >= KNN*KNKMAX^KNLevels
10 const int LogKNKMAX = 7; // ceil(log KNK)
11 /*
12 const int KNBufferSize1 = 3; // equalize procedure call overheads etc.
13 const int KNN = 10; // bandwidth
14 const int KNKMAX = 4; // maximal arity
15 const int KNLevels = 4; // overall capacity >= KNN*KNKMAX^KNLevels
16 const int LogKNKMAX = 2; // ceil(log KNK)
17 */
18 template <class Key, class Value>
19 struct KNElement {Key key; Value value;};
20 
22 // fixed size binary heap
23 template <class Key, class Value, int capacity>
24 class BinaryHeap {
25  // static const Key infimum = 4;
26  //static const Key supremum = numeric_limits<Key>.max();
27  typedef KNElement<Key, Value> Element;
28  Element data[capacity + 2];
29  int size; // index of last used element
30 public:
31  BinaryHeap(Key sup, Key infimum):size(0) {
32  data[0].key = infimum; // sentinel
33  data[capacity + 1].key = sup;
34  reset();
35  }
36  Key getSupremum() { return data[capacity + 1].key; }
37  void reset();
38  int getSize() const { return size; }
39  Key getMinKey() const { return data[1].key; }
40  Value getMinValue() const { return data[1].value; }
41  void deleteMin();
42  void deleteMinFancy(Key *key, Value *value) {
43  *key = getMinKey();
44  *value = getMinValue();
45  deleteMin();
46  }
47  void insert(Key k, Value v);
48  void sortTo(Element *to); // sort in increasing order and empty
49  //void sortInPlace(); // in decreasing order
50 };
51 
52 
53 // reset size to 0 and fill data array with sentinels
54 template <class Key, class Value, int capacity>
56 reset() {
57  size = 0;
58  Key sup = getSupremum();
59  for (int i = 1; i <= capacity; i++) {
60  data[i].key = sup;
61  }
62  // if this becomes a bottle neck
63  // we might want to replace this by log KNN
64  // memcpy-s
65 }
66 
67 template <class Key, class Value, int capacity>
69 deleteMin()
70 {
71  Assert2(size > 0);
72 
73  // first move up elements on a min-path
74  int hole = 1;
75  int succ = 2;
76  int sz = size;
77  while (succ < sz) {
78  Key key1 = data[succ].key;
79  Key key2 = data[succ + 1].key;
80  if (key1 > key2) {
81  succ++;
82  data[hole].key = key2;
83  data[hole].value = data[succ].value;
84  } else {
85  data[hole].key = key1;
86  data[hole].value = data[succ].value;
87  }
88  hole = succ;
89  succ <<= 1;
90  }
91 
92  // bubble up rightmost element
93  Key bubble = data[sz].key;
94  int pred = hole >> 1;
95  while (data[pred].key > bubble) { // must terminate since min at root
96  data[hole] = data[pred];
97  hole = pred;
98  pred >>= 1;
99  }
100 
101  // finally move data to hole
102  data[hole].key = bubble;
103  data[hole].value = data[sz].value;
104 
105  data[size].key = getSupremum(); // mark as deleted
106  size = sz - 1;
107 }
108 
109 
110 // empty the heap and put the element to "to"
111 // sorted in increasing order
112 template <class Key, class Value, int capacity>
114 sortTo(Element *to)
115 {
116  const int sz = size;
117  const Key sup = getSupremum();
118  Element * const beyond = to + sz;
119  Element * const root = data + 1;
120  while (to < beyond) {
121  // copy minimun
122  *to = *root;
123  to++;
124 
125  // bubble up second smallest as in deleteMin
126  int hole = 1;
127  int succ = 2;
128  while (succ <= sz) {
129  Key key1 = data[succ ].key;
130  Key key2 = data[succ + 1].key;
131  if (key1 > key2) {
132  succ++;
133  data[hole].key = key2;
134  data[hole].value = data[succ].value;
135  } else {
136  data[hole].key = key1;
137  data[hole].value = data[succ].value;
138  }
139  hole = succ;
140  succ <<= 1;
141  }
142 
143  // just mark hole as deleted
144  data[hole].key = sup;
145  }
146  size = 0;
147 }
148 
149 
150 template <class Key, class Value, int capacity>
152 insert(Key k, Value v)
153 {
154  Assert2(size < capacity);
155  Debug4(cout << "insert(" << k << ", " << v << ")" << endl);
156 
157  size++;
158  int hole = size;
159  int pred = hole >> 1;
160  Key predKey = data[pred].key;
161  while (predKey > k) { // must terminate due to sentinel at 0
162  data[hole].key = predKey;
163  data[hole].value = data[pred].value;
164  hole = pred;
165  pred >>= 1;
166  predKey = data[pred].key;
167  }
168 
169  // finally move data to hole
170  data[hole].key = k;
171  data[hole].value = v;
172 }
173 
175 // The data structure from Knuth, "Sorting and Searching", Section 5.4.1
176 template <class Key, class Value>
177 class KNLooserTree {
178  // public: // should not be here but then I would need a scary
179  // sequence of template friends which I doubt to work
180  // on all compilers
181  typedef KNElement<Key, Value> Element;
182  struct Entry {
183  Key key; // Key of Looser element (winner for 0)
184  int index; // number of loosing segment
185  };
186 
187  // stack of empty segments
188  int empty[KNKMAX]; // indices of empty segments
189  int lastFree; // where in "empty" is the last valid entry?
190 
191  int size; // total number of elements stored
192  int logK; // log of current tree size
193  int k; // invariant k = 1 << logK
194 
195  Element dummy; // target of empty segment pointers
196 
197  // upper levels of looser trees
198  // entry[0] contains the winner info
199  Entry entry[KNKMAX];
200 
201  // leaf information
202  // note that Knuth uses indices k..k-1
203  // while we use 0..k-1
204  Element *current[KNKMAX]; // pointer to actual element
205  Element *segment[KNKMAX]; // start of Segments
206 
207  // private member functions
208  int initWinner(int root);
209  void updateOnInsert(int node, Key newKey, int newIndex,
210  Key *winnerKey, int *winnerIndex, int *mask);
211  void deallocateSegment(int index);
212  void doubleK();
213  void compactTree();
214  void rebuildLooserTree();
215  int segmentIsEmpty(int i);
216 public:
218  void init(Key sup); // before, no consistent state is reached :-(
219 
220  void multiMergeUnrolled3(Element *to, int l);
221  void multiMergeUnrolled4(Element *to, int l);
222  void multiMergeUnrolled5(Element *to, int l);
223  void multiMergeUnrolled6(Element *to, int l);
224  void multiMergeUnrolled7(Element *to, int l);
225  void multiMergeUnrolled8(Element *to, int l);
226  void multiMergeUnrolled9(Element *to, int l);
227  void multiMergeUnrolled10(Element *to, int l);
228 
229  void multiMerge(Element *to, int l); // delete l smallest element to "to"
230  void multiMergeK(Element *to, int l);
231  int spaceIsAvailable() { return k < KNKMAX || lastFree >= 0; }
232  // for new segment
233  void insertSegment(Element *to, int sz); // insert segment beginning at to
234  int getSize() { return size; }
235  Key getSupremum() { return dummy.key; }
236 };
237 
238 
240 // 2 level multi-merge tree
241 template <class Key, class Value>
242 class KNHeap {
243  typedef KNElement<Key, Value> Element;
244 
246 
247  // one delete buffer for each tree (extra space for sentinel)
248  Element buffer2[KNLevels][KNN + 1]; // tree->buffer2->buffer1
249  Element *minBuffer2[KNLevels];
250 
251  // overall delete buffer
252  Element buffer1[KNBufferSize1 + 1];
253  Element *minBuffer1;
254 
255  // insert buffer
256  BinaryHeap<Key, Value, KNN> insertHeap;
257 
258  // how many levels are active
259  int activeLevels;
260 
261  // total size not counting insertBuffer and buffer1
262  int size;
263 
264  // private member functions
265  void refillBuffer1();
266  void refillBuffer11(int sz);
267  void refillBuffer12(int sz);
268  void refillBuffer13(int sz);
269  void refillBuffer14(int sz);
270  int refillBuffer2(int k);
271  int makeSpaceAvailable(int level);
272  void emptyInsertHeap();
273  Key getSupremum() const { return buffer2[0][KNN].key; }
274  int getSize1( ) const { return ( buffer1 + KNBufferSize1) - minBuffer1; }
275  int getSize2(int i) const { return &(buffer2[i][KNN]) - minBuffer2[i]; }
276 public:
277  KNHeap(Key sup, Key infimum);
278  int getSize() const;
279  void getMin(Key *key, Value *value);
280  void deleteMin(Key *key, Value *value);
281  void insert(Key key, Value value);
282 };
283 
284 
285 template <class Key, class Value>
286 inline int KNHeap<Key, Value>::getSize() const
287 {
288  return
289  size +
290  insertHeap.getSize() +
291  ((buffer1 + KNBufferSize1) - minBuffer1);
292 }
293 
294 template <class Key, class Value>
295 inline void KNHeap<Key, Value>::getMin(Key *key, Value *value) {
296  Key key1 = minBuffer1->key;
297  Key key2 = insertHeap.getMinKey();
298  if (key2 >= key1) {
299  *key = key1;
300  *value = minBuffer1->value;
301  } else {
302  *key = key2;
303  *value = insertHeap.getMinValue();
304  }
305 }
306 
307 template <class Key, class Value>
308 inline void KNHeap<Key, Value>::deleteMin(Key *key, Value *value) {
309  Key key1 = minBuffer1->key;
310  Key key2 = insertHeap.getMinKey();
311  if (key2 >= key1) {
312  *key = key1;
313  *value = minBuffer1->value;
314  Assert2(minBuffer1 < buffer1 + KNBufferSize1); // no delete from empty
315  minBuffer1++;
316  if (minBuffer1 == buffer1 + KNBufferSize1) {
317  refillBuffer1();
318  }
319  } else {
320  *key = key2;
321  *value = insertHeap.getMinValue();
322  insertHeap.deleteMin();
323  }
324 }
325 
326 template <class Key, class Value>
327 inline void KNHeap<Key, Value>::insert(Key k, Value v) {
328  if (insertHeap.getSize() == KNN) { emptyInsertHeap(); }
329  insertHeap.insert(k, v);
330 }
331 #endif
void deleteMin()
void deleteMinFancy(Key *key, Value *value)
Definition: knheap.h:42
int getSize() const
Definition: knheap.h:38
BinaryHeap(Key sup, Key infimum)
Definition: knheap.h:31
Key getMinKey() const
Definition: knheap.h:39
Key getSupremum()
Definition: knheap.h:36
void sortTo(Element *to)
void insert(Key k, Value v)
Value getMinValue() const
Definition: knheap.h:40
void reset()
Definition: knheap.h:56
Definition: knheap.h:242
void insert(Key key, Value value)
void deleteMin(Key *key, Value *value)
KNHeap(Key sup, Key infimum)
void getMin(Key *key, Value *value)
int getSize() const
void init(Key sup)
void multiMergeUnrolled7(Element *to, int l)
void multiMergeUnrolled8(Element *to, int l)
void multiMergeUnrolled5(Element *to, int l)
void multiMerge(Element *to, int l)
void multiMergeUnrolled6(Element *to, int l)
void multiMergeUnrolled10(Element *to, int l)
void multiMergeK(Element *to, int l)
int spaceIsAvailable()
Definition: knheap.h:231
int getSize()
Definition: knheap.h:234
void insertSegment(Element *to, int sz)
Key getSupremum()
Definition: knheap.h:235
void multiMergeUnrolled9(Element *to, int l)
void multiMergeUnrolled3(Element *to, int l)
void multiMergeUnrolled4(Element *to, int l)
int size
Definition: common.h:20
const int KNN
Definition: knheap.h:7
const int KNKMAX
Definition: knheap.h:8
const int KNLevels
Definition: knheap.h:9
const int KNBufferSize1
Definition: knheap.h:6
const int LogKNKMAX
Definition: knheap.h:10
#define Debug4(A)
Definition: util.h:44
#define Assert2(C)
Definition: util.h:61
Value value
Definition: heap-CLR.h:7
Key key
Definition: heap-CLR.h:7