COMBINATORIAL_BLAS  1.6
heap4.h
Go to the documentation of this file.
1 // 4ary heap data structure
2 #ifndef HEAP4
3 #define HEAP4
4 #include "util.h"
5 
6 const unsigned long LineSize = 64; // cache line size (or multiple)
7 
8 template <class Key, class Value>
9 struct KNElement {Key key; Value value;};
10 
11 // align an address
12 // require: sz is a power of two
13 inline char *knAlign(void *p, unsigned long sz)
14 {
15  return (char*)(((unsigned long)p + (sz - 1)) & ~(sz - 1));
16 }
17 // fixed size 4-ary heap
18 template <class Key, class Value>
19 class Heap4 {
20  // static const Key infimum = 4;
21  //static const Key supremum = numeric_limits<Key>.max();
22  typedef KNElement<Key, Value> Element;
23  int capacity;
24  Element * rawData;
25  Element * const data; // aligned version of rawData
26  int size; // index of last used element
27  int finalLayerSize; // size of first layer with free space
28  int finalLayerDist; // distance to end of layer
29 public:
30  Heap4(Key sup, Key infimum, int cap) :
31  capacity(cap),
32  rawData(new Element[capacity + 4 + (LineSize-1)/sizeof(Element) + 1]),
33  data((Element*)knAlign(rawData, LineSize))
34  {
35  data[0].key = infimum; // sentinel
36  data[capacity + 1].key = sup;
37  data[capacity + 2].key = sup;
38  data[capacity + 3].key = sup;
39  reset();
40  }
41 
42  ~Heap4() { delete [] rawData; }
43  Key getSupremum() { return data[capacity + 1].key; }
44  void reset();
45  int getSize() const { return size; }
46  Key getMinKey() const { return data[1].key; }
47  Value getMinValue() const { return data[1].value; }
49  void deleteMin(Key *key, Value *value);
50  void insert(Key k, Value v);
51  void print();
52  //void sortTo(Element *to); // sort in increasing order and empty
53  //void sortInPlace(); // in decreasing order
54 };
55 
56 
57 // reset size to 0 and fill data array with sentinels
58 template <class Key, class Value>
59 inline void Heap4<Key, Value>::
60 reset() {
61  size = 0;
62  finalLayerSize = 1;
63  finalLayerDist = 0;
64  Key sup = getSupremum();
65  for (int i = 1; i <= capacity; i++) {
66  data[i].key = sup;
67  }
68 }
69 
70 template <class Key, class Value>
71 inline void Heap4<Key, Value>::
72 deleteMin(Key *key, Value *value)
73 {
74  *key = getMinKey();
75  *value = getMinValue();
76  deleteMinBasic();
77 }
78 
79 template <class Key, class Value>
80 inline void Heap4<Key, Value>::
82 {
83  Assert2(size > 0);
84  Key minKey, otherKey;
85  int delta;
86 
87  // first move up elements on a min-path
88  int hole = 1;
89  int succ = 2;
90  int layerSize = 4; // size of succ's layer
91  int layerPos = 0; // pos of succ within its layer
92  int sz = size;
93  size = sz - 1;
94  finalLayerDist++;
95  if (finalLayerDist == finalLayerSize) { // layer empty now
96  finalLayerSize >>= 2;
97  finalLayerDist = 0;
98  }
99  while (succ < sz) {
100  minKey = data[succ].key;
101  delta = 0;
102 
103  // I could save a few assignments using
104  // a complete case distincition but
105  // this costs in terms of instruction cache load
106  otherKey = data[succ + 1].key;
107  if (otherKey < minKey) { minKey = otherKey; delta = 1; }
108  otherKey = data[succ + 2].key;
109  if (otherKey < minKey) { minKey = otherKey; delta = 2; }
110  otherKey = data[succ + 3].key;
111  if (otherKey < minKey) { minKey = otherKey; delta = 3; }
112  succ += delta;
113  layerPos += delta;
114 
115  // move min successor up
116  data[hole].key = minKey;
117  data[hole].value = data[succ].value;
118 
119  // step to next layer
120  hole = succ;
121  succ = succ - layerPos + layerSize; // beginning of next layer
122  layerPos <<= 2;
123  succ += layerPos; // now correct value
124  layerSize <<= 2;
125  }
126 
127  // bubble up rightmost element
128  Key bubble = data[sz].key;
129  layerSize >>= 2; // now size of hole's layer
130  layerPos >>= 2; // now pos of hole within its layer
131  // Assert2(finalLayerSize == layerSize);
132  int layerDist = layerSize - layerPos - 1; // hole's dist to end of lay.
133  int pred = hole + layerDist - layerSize; // end of pred's layer for now
134  layerSize >>= 2; // now size of pred's layer
135  layerDist >>= 2; // now pred's pos in layer
136  pred = pred - layerDist; // finally preds index
137  while (data[pred].key > bubble) { // must terminate since inf at root
138  data[hole] = data[pred];
139  hole = pred;
140  pred = hole + layerDist - layerSize; // end of hole's layer for now
141  layerSize >>= 2; // now size of pred's layer
142  layerDist >>= 2;
143  pred = pred - layerDist; // finally preds index
144  }
145 
146  // finally move data to hole
147  data[hole].key = bubble;
148  data[hole].value = data[sz].value;
149 
150  data[sz].key = getSupremum(); // mark as deleted
151 }
152 
153 
154 template <class Key, class Value>
156 insert(Key k, Value v)
157 {
158  Assert2(size < capacity);
159  Debug4(cout << "insert(" << k << ", " << v << ")" << endl);
160 
161  int layerSize = finalLayerSize;
162  int layerDist = finalLayerDist;
163  finalLayerDist--;
164  if (finalLayerDist == -1) { // layer full
165  // start next layer
166  finalLayerSize <<= 2;
167  finalLayerDist = finalLayerSize - 1;
168  }
169  size++;
170  int hole = size;
171  int pred = hole + layerDist - layerSize; // end of preds's layer for now
172  layerSize >>= 2; // now size of pred's layer
173  layerDist >>= 2;
174  pred = pred - layerDist; // finally preds index
175  Key predKey = data[pred].key;
176  while (predKey > k) { // must terminate due to sentinel at 0
177  data[hole].key = predKey;
178  data[hole].value = data[pred].value;
179  hole = pred;
180  pred = hole + layerDist - layerSize; // end of preds's layer for now
181  layerSize >>= 2; // now size of pred's layer
182  layerDist >>= 2;
183  pred = pred - layerDist; // finally preds index
184  predKey = data[pred].key;
185  }
186 
187  // finally move data to hole
188  data[hole].key = k;
189  data[hole].value = v;
190 }
191 
192 template <class Key, class Value>
193 inline void Heap4<Key, Value>::
194 print()
195 {
196  int pos = 1;
197  for (int layerSize = 1; pos < size; layerSize <<= 2) {
198  for (int i = 0; i < layerSize && pos + i <= size; i++) {
199  cout << data[pos + i].key << " ";
200  }
201  pos += layerSize;
202  cout << endl;
203  }
204 }
205 
206 #endif
Definition: heap4.h:19
int getSize() const
Definition: heap4.h:45
Value getMinValue() const
Definition: heap4.h:47
Heap4(Key sup, Key infimum, int cap)
Definition: heap4.h:30
void print()
~Heap4()
Definition: heap4.h:42
void deleteMin(Key *key, Value *value)
void deleteMinBasic()
void reset()
Definition: heap4.h:60
Key getMinKey() const
Definition: heap4.h:46
void insert(Key k, Value v)
Key getSupremum()
Definition: heap4.h:43
int size
Definition: common.h:20
char * knAlign(void *p, unsigned long sz)
Definition: heap4.h:13
const unsigned long LineSize
Definition: heap4.h:6
#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