COMBINATORIAL_BLAS 1.6
 
Loading...
Searching...
No Matches
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
6const int KNBufferSize1 = 32; // equalize procedure call overheads etc.
7const int KNN = 128; // bandwidth (also size of the binary heap)
8const int KNKMAX = 128; // maximal arity
9const int KNLevels = 4; // overall capacity >= KNN*KNKMAX^KNLevels
10const int LogKNKMAX = 7; // ceil(log KNK)
11/*
12const int KNBufferSize1 = 3; // equalize procedure call overheads etc.
13const int KNN = 10; // bandwidth
14const int KNKMAX = 4; // maximal arity
15const int KNLevels = 4; // overall capacity >= KNN*KNKMAX^KNLevels
16const int LogKNKMAX = 2; // ceil(log KNK)
17*/
18template <class Key, class Value>
19struct KNElement {Key key; Value value;};
20
22// fixed size binary heap
23template <class Key, class Value, int capacity>
25 // static const Key infimum = 4;
26 //static const Key supremum = numeric_limits<Key>.max();
28 Element data[capacity + 2];
29 int size; // index of last used element
30public:
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
54template <class Key, class Value, int capacity>
56reset() {
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
67template <class Key, class Value, int capacity>
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
112template <class Key, class Value, int capacity>
114sortTo(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
150template <class Key, class Value, int capacity>
152insert(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
176template <class Key, class Value>
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
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);
216public:
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);
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
241template <class Key, class Value>
242class KNHeap {
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
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]; }
276public:
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
285template <class Key, class Value>
287{
288 return
289 size +
290 insertHeap.getSize() +
291 ((buffer1 + KNBufferSize1) - minBuffer1);
292}
293
294template <class Key, class Value>
295inline 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
307template <class Key, class Value>
308inline 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
326template <class Key, class Value>
327inline 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()
Definition knheap.h:69
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)
Definition knheap.h:114
void insert(Key k, Value v)
Definition knheap.h:152
Value getMinValue() const
Definition knheap.h:40
void reset()
Definition knheap.h:56
void insert(Key key, Value value)
Definition knheap.h:327
void deleteMin(Key *key, Value *value)
Definition knheap.h:308
KNHeap(Key sup, Key infimum)
void getMin(Key *key, Value *value)
Definition knheap.h:295
int getSize() const
Definition knheap.h:286
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
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
Value value
Definition heap-CLR.h:7
Key key
Definition heap-CLR.h:7