2
Copyright(c) 2002-2005 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
4
Permission is hereby granted, free of charge, to any person
5
obtaining a copy of this software and associated documentation
6
files (the "Software"), to deal in the Software without restriction,
7
including without limitation the rights to use, copy, modify, merge,
8
publish, distribute, sublicense, and/or sell copies of the Software,
9
and to permit persons to whom the Software is furnished to do so,
10
subject to the following conditions:
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
OTHER DEALINGS IN THE SOFTWARE.
23
For more information please visit: http://bmagic.sourceforge.net
27
#ifndef BMVMIN__H__INCLUDED__
28
#define BMVMIN__H__INCLUDED__
34
#define BM_MINISET_GAPLEN (bm::gap_len_table<true>::_len[0])
35
#define BM_MINISET_ARRSIZE(x) ((x / 32) + ( (x % 32) && 1 ))
37
/*! @defgroup mset Small sets functionality
38
* Templates in this group are used to keep block types in BM library.
39
* Classes of this group can tune bvector template (MS parameter)
40
* for best performance or minimal memory usage.
47
@brief Template class implements memory saving set functionality
49
Template can be used as template parameter for bvector if we
50
want to tune bvector for minimal memory consumption.
54
template <class A, size_t N> class miniset
63
miniset(const miniset& mset)
68
init_gapbuf(mset.m_buf);
70
init_bitbuf(mset.m_buf);
83
A::deallocate(m_buf, m_type ?
84
(BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t)))
86
(BM_MINISET_ARRSIZE(N)));
90
/// Checks if bit pos 1 or 0. Returns 0 if 0 and non zero otherwise.
91
unsigned test(bm::id_t n) const
97
gap_test((gap_word_t*)m_buf, n)
99
m_buf[n>>bm::set_word_shift] & (1<<(n & bm::set_word_mask));
102
void set(bm::id_t n, bool val=true)
112
unsigned nword = n >> bm::set_word_shift;
113
unsigned mask = unsigned(1) << (n & bm::set_word_mask);
115
val ? (m_buf[nword] |= mask) : (m_buf[nword] &= ~mask);
126
unsigned new_block_len =
127
gap_set_value(val, (gap_word_t*)m_buf, n, &is_set);
129
if (new_block_len > unsigned(BM_MINISET_GAPLEN-4))
136
unsigned mem_used() const
138
return sizeof(*this) +
140
(m_type ? (BM_MINISET_GAPLEN * sizeof(gap_word_t))
141
: (BM_MINISET_ARRSIZE(N) * sizeof(bm::word_t)))
145
void swap(miniset& mset)
147
bm::word_t* buftmp = m_buf;
150
unsigned typetmp = m_type;
151
m_type = mset.m_type;
152
mset.m_type = typetmp;
158
void init_bitbuf(bm::word_t* buf)
160
unsigned arr_size = BM_MINISET_ARRSIZE(N);
161
m_buf = A::allocate(arr_size, 0);
164
::memcpy(m_buf, buf, arr_size * sizeof(bm::word_t));
168
::memset(m_buf, 0, arr_size * sizeof(bm::word_t));
173
void init_gapbuf(bm::word_t* buf)
176
BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t));
177
m_buf = A::allocate(arr_size, 0);
180
::memcpy(m_buf, buf, arr_size * sizeof(bm::word_t));
185
gap_set_all((gap_word_t*)m_buf, bm::gap_max_bits, 0);
192
unsigned arr_size = BM_MINISET_ARRSIZE(N);
193
bm::word_t* buf = A::allocate(arr_size, 0);
195
gap_convert_to_bitset(buf, (gap_word_t*) m_buf, arr_size);
197
BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t));
198
A::deallocate(m_buf, arr_size);
204
bm::word_t* m_buf; //!< Buffer pointer
205
unsigned m_type; //!< buffer type (0-bit, 1-gap)
210
@brief Mini bitvector used in bvector template to keep block type flags
212
Template is used as a default template parameter MS for bvector
213
Offers maximum performance comparing to miniset.
217
template<size_t N> class bvmini
221
bvmini(int start_strategy = 0)
223
::memset(m_buf, 0, sizeof(m_buf));
226
bvmini(const bvmini& mset)
228
::memcpy(m_buf, mset.m_buf, sizeof(m_buf));
232
/// Checks if bit pos 1 or 0. Returns 0 if 0 and non zero otherwise.
233
unsigned test(bm::id_t n) const
235
return m_buf[n>>bm::set_word_shift] & (1<<(n & bm::set_word_mask));
238
void set(bm::id_t n, bool val=true)
240
unsigned nword = n >> bm::set_word_shift;
241
unsigned mask = unsigned(1) << (n & bm::set_word_mask);
243
val ? (m_buf[nword] |= mask) : (m_buf[nword] &= ~mask);
246
unsigned mem_used() const
248
return sizeof(*this);
251
void swap(bvmini& mset)
253
for (unsigned i = 0; i < BM_MINISET_ARRSIZE(N); ++i)
255
bm::word_t tmp = m_buf[i];
256
m_buf[i] = mset.m_buf[i];
262
bm::word_t m_buf[BM_MINISET_ARRSIZE(N)];
269
@brief Bitvector class with very limited functionality.
271
Class implements simple bitset and used for internal
272
and testing purposes.
274
template<class A> class bvector_mini
277
bvector_mini(unsigned size)
281
unsigned arr_size = (size / 32) + 1;
282
m_buf = A::allocate(arr_size, 0);
283
::memset(m_buf, 0, arr_size * sizeof(unsigned));
285
bvector_mini(const bvector_mini& bvect)
286
: m_size(bvect.m_size)
288
unsigned arr_size = (m_size / 32) + 1;
289
m_buf = A::allocate(arr_size, 0);
290
::memcpy(m_buf, bvect.m_buf, arr_size * sizeof(unsigned));
295
A::deallocate(m_buf, (m_size / 32) + 1);
298
/// Checks if bit pos 1 or 0. Returns 0 if 0 and non zero otherwise.
299
int is_bit_true(unsigned pos) const
301
unsigned char mask = (unsigned char)((char)0x1 << (pos & 7));
302
unsigned char* offs = (unsigned char*)m_buf + (pos >> 3); // m_buf + (pos/8)
304
return (*offs) & mask;
307
/// Sets bit number pos to 1
308
void set_bit(unsigned pos)
310
unsigned char mask = (unsigned char)(0x1 << (pos & 7));
311
unsigned char* offs = (unsigned char*)m_buf + (pos >> 3);
316
/// Sets bit number pos to 0
317
void clear_bit(unsigned pos)
319
unsigned char mask = (unsigned char)(0x1 << (pos & 7));
320
unsigned char* offs = (unsigned char*)m_buf + (pos >> 3);
325
/// Counts number of bits ON
326
unsigned bit_count() const
328
register unsigned count = 0;
329
const unsigned* end = m_buf + (m_size / 32)+1;
331
for (unsigned* start = m_buf; start < end; ++start)
333
register unsigned value = *start;
334
for (count += (value!=0); value &= value - 1; ++count);
340
int compare(const bvector_mini& bvect)
342
unsigned cnt1 = bit_count();
343
unsigned cnt2 = bvect.bit_count();
345
if (!cnt1 && !cnt2) return 0;
347
unsigned cnt_min = cnt1 < cnt2 ? cnt1 : cnt2;
349
if (!cnt_min) return cnt1 ? 1 : -1;
351
unsigned idx1 = get_first();
352
unsigned idx2 = bvect.get_first();
354
for (unsigned i = 0; i < cnt_min; ++i)
358
return idx1 < idx2 ? 1 : -1;
360
idx1 = get_next(idx1);
361
idx2 = bvect.get_next(idx2);
364
BM_ASSERT(idx1==0 || idx2==0);
368
if (!idx1) return -1;
370
return idx1 < idx2 ? 1 : -1;
377
/// Returns index of the first ON bit
378
unsigned get_first() const
381
const unsigned char* ptr = (unsigned char*) m_buf;
383
for (unsigned i = 0; i < (m_size/8)+1; ++i)
385
register unsigned char w = ptr[i];
397
pos += sizeof(unsigned char) * 8;
403
/// Returns index of next bit, which is ON
404
unsigned get_next(unsigned idx) const
408
for (i = idx+1; i < m_size; ++i)
410
unsigned char* offs = (unsigned char*)m_buf + (i >> 3);
413
unsigned char mask = (unsigned char)((char)0x1 << (i & 7));
429
void combine_and(const bvector_mini& bvect)
431
const unsigned* end = m_buf + (m_size / 32)+1;
433
const unsigned* src = bvect.get_buf();
435
for (unsigned* start = m_buf; start < end; ++start)
441
void combine_xor(const bvector_mini& bvect)
443
const unsigned* end = m_buf + (m_size / 32)+1;
445
const unsigned* src = bvect.get_buf();
447
for (unsigned* start = m_buf; start < end; ++start)
454
void combine_or(const bvector_mini& bvect)
456
const unsigned* end = m_buf + (m_size / 32)+1;
458
const unsigned* src = bvect.get_buf();
460
for (unsigned* start = m_buf; start < end; ++start)
466
void combine_sub(const bvector_mini& bvect)
468
const unsigned* end = m_buf + (m_size / 32)+1;
470
const unsigned* src = bvect.get_buf();
472
for (unsigned* start = m_buf; start < end; ++start)
478
const unsigned* get_buf() const { return m_buf; }
479
unsigned mem_used() const
481
return sizeof(bvector_mini) + (m_size / 32) + 1;
484
void swap(bvector_mini& bvm)
486
BM_ASSERT(m_size == bvm.m_size);
487
bm::word_t* buftmp = m_buf;
2
Copyright(c) 2002-2005 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
4
Permission is hereby granted, free of charge, to any person
5
obtaining a copy of this software and associated documentation
6
files (the "Software"), to deal in the Software without restriction,
7
including without limitation the rights to use, copy, modify, merge,
8
publish, distribute, sublicense, and/or sell copies of the Software,
9
and to permit persons to whom the Software is furnished to do so,
10
subject to the following conditions:
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
OTHER DEALINGS IN THE SOFTWARE.
23
For more information please visit: http://bmagic.sourceforge.net
27
#ifndef BMVMIN__H__INCLUDED__
28
#define BMVMIN__H__INCLUDED__
34
#define BM_MINISET_GAPLEN (bm::gap_len_table<true>::_len[0])
35
#define BM_MINISET_ARRSIZE(x) ((x / 32) + ( (x % 32) && 1 ))
37
/*! @defgroup mset Small sets functionality
38
* Templates in this group are used to keep block types in BM library.
39
* Classes of this group can tune bvector template (MS parameter)
40
* for best performance or minimal memory usage.
47
@brief Template class implements memory saving set functionality
49
Template can be used as template parameter for bvector if we
50
want to tune bvector for minimal memory consumption.
54
template <class A, size_t N> class miniset
63
miniset(const miniset& mset)
68
init_gapbuf(mset.m_buf);
70
init_bitbuf(mset.m_buf);
83
A::deallocate(m_buf, m_type ?
84
(BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t)))
86
(BM_MINISET_ARRSIZE(N)));
90
/// Checks if bit pos 1 or 0. Returns 0 if 0 and non zero otherwise.
91
unsigned test(bm::id_t n) const
97
gap_test((gap_word_t*)m_buf, n)
99
m_buf[n>>bm::set_word_shift] & (1<<(n & bm::set_word_mask));
102
void set(bm::id_t n, bool val=true)
112
unsigned nword = n >> bm::set_word_shift;
113
unsigned mask = unsigned(1) << (n & bm::set_word_mask);
115
val ? (m_buf[nword] |= mask) : (m_buf[nword] &= ~mask);
126
unsigned new_block_len =
127
gap_set_value(val, (gap_word_t*)m_buf, n, &is_set);
129
if (new_block_len > unsigned(BM_MINISET_GAPLEN-4))
136
unsigned mem_used() const
138
return sizeof(*this) +
140
(m_type ? (BM_MINISET_GAPLEN * sizeof(gap_word_t))
141
: (BM_MINISET_ARRSIZE(N) * sizeof(bm::word_t)))
145
void swap(miniset& mset)
147
bm::word_t* buftmp = m_buf;
150
unsigned typetmp = m_type;
151
m_type = mset.m_type;
152
mset.m_type = typetmp;
158
void init_bitbuf(bm::word_t* buf)
160
unsigned arr_size = BM_MINISET_ARRSIZE(N);
161
m_buf = A::allocate(arr_size, 0);
164
::memcpy(m_buf, buf, arr_size * sizeof(bm::word_t));
168
::memset(m_buf, 0, arr_size * sizeof(bm::word_t));
173
void init_gapbuf(bm::word_t* buf)
176
BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t));
177
m_buf = A::allocate(arr_size, 0);
180
::memcpy(m_buf, buf, arr_size * sizeof(bm::word_t));
185
gap_set_all((gap_word_t*)m_buf, bm::gap_max_bits, 0);
192
unsigned arr_size = BM_MINISET_ARRSIZE(N);
193
bm::word_t* buf = A::allocate(arr_size, 0);
195
gap_convert_to_bitset(buf, (gap_word_t*) m_buf, arr_size);
197
BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t));
198
A::deallocate(m_buf, arr_size);
204
bm::word_t* m_buf; //!< Buffer pointer
205
unsigned m_type; //!< buffer type (0-bit, 1-gap)
210
@brief Mini bitvector used in bvector template to keep block type flags
212
Template is used as a default template parameter MS for bvector
213
Offers maximum performance comparing to miniset.
217
template<size_t N> class bvmini
221
bvmini(int start_strategy = 0)
223
::memset(m_buf, 0, sizeof(m_buf));
226
bvmini(const bvmini& mset)
228
::memcpy(m_buf, mset.m_buf, sizeof(m_buf));
232
/// Checks if bit pos 1 or 0. Returns 0 if 0 and non zero otherwise.
233
unsigned test(bm::id_t n) const
235
return m_buf[n>>bm::set_word_shift] & (1<<(n & bm::set_word_mask));
238
void set(bm::id_t n, bool val=true)
240
unsigned nword = n >> bm::set_word_shift;
241
unsigned mask = unsigned(1) << (n & bm::set_word_mask);
243
val ? (m_buf[nword] |= mask) : (m_buf[nword] &= ~mask);
246
unsigned mem_used() const
248
return sizeof(*this);
251
void swap(bvmini& mset)
253
for (unsigned i = 0; i < BM_MINISET_ARRSIZE(N); ++i)
255
bm::word_t tmp = m_buf[i];
256
m_buf[i] = mset.m_buf[i];
262
bm::word_t m_buf[BM_MINISET_ARRSIZE(N)];
269
@brief Bitvector class with very limited functionality.
271
Class implements simple bitset and used for internal
272
and testing purposes.
274
template<class A> class bvector_mini
277
bvector_mini(unsigned size)
281
unsigned arr_size = (size / 32) + 1;
282
m_buf = A::allocate(arr_size, 0);
283
::memset(m_buf, 0, arr_size * sizeof(unsigned));
285
bvector_mini(const bvector_mini& bvect)
286
: m_size(bvect.m_size)
288
unsigned arr_size = (m_size / 32) + 1;
289
m_buf = A::allocate(arr_size, 0);
290
::memcpy(m_buf, bvect.m_buf, arr_size * sizeof(unsigned));
295
A::deallocate(m_buf, (m_size / 32) + 1);
298
/// Checks if bit pos 1 or 0. Returns 0 if 0 and non zero otherwise.
299
int is_bit_true(unsigned pos) const
301
unsigned char mask = (unsigned char)((char)0x1 << (pos & 7));
302
unsigned char* offs = (unsigned char*)m_buf + (pos >> 3); // m_buf + (pos/8)
304
return (*offs) & mask;
307
/// Sets bit number pos to 1
308
void set_bit(unsigned pos)
310
unsigned char mask = (unsigned char)(0x1 << (pos & 7));
311
unsigned char* offs = (unsigned char*)m_buf + (pos >> 3);
316
/// Sets bit number pos to 0
317
void clear_bit(unsigned pos)
319
unsigned char mask = (unsigned char)(0x1 << (pos & 7));
320
unsigned char* offs = (unsigned char*)m_buf + (pos >> 3);
325
/// Counts number of bits ON
326
unsigned bit_count() const
328
register unsigned count = 0;
329
const unsigned* end = m_buf + (m_size / 32)+1;
331
for (unsigned* start = m_buf; start < end; ++start)
333
register unsigned value = *start;
334
for (count += (value!=0); value &= value - 1; ++count);
340
int compare(const bvector_mini& bvect)
342
unsigned cnt1 = bit_count();
343
unsigned cnt2 = bvect.bit_count();
345
if (!cnt1 && !cnt2) return 0;
347
unsigned cnt_min = cnt1 < cnt2 ? cnt1 : cnt2;
349
if (!cnt_min) return cnt1 ? 1 : -1;
351
unsigned idx1 = get_first();
352
unsigned idx2 = bvect.get_first();
354
for (unsigned i = 0; i < cnt_min; ++i)
358
return idx1 < idx2 ? 1 : -1;
360
idx1 = get_next(idx1);
361
idx2 = bvect.get_next(idx2);
364
BM_ASSERT(idx1==0 || idx2==0);
368
if (!idx1) return -1;
370
return idx1 < idx2 ? 1 : -1;
377
/// Returns index of the first ON bit
378
unsigned get_first() const
381
const unsigned char* ptr = (unsigned char*) m_buf;
383
for (unsigned i = 0; i < (m_size/8)+1; ++i)
385
register unsigned char w = ptr[i];
397
pos += sizeof(unsigned char) * 8;
403
/// Returns index of next bit, which is ON
404
unsigned get_next(unsigned idx) const
408
for (i = idx+1; i < m_size; ++i)
410
unsigned char* offs = (unsigned char*)m_buf + (i >> 3);
413
unsigned char mask = (unsigned char)((char)0x1 << (i & 7));
429
void combine_and(const bvector_mini& bvect)
431
const unsigned* end = m_buf + (m_size / 32)+1;
433
const unsigned* src = bvect.get_buf();
435
for (unsigned* start = m_buf; start < end; ++start)
441
void combine_xor(const bvector_mini& bvect)
443
const unsigned* end = m_buf + (m_size / 32)+1;
445
const unsigned* src = bvect.get_buf();
447
for (unsigned* start = m_buf; start < end; ++start)
454
void combine_or(const bvector_mini& bvect)
456
const unsigned* end = m_buf + (m_size / 32)+1;
458
const unsigned* src = bvect.get_buf();
460
for (unsigned* start = m_buf; start < end; ++start)
466
void combine_sub(const bvector_mini& bvect)
468
const unsigned* end = m_buf + (m_size / 32)+1;
470
const unsigned* src = bvect.get_buf();
472
for (unsigned* start = m_buf; start < end; ++start)
478
const unsigned* get_buf() const { return m_buf; }
479
unsigned mem_used() const
481
return sizeof(bvector_mini) + (m_size / 32) + 1;
484
void swap(bvector_mini& bvm)
486
BM_ASSERT(m_size == bvm.m_size);
487
bm::word_t* buftmp = m_buf;