4 #include "monobitset.h"
8 #define MONO_ZERO_LEN_ARRAY 0
10 #define MONO_ZERO_LEN_ARRAY 1
13 #define BITS_PER_CHUNK (8 * sizeof (guint32))
18 guint32 data [MONO_ZERO_LEN_ARRAY];
22 * mono_bitset_alloc_size:
23 * @max_size: The numer of bits you want to hold
26 * Return the number of bytes required to hold the bitset.
27 * Useful to allocate it on the stack or with mempool.
28 * Use with mono_bitset_mem_new ().
31 mono_bitset_alloc_size (guint32 max_size, guint32 flags) {
32 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
34 return sizeof (MonoBitSet) + sizeof (guint32) * (real_size - MONO_ZERO_LEN_ARRAY);
39 * @max_size: The numer of bits you want to hold
40 * @flags: bitfield of flags
42 * Return a bitset of size max_size. It must be freed using
46 mono_bitset_new (guint32 max_size, guint32 flags) {
47 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
50 result = g_malloc0 (sizeof (MonoBitSet) + sizeof (guint32) * (real_size - MONO_ZERO_LEN_ARRAY));
51 result->size = real_size * BITS_PER_CHUNK;
52 result->flags = flags;
57 * mono_bitset_mem_new:
58 * @mem: The location the bitset is stored
59 * @max_size: The number of bits you want to hold
60 * @flags: bitfield of flags
62 * Return mem, which is now a initialized bitset of size max_size. It is
63 * not freed even if called with mono_bitset_free. mem must be at least
64 * as big as mono_bitset_alloc_size returns for the same max_size.
67 mono_bitset_mem_new (gpointer mem, guint32 max_size, guint32 flags) {
68 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
69 MonoBitSet *result = mem;
71 result->size = real_size * BITS_PER_CHUNK;
72 result->flags = flags | MONO_BITSET_DONT_FREE;
78 * @set: bitset ptr to free
80 * Free bitset unless flags have MONO_BITSET_DONT_FREE set. Does not
81 * free anything if flag MONO_BITSET_DONT_FREE is set or bitset was
82 * made with mono_bitset_mem_new.
85 mono_bitset_free (MonoBitSet *set) {
86 if (!(set->flags & MONO_BITSET_DONT_FREE))
93 * @pos: set bit at this pos
95 * Set bit at pos @pos, counting from 0.
98 mono_bitset_set (MonoBitSet *set, guint32 pos) {
99 int j = pos / BITS_PER_CHUNK;
100 int bit = pos % BITS_PER_CHUNK;
102 g_return_if_fail (pos < set->size);
104 set->data [j] |= 1 << bit;
110 * @pos: test bit at this pos
112 * Test bit at pos @pos, counting from 0.
113 * Returns a value != 0 if set, 0 otherwise.
116 mono_bitset_test (const MonoBitSet *set, guint32 pos) {
117 int j = pos / BITS_PER_CHUNK;
118 int bit = pos % BITS_PER_CHUNK;
120 g_return_val_if_fail (pos < set->size, 0);
122 return set->data [j] & (1 << bit);
126 * mono_bitset_test_bulk:
128 * @pos: test bit at this pos
130 * Return 32 bits from the bitset, starting from @pos, which must be divisible
134 mono_bitset_test_bulk (const MonoBitSet *set, guint32 pos) {
135 int j = pos / BITS_PER_CHUNK;
137 if (pos >= set->size)
140 return set->data [j];
146 * @pos: unset bit at this pos
148 * Unset bit at pos 'pos', counting from 0.
151 mono_bitset_clear (MonoBitSet *set, guint32 pos) {
152 int j = pos / BITS_PER_CHUNK;
153 int bit = pos % BITS_PER_CHUNK;
155 g_return_if_fail (pos < set->size);
157 set->data [j] &= ~(1 << bit);
161 * mono_bitset_clear_all:
167 mono_bitset_clear_all (MonoBitSet *set) {
169 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
174 * mono_bitset_set_all:
180 mono_bitset_set_all (MonoBitSet *set) {
182 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
183 set->data [i] = 0xffffffff;
187 * mono_bitset_invert:
193 mono_bitset_invert (MonoBitSet *set) {
195 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
196 set->data [i] = ~set->data [i];
203 * Returns the number of bits this bitset can hold.
206 mono_bitset_size (const MonoBitSet *set) {
211 * should test wich version is faster.
219 * return number of bits that is set.
222 mono_bitset_count (const MonoBitSet *set) {
223 static const unsigned char table [16] = {
224 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
227 const unsigned char *b;
230 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
231 /* there is probably some asm code that can do this much faster */
233 b = (unsigned char*) (set->data + i);
234 count += table [b [0] & 0xf];
235 count += table [b [0] >> 4];
236 count += table [b [1] & 0xf];
237 count += table [b [1] >> 4];
238 count += table [b [2] & 0xf];
239 count += table [b [2] >> 4];
240 count += table [b [3] & 0xf];
241 count += table [b [3] >> 4];
248 mono_bitset_count (const MonoBitSet *set) {
249 static const guint32 table [] = {
250 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
252 guint32 i, count, val;
255 for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
258 val = (val & table [0]) ((val >> 1) & table [0]);
259 val = (val & table [1]) ((val >> 2) & table [1]);
260 val = (val & table [2]) ((val >> 4) & table [2]);
261 val = (val & table [3]) ((val >> 8) & table [3]);
262 val = (val & table [4]) ((val >> 16) & table [4]);
274 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
275 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
276 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
277 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
278 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
279 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
280 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
281 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
285 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
286 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
290 my_g_bit_nth_lsf (guint32 mask, gint nth_bit)
294 if (mask & (1 << (gulong) nth_bit))
296 } while (nth_bit < 31);
299 #define my_g_bit_nth_lsf_nomask(m) (my_g_bit_nth_lsf((m),-1))
302 #if SIZEOF_VOID_P == 8 && GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 4
304 * There was a 64 bit bug in glib-2.2: g_bit_nth_msf (0, -1) would return 32,
305 * causing infinite loops in dominator computation. So glib-2.4 is required.
307 my_g_bit_nth_msf (gulong mask,
311 nth_bit = GLIB_SIZEOF_LONG * 8;
315 if (mask & (1UL << nth_bit))
322 #define my_g_bit_nth_msf(mask,nth_bit) g_bit_nth_msf((mask),(nth_bit))
326 * mono_bitset_find_start:
329 * Equivalent to mono_bitset_find_first (set, -1) but faster.
332 mono_bitset_find_start (const MonoBitSet *set)
336 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
338 return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
344 * mono_bitset_find_first:
346 * @pos: pos to search _after_ (not including)
348 * Returns position of first set bit after @pos. If pos < 0 begin search from
349 * start. Return -1 if no bit set is found.
352 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
361 j = pos / BITS_PER_CHUNK;
362 bit = pos % BITS_PER_CHUNK;
363 g_return_val_if_fail (pos < set->size, -1);
365 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
368 result = my_g_bit_nth_lsf (set->data [j], bit);
370 return result + j * BITS_PER_CHUNK;
372 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
374 return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
380 * mono_bitset_find_last:
382 * @pos: pos to search _before_ (not including)
384 * Returns position of last set bit before pos. If pos < 0 search is
385 * started from the end. Returns -1 if no set bit is found.
388 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
389 int j, bit, result, i;
394 j = pos / BITS_PER_CHUNK;
395 bit = pos % BITS_PER_CHUNK;
397 g_return_val_if_fail (pos < set->size, -1);
400 result = my_g_bit_nth_msf (set->data [j], bit);
402 return result + j * BITS_PER_CHUNK;
404 for (i = --j; i >= 0; --i) {
406 return my_g_bit_nth_msf (set->data [i], -1) + i * BITS_PER_CHUNK;
413 * @set: bitset ptr to clone
414 * @new_size: number of bits the cloned bitset can hold
416 * Return a cloned bitset of size new_size. MONO_BITSET_DONT_FREE
417 * unset in cloned bitset. If new_size is 0, the cloned object is just
421 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
425 new_size = set->size;
426 result = mono_bitset_new (new_size, set->flags);
427 result->flags &= ~MONO_BITSET_DONT_FREE;
428 memcpy (result->data, set->data, set->size / 8);
433 * mono_bitset_copyto:
434 * @src: bitset ptr to copy from
435 * @dest: bitset ptr to copy to
437 * Copy one bitset to another.
440 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
443 g_return_if_fail (dest->size <= src->size);
445 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
446 dest->data [i] = src->data [i];
451 * @dest: bitset ptr to hold union
452 * @src: bitset ptr to copy
454 * Make union of one bitset and another.
457 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
460 g_return_if_fail (src->size <= dest->size);
462 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
463 dest->data [i] |= src->data [i];
467 * mono_bitset_intersection:
468 * @dest: bitset ptr to hold intersection
469 * @src: bitset ptr to copy
471 * Make intersection of one bitset and another.
474 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
477 g_return_if_fail (src->size <= dest->size);
479 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
480 dest->data [i] = dest->data [i] & src->data [i];
485 * @dest: bitset ptr to hold bitset - src
486 * @src: bitset ptr to copy
488 * Unset all bits in dest, which are set in src.
491 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
494 g_return_if_fail (src->size <= dest->size);
496 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
497 dest->data [i] &= ~src->data [i];
505 * return TRUE if their size are the same and the same bits are set in
509 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
511 if (src->size != src1->size)
514 for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
515 if (src->data [i] != src1->data [i])
521 * mono_bitset_foreach:
523 * @func: Function to call for every set bit
524 * @data: pass this as second arg to func
526 * Calls func for every bit set in bitset. Argument 1 is the number of
527 * the bit set, argument 2 is data
530 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
533 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
535 for (j = 0; j < BITS_PER_CHUNK; ++j)
536 if (set->data [i] & (1 << j))
537 func (j + i * BITS_PER_CHUNK, data);
546 * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
550 MonoBitSet *set1, *set2, *set3, *set4;
554 set1 = mono_bitset_new (60, 0);
555 set4 = mono_bitset_new (60, 0);
557 if (mono_bitset_count (set1) != 0)
561 mono_bitset_set (set1, 33);
562 if (mono_bitset_count (set1) != 1)
566 /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */
568 if (mono_bitset_find_first (set1, 0) != 33)
572 if (mono_bitset_find_first (set1, 33) != -1)
577 if (mono_bitset_find_first (set1, -100) != 33)
581 if (mono_bitset_find_last (set1, -1) != 33)
585 if (mono_bitset_find_last (set1, 33) != -1)
589 if (mono_bitset_find_last (set1, -100) != 33)
593 if (mono_bitset_find_last (set1, 34) != 33)
598 if (!mono_bitset_test (set1, 33))
602 if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
606 set2 = mono_bitset_clone (set1, 0);
607 if (mono_bitset_count (set2) != 1)
611 mono_bitset_invert (set2);
612 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
616 mono_bitset_clear (set2, 10);
617 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
622 set3 = mono_bitset_clone (set2, 0);
623 mono_bitset_union (set3, set1);
624 if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
628 mono_bitset_clear_all (set2);
629 if (mono_bitset_count (set2) != 0)
633 mono_bitset_invert (set2);
634 if (mono_bitset_count (set2) != mono_bitset_size (set2))
638 mono_bitset_set (set4, 0);
639 mono_bitset_set (set4, 1);
640 mono_bitset_set (set4, 10);
641 if (mono_bitset_count (set4) != 3)
646 for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
662 /* g_print ("count got: %d at %d\n", count, i); */
668 if (mono_bitset_find_first (set4, -1) != 0)
673 mono_bitset_set (set4, 31);
674 if (mono_bitset_find_first (set4, 10) != 31)
678 mono_bitset_free (set1);
680 set1 = mono_bitset_new (200, 0);
681 mono_bitset_set (set1, 0);
682 mono_bitset_set (set1, 1);
683 mono_bitset_set (set1, 10);
684 mono_bitset_set (set1, 31);
685 mono_bitset_set (set1, 150);
687 mono_bitset_free (set1);
688 mono_bitset_free (set2);
689 mono_bitset_free (set3);
690 mono_bitset_free (set4);
692 g_print ("total tests passed: %d\n", error - 1);