5 * Created by Victor Grishchenko on 3/28/09.
6 * Copyright 2009 Delft University of Technology. All rights reserved.
13 /** A binmap covering 2^64 range. Complexity limit: 100+200LoC */
17 typedef enum { FILLED=0xffff, EMPTY=0x0000, MIXED=0x5555 } fill_t;
18 static const int NOJOIN;
24 uint16_t get (bin64_t bin);
26 void set (bin64_t bin, fill_t val=FILLED);
28 void copy_range (bins& origin, bin64_t range);
30 bin64_t find (const bin64_t range, fill_t seek=EMPTY) ;
33 (bins& filter, bin64_t range, fill_t seek=EMPTY) ;
35 void remove (bins& b);
37 void dump(const char* note);
39 uint64_t* get_stripes (int& count);
41 uint32_t size() { return cells_allocated; }
43 uint64_t seq_length ();
45 bin64_t cover(bin64_t val);
49 bool is_solid (bin64_t range=bin64_t::ALL, fill_t val=MIXED) ;
50 bool is_empty (bin64_t range=bin64_t::ALL) { return is_solid(range,EMPTY); }
51 bool is_filled (bin64_t range=bin64_t::ALL) { return is_solid(range,FILLED); }
55 static bool is_mixed (uint16_t val) { return val!=EMPTY && val!=FILLED; }
56 static bool is_solid (uint16_t val) { return val==EMPTY || val==FILLED; }
58 void twist (uint64_t mask);
62 /** Every 16th uint32 is a flag field denoting whether
63 previous 30 halves (in 15 cells) are deep or not.
64 The last bit is used as a fill-flag.
65 Free cells have a value of 0; neither deep nor flat
66 cell could have a value of 0 except for the root
67 cell in case the binmap is all-0. */
72 uint32_t blocks_allocated;
73 uint32_t cells_allocated;
80 static const uint8_t SPLIT[16];
81 static const uint8_t JOIN[16];
83 bool deep(uint32_t half) const {
84 return cells[(half>>1)|0xf] & (1<<(half&0x1f));
86 void mark(uint32_t half) {
87 cells[(half>>1)|0xf] |= (1<<(half&0x1f));
89 void unmark(uint32_t half) {
90 cells[(half>>1)|0xf] &= ~(1<<(half&0x1f));
95 uint16_t alloc_cell ();
96 void free_cell (uint16_t cell);
98 /** Join the cell this half is pointing to
99 (in other words, flatten the half). */
100 bool join(uint32_t half) ;
102 /** Make the half deep. */
103 void split(uint32_t half) ;
105 static uint32_t split16to32(uint16_t half);
106 static int join32to16(uint32_t cell);
108 friend class iterator;
110 FRIEND_TEST(BinsTest,Routines);
115 /** Iterates over bins; for deep halves, bin==half.
116 For flat halves, bin is a range of bits in a half.
117 Iterator may split cells if needed.
118 Value is either undefined (deep cell, mixed cell)
123 uint32_t history[64];
126 bin64_t pos; // TODO: half[] layer bin
128 iterator(bins* host, bin64_t start=bin64_t(0,0), bool split=false);
130 bool deep () { return host->deep(half); }
132 return !deep() && bins::is_solid(host->halves[half]);
134 void sibling () { half^=1; pos=pos.sibling(); }
135 bool end () { return half==1; }
136 void to (bool right);
138 void right() {to(1);}
139 /** Move to the next defined (non-deep, flat) cell.
140 If solid==true, move to a solid (0xffff/0x0) cell. */
141 bin64_t next (bool solid=false);
142 bin64_t bin() { return pos; }
143 void towards(bin64_t bin) {
144 bin64_t next = pos.towards(bin);
145 assert(next!=bin64_t::NONE);
149 bool defined() { return !host->deep(half); }
150 uint16_t& operator* () { return host->halves[half]; }
151 uint8_t layer() const { return layer_; }
163 bool empty() const { return !filled_; }