hobbes
a language, embedded compiler, and runtime for efficient dynamic expression evaluation, data storage and analysis
rmap.H
Go to the documentation of this file.
1 /*****************
2  * rmap : map key ranges to values
3  *****************/
4 
5 #ifndef HOBBES_UTIL_RMAP_HPP_INCLUDED
6 #define HOBBES_UTIL_RMAP_HPP_INCLUDED
7 
8 #include <vector>
9 #include <set>
10 #include <map>
11 #include <functional>
12 #include <iostream>
13 
14 namespace hobbes {
15 
16 template <typename K, typename V, typename Ord>
17  class range_map {
18  public:
19  typedef std::pair<K, K> range;
20  typedef std::vector<range> ranges;
21 
22  // show the state of this range map
23  void show(std::ostream& out) const {
24  out << "{";
25  if (this->rs.size() != this->vs.size()) {
26  out << "INVALID (" << this->rs.size() << " != " << this->vs.size() << ")";
27  } else if (this->rs.size() > 0) {
28  out << "'" << this->rs[0].first << "-" << this->rs[0].second << "' => " << this->vs[0];
29  for (size_t i = 1; i < this->rs.size(); ++i) {
30  out << ", '" << this->rs[i].first << "-" << this->rs[i].second << "' => " << this->vs[i];
31  }
32  }
33  out << "}";
34  }
35 
36  // find the value V such that (k0,k1)->V in this and k0 <= k <= k1
37  const V* lookup(const K& k) const {
38  size_t i = find(k);
39  if (i < this->vs.size()) {
40  return &this->vs[i];
41  } else {
42  return 0;
43  }
44  }
45 
46  // find the value V such that (k0,k1)->V in this and k0 <= kr.0 <= kr.1 <= k1
47  const V* lookupRangeSubset(const range& kr) const {
48  size_t i = find(kr.first);
49  size_t j = find(kr.second);
50 
51  if (i == j && i < this->vs.size()) {
52  return &this->vs[i];
53  } else {
54  return 0;
55  }
56  }
57 
58  // insert a range->value mapping
59  // overwrite any mappings intersected
60  void insert(const range& rr, const V& v) {
61  for (size_t i = 0; i < this->rs.size(); ++i) {
62  range& lr = this->rs[i];
63 
64  switch (classifyIntersection(lr, rr)) {
65  case LLRR:
66  continue;
67  case RRLL:
68  insAt(i, rr, v);
69  assert(rangesValid());
70  return;
71  case EE:
72  this->vs[i] = v;
73  assert(rangesValid());
74  return;
75  case ELR:
76  this->vs[i] = v;
77  lr.second = rr.second;
78  deleteFrom(i+1, rr);
79  assert(rangesValid());
80  return;
81  case ERL:
82  lr.first = Ord::succ(rr.second); //+1
83  insAt(i, rr, v);
84  assert(rangesValid());
85  return;
86  case LRE:
87  lr.second = Ord::pred(rr.first); //-1
88  insAt(i+1, rr, v);
89  assert(rangesValid());
90  return;
91  case RLE:
92  lr.first = rr.first;
93  this->vs[i] = v;
94  assert(rangesValid());
95  return;
96  case LRRL: {
97  range er(Ord::succ(rr.second), lr.second);
98  lr.second = Ord::pred(rr.first);
99 
100  insAt(i+1, rr, v);
101  insAt(i+2, er, this->vs[i]);
102  assert(rangesValid());
103  return;
104  }
105  case RLLR:
106  lr.first = rr.first;
107  lr.second = rr.second;
108  this->vs[i] = v;
109 
110  deleteFrom(i+1, rr);
111  assert(rangesValid());
112  return;
113  case LRLR:
114  lr.second = Ord::pred(rr.first);
115  deleteFrom(i+1,rr);
116  insAt(i+1, rr, v);
117  assert(rangesValid());
118  return;
119  case RLRL:
120  lr.first = Ord::succ(rr.second);
121  insAt(i, rr, v);
122  assert(rangesValid());
123  return;
124  }
125  }
126 
127  // if we get here, the range doesn't intersect anything
128  // it must go at the end
129  this->rs.push_back(rr);
130  this->vs.push_back(v);
131  }
132 
133  void insert(const K& k0, const K& k1, const V& v) {
134  insert(range(k0,k1),v);
135  }
136 
137  void mergeRange(range rr, const std::function<void(V&)>& f) {
138  for (size_t i = 0; i < this->rs.size(); ++i) {
139  range& lr = this->rs[i];
140 
141  switch (classifyIntersection(lr, rr)) {
142  case LLRR:
143  continue;
144  case RRLL:
145  insAt(i, rr, V());
146  f(this->vs[i]);
147  assert(rangesValid());
148  return;
149  case EE:
150  f(this->vs[i]);
151  assert(rangesValid());
152  return;
153  case ELR:
154  f(this->vs[i]);
155  rr.first=Ord::succ(lr.second);
156  break;
157  case ERL: {
158  range er(Ord::succ(rr.second), lr.second);
159  V ev = this->vs[i];
160 
161  lr.second = rr.second;
162  f(this->vs[i]);
163  insAt(i+1, er, ev);
164  assert(rangesValid());
165  return;
166  }
167  case LRE:
168  lr.second = Ord::pred(rr.first);
169  insAt(i+1, rr, this->vs[i]);
170  f(this->vs[i+1]);
171  assert(rangesValid());
172  return;
173  case RLE:
174  insAt(i, range(rr.first, Ord::pred(lr.first)), V());
175  f(this->vs[i]);
176  f(this->vs[i+1]);
177  assert(rangesValid());
178  return;
179  case LRRL: {
180  range er(Ord::succ(rr.second), lr.second);
181  lr.second = Ord::pred(rr.first);
182 
183  insAt(i+1, rr, this->vs[i]);
184  f(this->vs[i+1]);
185 
186  insAt(i+2, er, this->vs[i]);
187  assert(rangesValid());
188  return;
189  }
190  case RLLR: {
191  range nr(Ord::succ(lr.second), rr.second);
192  insAt(i, range(rr.first, Ord::pred(lr.first)), V());
193  f(this->vs[i]);
194  f(this->vs[i+1]);
195  rr = nr;
196  break;
197  }
198  case LRLR: {
199  range mr(rr.first, lr.second);
200  range er(Ord::succ(lr.second), rr.second);
201  lr.second = Ord::pred(rr.first);
202  insAt(i+1, mr, this->vs[i]);
203  f(this->vs[i+1]);
204  rr = er;
205  break;
206  }
207  case RLRL: {
208  range br(rr.first, Ord::pred(lr.first));
209  range er(Ord::succ(rr.second), lr.second);
210  V ev = this->vs[i];
211 
212  lr.second = rr.second;
213  f(this->vs[i]);
214 
215  insAt(i, br, V());
216  f(this->vs[i]);
217 
218  insAt(i+2, er, ev);
219  assert(rangesValid());
220  return;
221  }}
222  }
223 
224  // if we get here, the range doesn't intersect anything
225  // it must go at the end
226  this->rs.push_back(rr);
227  this->vs.resize(this->vs.size()+1);
228  f(this->vs.back());
229  assert(rangesValid());
230  }
231 
232  void mergeRange(const K& k0, const K& k1, const std::function<void(V&)>& f) {
233  mergeRange(range(k0,k1),f);
234  }
235 
236  void keys(std::set<K>* ks) const {
237  for (const auto& r : this->rs) {
238  Ord::copyRange(r.first, r.second, ks);
239  }
240  }
241 
242  typedef std::vector<std::pair<range, V>> Mapping;
243  Mapping mapping() const {
244  Mapping r;
245  for (size_t i = 0; i < this->rs.size(); ++i) {
246  r.push_back(std::make_pair(this->rs[i], this->vs[i]));
247  }
248  return r;
249  }
250 
251  ranges disjointRanges(const ranges& trs) const {
252  ranges lrs = this->rs;
253  ranges rrs = trs;
254 
255  ranges r;
256  size_t i = 0, j = 0;
257  while (i < lrs.size() && j < rrs.size()) {
258  range& lr = lrs[i];
259  range& rr = rrs[j];
260 
261  switch (classifyIntersection(lr, rr)) {
262  case LLRR:
263  r.push_back(lr);
264  ++i;
265  break;
266  case RRLL:
267  r.push_back(rr);
268  ++j;
269  break;
270  case EE:
271  r.push_back(lr);
272  ++i;
273  ++j;
274  break;
275  case ELR:
276  r.push_back(lr);
277  ++i;
278  rr.first = Ord::succ(lr.second);
279  break;
280  case ERL:
281  r.push_back(rr);
282  ++j;
283  lr.first = Ord::succ(rr.second);
284  break;
285  case LRE:
286  r.push_back(range(lr.first, rr.first));
287  if (Ord::lt(rr.first, rr.second)) {
288  r.push_back(range(Ord::succ(rr.first), rr.second));
289  }
290  ++i;
291  ++j;
292  break;
293  case RLE:
294  r.push_back(range(rr.first, lr.first));
295  if (Ord::lt(lr.first, lr.second)) {
296  r.push_back(range(Ord::succ(lr.first), lr.second));
297  }
298  ++i;
299  ++j;
300  break;
301  case LRRL:
302  r.push_back(range(lr.first, Ord::pred(rr.first)));
303  r.push_back(range(rr.first, rr.second));
304  ++j;
305  lr.first=Ord::succ(rr.second);
306  break;
307  case RLLR:
308  r.push_back(range(rr.first, Ord::pred(lr.first)));
309  r.push_back(range(lr.first, lr.second));
310  ++i;
311  rr.first=Ord::succ(lr.second);
312  break;
313  case LRLR:
314  r.push_back(range(lr.first, Ord::pred(rr.first)));
315  r.push_back(range(rr.first, Ord::pred(lr.second)));
316  ++i;
317  rr.first = lr.second;
318  break;
319  case RLRL:
320  r.push_back(range(rr.first, lr.first-1));
321  r.push_back(range(lr.first, rr.second-1));
322  ++j;
323  lr.first = rr.second;
324  break;
325  }
326  }
327 
328  // copy any remaining ranges
329  for (; i < lrs.size(); ++i) r.push_back(lrs[i]);
330  for (; j < rrs.size(); ++j) r.push_back(rrs[j]);
331 
332  assert(rangesValid(r));
333  return r;
334  }
335 
336  // we can merge contiguous ranges with equivalent map values
337  void compact() {
338  if (this->rs.size() >= 2) {
339  size_t i = 0;
340  while (i < this->rs.size()-1) {
341  range& tr = this->rs[i];
342  range& nr = this->rs[i+1];
343 
344  if (tr.second == Ord::pred(nr.first) && this->vs[i] == this->vs[i+1]) {
345  tr.second = nr.second;
346  this->rs.erase(this->rs.begin()+i+1);
347  this->vs.erase(this->vs.begin()+i+1);
348  } else {
349  ++i;
350  }
351  }
352  }
353  assert(rangesValid());
354  }
355  private:
356  typedef std::vector<V> values;
357  ranges rs;
358  values vs;
359 
360  static bool rangesValid(const ranges& rs) {
361  for (const auto& r : rs) {
362  if (r.first != r.second && !(Ord::lt(r.first, r.second))) {
363  return false;
364  }
365  }
366  return true;
367  }
368  bool rangesValid() const { return rangesValid(this->rs); }
369 
370  size_t find(const K& k) const {
371  for (size_t i = 0; i < this->rs.size(); ++i) {
372  const range& r = this->rs[i];
373 
374  if (k == r.first || k == r.second || (Ord::lt(r.first, k) && Ord::lt(k, r.second))) {
375  return i;
376  } else if (Ord::lt(k, r.first)) {
377  break;
378  }
379  }
380  return this->vs.size();
381  }
382 
383  void insAt(size_t i, const range& r, const V& v) {
384  this->rs.insert(this->rs.begin() + i, r);
385  this->vs.insert(this->vs.begin() + i, v);
386  }
387 
388  // there are 11 ways that two ranges (L and R) can be classified for intersection
389  // (with the first L meaning first range point for L and second L meaning second range point for L, equiv for R)
390  // (E means both L and R are identical)
392  LLRR, // disjoint (left first)
393  RRLL, // disjoint (right first)
394 
395  EE, // exact overlap
396  ELR, // same start, different ends (right subsumes)
397  ERL, // same start, different ends (left subsumes)
398  LRE, // same end, different starts (left subsumes)
399  RLE, // same end, different starts (right subsumes)
400 
401  LRRL, // total overlap (left subsumes)
402  RLLR, // total overlap (right subsumes)
403 
404  LRLR, // partial overlap (left first)
405  RLRL // partial overlap (right first)
406  };
407 
408  static RangeIntersection classifyIntersection(const range& lr, const range& rr) {
409  if (Ord::lt(lr.second, rr.first)) {
410  return LLRR;
411  } else if (Ord::lt(rr.second, lr.first)) {
412  return RRLL;
413  } else if (lr.first == rr.first) {
414  if (lr.second == rr.second) {
415  return EE;
416  } else if (Ord::lt(lr.second, rr.second)) {
417  return ELR;
418  } else {
419  return ERL;
420  }
421  } else if (lr.second == rr.second) {
422  if (Ord::lt(lr.first, rr.first)) {
423  return LRE;
424  } else {
425  return RLE;
426  }
427  } else if (Ord::lt(lr.first, rr.first) && Ord::lt(rr.second, lr.second)) {
428  return LRRL;
429  } else if (Ord::lt(rr.first, lr.first) && Ord::lt(lr.second, rr.second)) {
430  return RLLR;
431  } else if (Ord::lt(rr.first, lr.first) && Ord::lt(rr.second, lr.second)) {
432  return RLRL;
433  } else {
434  return LRLR;
435  }
436  }
437 
438  // truncate/delete ranges clipped by a given range (necessary when inserting large ranges)
439  void deleteFrom(size_t i, const range& rr) {
440  while (i < this->rs.size()) {
441  range& lr = this->rs[i];
442 
443  switch (classifyIntersection(lr, rr)) {
444  case LLRR:
445  ++i;
446  break; // ???
447  case RRLL:
448  return;
449  case EE:
450  this->rs.erase(this->rs.begin()+i);
451  this->vs.erase(this->vs.begin()+i);
452  return;
453  case ELR:
454  this->rs.erase(this->rs.begin()+i);
455  this->vs.erase(this->vs.begin()+i);
456  break;
457  case ERL:
458  lr.first = Ord::succ(rr.second);
459  return;
460  case LRE:
461  lr.second = Ord::pred(rr.first);
462  return;
463  case RLE:
464  this->rs.erase(this->rs.begin()+i);
465  this->vs.erase(this->vs.begin()+i);
466  return;
467  case LRRL: {
468  range er(Ord::succ(rr.second), lr.second);
469  lr.second = Ord::pred(rr.first);
470  this->rs.insert(this->rs.begin()+i+1, er);
471  this->vs.insert(this->vs.begin()+i+1, this->vs[i]);
472  return;
473  }
474  case RLLR:
475  this->rs.erase(this->rs.begin()+i);
476  this->vs.erase(this->vs.begin()+i);
477  break;
478  case LRLR:
479  lr.second = Ord::pred(rr.first);
480  ++i;
481  break;
482  case RLRL:
483  lr.first = Ord::succ(rr.second);
484  return;
485  }
486  }
487  }
488  };
489 }
490 
491 #endif
492 
std::vector< range > ranges
Definition: rmap.H:20
Definition: rmap.H:398
Mapping mapping() const
Definition: rmap.H:243
std::pair< K, K > range
Definition: rmap.H:19
Definition: rmap.H:392
Definition: rmap.H:405
Definition: rmap.H:401
Definition: rmap.H:404
Definition: rmap.H:396
void show(std::ostream &out) const
Definition: rmap.H:23
void insAt(size_t i, const range &r, const V &v)
Definition: rmap.H:383
ranges rs
Definition: rmap.H:357
Definition: rmap.H:395
Definition: boot.H:7
Definition: rmap.H:402
void mergeRange(const K &k0, const K &k1, const std::function< void(V &)> &f)
Definition: rmap.H:232
std::vector< std::pair< range, V > > Mapping
Definition: rmap.H:242
void keys(std::set< K > *ks) const
Definition: rmap.H:236
void insert(const range &rr, const V &v)
Definition: rmap.H:60
item succ(const item &i)
Definition: lalr.C:279
ranges disjointRanges(const ranges &trs) const
Definition: rmap.H:251
Definition: rmap.H:17
const V * lookupRangeSubset(const range &kr) const
Definition: rmap.H:47
bool rangesValid() const
Definition: rmap.H:368
const V * lookup(const K &k) const
Definition: rmap.H:37
void mergeRange(range rr, const std::function< void(V &)> &f)
Definition: rmap.H:137
size_t find(const K &k) const
Definition: rmap.H:370
void compact()
Definition: rmap.H:337
Definition: rmap.H:397
Definition: rmap.H:399
size_t r(const reader::MetaData &md, size_t o, T *t)
Definition: storage.H:1730
values vs
Definition: rmap.H:358
#define out
Definition: netio.H:19
std::vector< V > values
Definition: rmap.H:356
void insert(const K &k0, const K &k1, const V &v)
Definition: rmap.H:133
static bool rangesValid(const ranges &rs)
Definition: rmap.H:360
Definition: rmap.H:393
void deleteFrom(size_t i, const range &rr)
Definition: rmap.H:439
static RangeIntersection classifyIntersection(const range &lr, const range &rr)
Definition: rmap.H:408