source: branches/profile/PROBE_SET/ps_bitset.hxx

Last change on this file was 9523, checked in by westram, 12 years ago
  • use explicit override
    • renamed PS_BitSet_Fast::get/set to Get/Set? (like in PS_BitSet).
      • methods did not overload.
      • untested - undo changeset if problems arise
  • removed virtual from memberfunctions only occurring once (globally)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 KB
Line 
1#ifndef PS_BITSET_HXX
2#define PS_BITSET_HXX
3
4#ifndef __SET__
5#include <set>
6#endif
7#ifndef PS_FILEBUFFER_HXX
8#include "ps_filebuffer.hxx"
9#endif
10
11class PS_BitSet : virtual Noncopyable {
12protected:
13    unsigned char *data;
14
15    bool bias;      // preset value for newly allocated memory
16    long max_index; // max. used index
17    long capacity;  // number of allocated bits
18
19    PS_BitSet(const bool _bias, const long _max_index, const long _capacity)
20        : data(NULL),
21          bias(_bias),
22          max_index(_max_index),
23          capacity(_capacity)
24    {}
25
26public:
27    typedef set<long> IndexSet;
28
29            long getTrueIndices(IndexSet &_index_set, const long _fill_index);
30            long getFalseIndices(IndexSet &_index_set, const long _fill_index);
31            long getCountOfTrues(const long _fill_index = -1);
32   
33            long getMaxUsedIndex() const { return max_index; }
34            long getCapacity() const { return capacity; }
35
36    virtual bool Get(const long _index);
37    virtual bool Set(const long _index, const bool _value);
38
39    virtual void setTrue(const long _index);
40    virtual void setFalse(const long _index);
41
42            void invert();
43            void x_or(const PS_BitSet *_other_set);
44
45            void print(const bool _header, const long _fill_index);
46            bool save(PS_FileBuffer *_file);
47            bool load(PS_FileBuffer *_file, const long _fill_index);
48
49            bool copy(const PS_BitSet *_other_bitset);
50    virtual bool reserve(const long _capacity);
51
52    explicit PS_BitSet(const bool _bias, const long _capacity) : bias(_bias), max_index(-1), capacity(0) {
53        data = 0;
54        reserve(_capacity);
55    }
56
57    explicit PS_BitSet(PS_FileBuffer *_file, const long _fill_index = -1) : bias(false), max_index(-1), capacity(0) {
58        data = 0;
59        load(_file, _fill_index);
60    }
61
62    virtual ~PS_BitSet() {
63        if (data) free(data);
64    }
65};
66
67//  ############################################################
68//  # PS_BitSet_Fast
69//  ############################################################
70class PS_BitSet_Fast : public PS_BitSet {
71private:
72
73    PS_BitSet_Fast(const PS_BitSet_Fast&);
74    PS_BitSet_Fast();
75
76public:
77
78    virtual bool Get(const long _index) OVERRIDE;
79    virtual bool Set(const long _index, const bool _value) OVERRIDE;
80
81    virtual void setTrue(const long _index) OVERRIDE;
82    virtual void setFalse(const long _index) OVERRIDE;
83
84    virtual bool reserve(const long _capacity) OVERRIDE;
85
86    explicit PS_BitSet_Fast(PS_FileBuffer *_file, const long _fill_index = -1) : PS_BitSet(false, -1, 0) {
87        data = 0;
88        load(_file, _fill_index);
89    }
90
91    explicit PS_BitSet_Fast(bool _bias, long _capacity) : PS_BitSet(_bias, _capacity) {
92        // we just altered member functions so we don't do anything here
93        // but call correct base class constructor to prevent
94        // the call of PS_BitSet() without parameters
95    }
96};
97
98
99long PS_BitSet::getFalseIndices(PS_BitSet::IndexSet &_index_set, const long _fill_index = -1) {
100    _index_set.clear();
101    // get indices of falses from bitset up to max_index
102    long index      = 0;
103    long byte_index = 0;
104    while (true) {
105        unsigned char byte  = data[byte_index++];       // get a data byte
106        if (!(byte &   1)) _index_set.insert(index); if (index++ >= max_index) break;
107        if (!(byte &   2)) _index_set.insert(index); if (index++ >= max_index) break;
108        if (!(byte &   4)) _index_set.insert(index); if (index++ >= max_index) break;
109        if (!(byte &   8)) _index_set.insert(index); if (index++ >= max_index) break;
110        if (!(byte &  16)) _index_set.insert(index); if (index++ >= max_index) break;
111        if (!(byte &  32)) _index_set.insert(index); if (index++ >= max_index) break;
112        if (!(byte &  64)) _index_set.insert(index); if (index++ >= max_index) break;
113        if (!(byte & 128)) _index_set.insert(index); if (index++ >= max_index) break;
114    }
115    // append indices [max_index+1 .. _fill_index] if bias is set to false
116    if (!bias) {
117        for (; (index <= _fill_index); ++index) {
118            _index_set.insert(index);
119        }
120    }
121    return _index_set.size();
122}
123
124
125long PS_BitSet::getTrueIndices(PS_BitSet::IndexSet &_index_set, const long _fill_index = -1) {
126    _index_set.clear();
127    // get indices of trues from bitset up to max_index
128    long index      = 0;
129    long byte_index = 0;
130    while (true) {
131        unsigned char byte  = data[byte_index++];       // get a data byte
132        if (byte &   1) _index_set.insert(index); if (index++ >= max_index) break;
133        if (byte &   2) _index_set.insert(index); if (index++ >= max_index) break;
134        if (byte &   4) _index_set.insert(index); if (index++ >= max_index) break;
135        if (byte &   8) _index_set.insert(index); if (index++ >= max_index) break;
136        if (byte &  16) _index_set.insert(index); if (index++ >= max_index) break;
137        if (byte &  32) _index_set.insert(index); if (index++ >= max_index) break;
138        if (byte &  64) _index_set.insert(index); if (index++ >= max_index) break;
139        if (byte & 128) _index_set.insert(index); if (index++ >= max_index) break;
140    }
141    // append indices [max_index+1 .. _max_index] if bias is set to true
142    if (bias) {
143        for (; (index <= _fill_index); ++index) {
144            _index_set.insert(index);
145        }
146    }
147    return _index_set.size();
148}
149
150
151long PS_BitSet::getCountOfTrues(const long _fill_index) {
152    long count = 0;
153    // get indices of trues from bitset up to max_index
154    long index      = 0;
155    long byte_index = 0;
156    while (true) {
157        unsigned char byte  = data[byte_index++];       // get a data byte
158        if (byte &   1) ++count; if (index++ >= max_index) break;
159        if (byte &   2) ++count; if (index++ >= max_index) break;
160        if (byte &   4) ++count; if (index++ >= max_index) break;
161        if (byte &   8) ++count; if (index++ >= max_index) break;
162        if (byte &  16) ++count; if (index++ >= max_index) break;
163        if (byte &  32) ++count; if (index++ >= max_index) break;
164        if (byte &  64) ++count; if (index++ >= max_index) break;
165        if (byte & 128) ++count; if (index++ >= max_index) break;
166    }
167    // append indices [max_index+1 .. _max_index] if bias is set to true
168    if (bias && (_fill_index > max_index)) {
169        count += _fill_index-max_index + 1;
170    }
171    return count;
172}
173
174
175bool PS_BitSet::Set(const long _index, const bool _value) {
176    ps_assert(_index >= 0);
177    reserve(_index);
178    bool previous_value = (((data[_index/8] >> (_index % 8)) & 1) == 1);
179    if (_value) {
180        data[_index/8] |= 1 << (_index % 8);
181    }
182    else {
183        data[_index/8] &= ~(1 << (_index % 8));
184    }
185    if (_index > max_index) max_index = _index;
186    return previous_value;
187}
188
189
190void PS_BitSet::setTrue(const long _index) {
191    ps_assert(_index >= 0);
192    reserve(_index);
193    data[_index/8] &= 1 << (_index % 8);
194    if (_index > max_index) max_index = _index;
195}
196
197
198void PS_BitSet::setFalse(const long _index) {
199    ps_assert(_index >= 0);
200    reserve(_index);
201    data[_index/8] &= ~(1 << (_index % 8));
202    if (_index > max_index) max_index = _index;
203}
204
205
206bool PS_BitSet::Get(const long _index) {
207    ps_assert(_index >= 0);
208    reserve(_index);
209    return (((data[_index/8] >> (_index % 8)) & 1) == 1);
210}
211
212
213bool PS_BitSet::copy(const PS_BitSet *_other_bitset) {
214    bias = _other_bitset->bias;
215    if (!reserve(_other_bitset->capacity)) return false;
216    memcpy(data, _other_bitset->data, (capacity>>3));
217    max_index = _other_bitset->max_index;
218    return true;
219}
220
221
222bool PS_BitSet::reserve(const long _capacity) {
223    unsigned char *new_data;
224    long new_capacity_bytes = (_capacity/8)+1;
225    long old_capacity_bytes = (capacity/8)+1;
226    if (capacity > 0) {
227        if (new_capacity_bytes <= old_capacity_bytes) return true;      // smaller or same size requested ?
228    }
229    new_capacity_bytes = ((new_capacity_bytes / 32)+1)*32;              // adjust requested size to bigger chunks
230    new_data = (unsigned char *)malloc(new_capacity_bytes);             // get new memory
231    if (new_data == 0) return false;
232    memset(new_data, bias ? 0xFF : 0, new_capacity_bytes);              // set memory to bias value
233    if (capacity > 0) memcpy(new_data, data, old_capacity_bytes);       // copy old values
234    if (data) free(data);                                               // free old memory
235    data     = new_data;                                                // store new pointer
236    capacity = new_capacity_bytes*8;                                    // store new capacity
237    return true;
238}
239
240
241void PS_BitSet::invert() {
242    for (long i = 0; i < capacity/8; ++i) {
243        data[i] = ~data[i];
244    }
245}
246
247
248void PS_BitSet::x_or(const PS_BitSet *_other_set) {
249    for (long i = 0; i < capacity/8; ++i) {
250        data[i] ^= _other_set->data[i];
251    }
252}
253
254
255void PS_BitSet::print(const bool _header = true, const long _fill_index = -1) {
256    if (_header) printf("PS_BitSet: bias(%1i) max_index(%6li) capacity(%6li) ", bias, max_index, capacity);
257    for (long i = 0; i <= max_index; ++i) {
258        printf(Get(i) ? "+" : "_");
259    }
260    for (long i = max_index+1; i <= _fill_index; ++i) {
261        printf(".");
262    }
263    printf(" %li\n", max_index);
264}
265
266
267bool PS_BitSet::save(PS_FileBuffer *_file) {
268    if (_file->isReadonly()) return false;
269    // save max_index
270    _file->put_long(max_index);
271    // save bias
272    _file->put_char((bias) ? '1' : '0');
273    // save bitset
274    long bytes = (max_index / 8)+1;
275    long i = 0;
276    while ((bytes-i) >= PS_FileBuffer::BUFFER_SIZE) {
277        _file->put(&(data[i]), PS_FileBuffer::BUFFER_SIZE);
278        i += PS_FileBuffer::BUFFER_SIZE;
279    }
280    _file->put(&(data[i]), (bytes-i));
281    return true;
282}
283
284
285bool PS_BitSet::load(PS_FileBuffer *_file, const long _fill_index = -1) {
286    // load max_index
287    _file->get_long(max_index);
288    // load bias
289    bias = (_file->get_char() == '1');
290    // initialize bitset
291    capacity = 0;
292    if (!reserve((max_index > _fill_index) ? max_index : _fill_index)) return false;
293    // load bitset
294    long bytes = (max_index / 8)+1;
295    long i = 0;
296    while ((bytes-i) >= PS_FileBuffer::BUFFER_SIZE) {
297        _file->get(&(data[i]), PS_FileBuffer::BUFFER_SIZE);
298        i += PS_FileBuffer::BUFFER_SIZE;
299    }
300    _file->get(&(data[i]), (bytes-i));
301    return true;
302}
303
304
305bool PS_BitSet_Fast::Get(const long _index) {
306    if (_index >= capacity) printf("PS_BitSet_Fast::get( %li ) exceeds capacity %li\n", _index, capacity);
307    if (_index > max_index) max_index = _index;
308    return (((data[_index/8] >> (_index % 8)) & 1) == 1);
309}
310
311
312bool PS_BitSet_Fast::Set(const long _index, const bool _value) {
313    if (_index >= capacity) printf("PS_BitSet_Fast::set( %li,%1i ) exceeds capacity %li\n", _index, _value, capacity);
314    bool previous_value = (((data[_index/8] >> (_index % 8)) & 1) == 1);
315    if (_value) {
316        data[_index/8] |= 1 << (_index % 8);
317    }
318    else {
319        data[_index/8] &= ~(1 << (_index % 8));
320    }
321    if (_index > max_index) max_index = _index;
322    return previous_value;
323}
324
325
326void PS_BitSet_Fast::setTrue(const long _index) {
327    if (_index >= capacity) printf("PS_BitSet_Fast::setTrue( %li ) exceeds capacity %li\n", _index, capacity);
328    data[_index/8] |= 1 << (_index % 8);
329    if (_index > max_index) max_index = _index;
330}
331
332
333void PS_BitSet_Fast::setFalse(const long _index) {
334    if (_index >= capacity) printf("PS_BitSet_Fast::setFalse( %li ) exceeds capacity %li\n", _index, capacity);
335    data[_index/8] &= ~(1 << (_index % 8));
336    if (_index > max_index) max_index = _index;
337}
338
339
340//   as i assume that a user of the _FAST variant knows how much
341//   data will be stored in the set we don't adjust the given
342//   capacity to bigger chunks as PS_BitSet::reserve does
343bool PS_BitSet_Fast::reserve(const long _capacity) {
344    unsigned char *new_data;
345    long new_capacity_bytes = (_capacity/8)+1;
346    long old_capacity_bytes = (capacity/8)+1;
347    if (capacity > 0) {
348        if (new_capacity_bytes <= old_capacity_bytes) return true;      // smaller or same size requested ?
349    }
350    new_data = (unsigned char *)malloc(new_capacity_bytes);             // get new memory
351    if (new_data == 0) return false;
352    memset(new_data, bias ? 0xFF : 0, new_capacity_bytes);              // set memory to bias value
353    if (capacity > 0) memcpy(new_data, data, old_capacity_bytes);       // copy old values
354    if (data) free(data);                                               // free old memory
355    data     = new_data;                                                // store new pointer
356    capacity = new_capacity_bytes*8;                                    // store new capacity
357    return true;
358}
359#else
360#error ps_bitset.hxx included twice
361#endif
Note: See TracBrowser for help on using the repository browser.