4 #include "monobitset.h"
7 #define MONO_ZERO_LEN_ARRAY 0
9 #define MONO_ZERO_LEN_ARRAY 1
12 #define BITS_PER_CHUNK (8 * sizeof (guint32))
17 guint32 data [MONO_ZERO_LEN_ARRAY];
21 * mono_bitset_alloc_size:
22 * @max_size: The numer of bits you want to hold
25 * Return the number of bytes required to hold the bitset.
26 * Useful to allocate it on the stack or with mempool.
27 * Use with mono_bitset_mem_new ().
30 mono_bitset_alloc_size (guint32 max_size, guint32 flags) {
31 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
33 return sizeof (MonoBitSet) + sizeof (guint32) * (real_size - MONO_ZERO_LEN_ARRAY);
38 * @max_size: The numer of bits you want to hold
39 * @flags: bitfield of flags
41 * Return a bitset of size max_size. It must be freed using
45 mono_bitset_new (guint32 max_size, guint32 flags) {
46 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
49 result = g_malloc0 (sizeof (MonoBitSet) + sizeof (guint32) * (real_size - MONO_ZERO_LEN_ARRAY));
50 result->size = real_size * BITS_PER_CHUNK;
51 result->flags = flags;
56 * mono_bitset_mem_new:
57 * @mem: The location the bitset is stored
58 * @max_size: The number of bits you want to hold
59 * @flags: bitfield of flags
61 * Return mem, which is now a initialized bitset of size max_size. It is
62 * not freed even if called with mono_bitset_free. mem must be at least
63 * as big as mono_bitset_alloc_size returns for the same max_size.
66 mono_bitset_mem_new (gpointer mem, guint32 max_size, guint32 flags) {
67 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
68 MonoBitSet *result = mem;
70 result->size = real_size * BITS_PER_CHUNK;
71 result->flags = flags | MONO_BITSET_DONT_FREE;
77 * @set: bitset ptr to free
79 * Free bitset unless flags have MONO_BITSET_DONT_FREE set. Does not
80 * free anything if flag MONO_BITSET_DONT_FREE is set or bitset was
81 * made with mono_bitset_mem_new.
84 mono_bitset_free (MonoBitSet *set) {
85 if (!(set->flags & MONO_BITSET_DONT_FREE))
92 * @pos: set bit at this pos
94 * Set bit at pos @pos, counting from 0.
97 mono_bitset_set (MonoBitSet *set, guint32 pos) {
98 int j = pos / BITS_PER_CHUNK;
99 int bit = pos % BITS_PER_CHUNK;
101 g_return_if_fail (pos < set->size);
103 set->data [j] |= 1 << bit;
109 * @pos: test bit at this pos
111 * Test bit at pos @pos, counting from 0.
112 * Returns a value != 0 if set, 0 otherwise.
115 mono_bitset_test (const MonoBitSet *set, guint32 pos) {
116 int j = pos / BITS_PER_CHUNK;
117 int bit = pos % BITS_PER_CHUNK;
119 g_return_val_if_fail (pos < set->size, 0);
121 return set->data [j] & (1 << bit);
127 * @pos: unset bit at this pos
129 * Unset bit at pos 'pos', counting from 0.
132 mono_bitset_clear (MonoBitSet *set, guint32 pos) {
133 int j = pos / BITS_PER_CHUNK;
134 int bit = pos % BITS_PER_CHUNK;
136 g_return_if_fail (pos < set->size);
138 set->data [j] &= ~(1 << bit);
142 * mono_bitset_clear_all:
148 mono_bitset_clear_all (MonoBitSet *set) {
150 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
155 * mono_bitset_set_all:
161 mono_bitset_set_all (MonoBitSet *set) {
163 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
164 set->data [i] = 0xffffffff;
168 * mono_bitset_invert:
174 mono_bitset_invert (MonoBitSet *set) {
176 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
177 set->data [i] = ~set->data [i];
184 * Returns the number of bits this bitset can hold.
187 mono_bitset_size (const MonoBitSet *set) {
192 * should test wich version is faster.
200 * return number of bits that is set.
203 mono_bitset_count (const MonoBitSet *set) {
204 static const unsigned char table [16] = {
205 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
208 const unsigned char *b;
211 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
212 /* there is probably some asm code that can do this much faster */
214 b = (unsigned char*) (set->data + i);
215 count += table [b [0] & 0xf];
216 count += table [b [0] >> 4];
217 count += table [b [1] & 0xf];
218 count += table [b [1] >> 4];
219 count += table [b [2] & 0xf];
220 count += table [b [2] >> 4];
221 count += table [b [3] & 0xf];
222 count += table [b [3] >> 4];
229 mono_bitset_count (const MonoBitSet *set) {
230 static const guint32 table [] = {
231 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
233 guint32 i, count, val;
236 for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
239 val = (val & table [0]) ((val >> 1) & table [0]);
240 val = (val & table [1]) ((val >> 2) & table [1]);
241 val = (val & table [2]) ((val >> 4) & table [2]);
242 val = (val & table [3]) ((val >> 8) & table [3]);
243 val = (val & table [4]) ((val >> 16) & table [4]);
255 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
256 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
257 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
258 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
259 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
260 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
261 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
262 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
266 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
267 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
271 my_g_bit_nth_lsf (guint32 mask, gint nth_bit)
275 if (mask & (1 << (gulong) nth_bit))
277 } while (nth_bit < 31);
280 #define my_g_bit_nth_lsf_nomask(m) (my_g_bit_nth_lsf((m),-1))
284 * mono_bitset_find_start:
287 * Equivalent to mono_bitset_find_first (set, -1) but faster.
290 mono_bitset_find_start (const MonoBitSet *set)
294 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
296 return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
302 * mono_bitset_find_first:
304 * @pos: pos to search _after_ (not including)
306 * Returns position of first set bit after @pos. If pos < 0 begin search from
307 * start. Return -1 if no bit set is found.
310 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
319 j = pos / BITS_PER_CHUNK;
320 bit = pos % BITS_PER_CHUNK;
321 g_return_val_if_fail (pos < set->size, -1);
323 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
326 result = my_g_bit_nth_lsf (set->data [j], bit);
328 return result + j * BITS_PER_CHUNK;
330 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
332 return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
338 * mono_bitset_find_last:
340 * @pos: pos to search _before_ (not including)
342 * Returns position of last set bit before pos. If pos < 0 search is
343 * started from the end. Returns -1 if no set bit is found.
346 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
347 int j, bit, result, i;
352 j = pos / BITS_PER_CHUNK;
353 bit = pos % BITS_PER_CHUNK;
355 g_return_val_if_fail (pos < set->size, -1);
358 result = g_bit_nth_msf (set->data [j], bit);
360 return result + j * BITS_PER_CHUNK;
362 for (i = --j; i >= 0; --i) {
364 return g_bit_nth_msf (set->data [i], -1) + i * BITS_PER_CHUNK;
371 * @set: bitset ptr to clone
372 * @new_size: number of bits the cloned bitset can hold
374 * Return a cloned bitset of size new_size. MONO_BITSET_DONT_FREE
375 * unset in cloned bitset. If new_size is 0, the cloned object is just
379 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
383 new_size = set->size;
384 result = mono_bitset_new (new_size, set->flags);
385 result->flags &= ~MONO_BITSET_DONT_FREE;
386 memcpy (result->data, set->data, set->size / 8);
391 * mono_bitset_copyto:
392 * @src: bitset ptr to copy from
393 * @dest: bitset ptr to copy to
395 * Copy one bitset to another.
398 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
401 g_return_if_fail (dest->size <= src->size);
403 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
404 dest->data [i] = src->data [i];
409 * @dest: bitset ptr to hold union
410 * @src: bitset ptr to copy
412 * Make union of one bitset and another.
415 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
418 g_return_if_fail (src->size <= dest->size);
420 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
421 dest->data [i] |= src->data [i];
425 * mono_bitset_intersection:
426 * @dest: bitset ptr to hold intersection
427 * @src: bitset ptr to copy
429 * Make intersection of one bitset and another.
432 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
435 g_return_if_fail (src->size <= dest->size);
437 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
438 dest->data [i] = dest->data [i] & src->data [i];
443 * @dest: bitset ptr to hold bitset - src
444 * @src: bitset ptr to copy
446 * Unset all bits in dest, which are set in src.
449 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
452 g_return_if_fail (src->size <= dest->size);
454 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
455 dest->data [i] &= ~src->data [i];
463 * return TRUE if their size are the same and the same bits are set in
467 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
469 if (src->size != src1->size)
472 for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
473 if (src->data [i] != src1->data [i])
479 * mono_bitset_foreach:
481 * @func: Function to call for every set bit
482 * @data: pass this as second arg to func
484 * Calls func for every bit set in bitset. Argument 1 is the number of
485 * the bit set, argument 2 is data
488 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
491 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
493 for (j = 0; j < BITS_PER_CHUNK; ++j)
494 if (set->data [i] & (1 << j))
495 func (j + i * BITS_PER_CHUNK, data);
504 * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
508 MonoBitSet *set1, *set2, *set3, *set4;
512 set1 = mono_bitset_new (60, 0);
513 set4 = mono_bitset_new (60, 0);
515 if (mono_bitset_count (set1) != 0)
519 mono_bitset_set (set1, 33);
520 if (mono_bitset_count (set1) != 1)
524 //g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0));
526 if (mono_bitset_find_first (set1, 0) != 33)
530 if (mono_bitset_find_first (set1, 33) != -1)
535 if (mono_bitset_find_first (set1, -100) != 33)
539 if (mono_bitset_find_last (set1, -1) != 33)
543 if (mono_bitset_find_last (set1, 33) != -1)
547 if (mono_bitset_find_last (set1, -100) != 33)
551 if (mono_bitset_find_last (set1, 34) != 33)
556 if (!mono_bitset_test (set1, 33))
560 if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
564 set2 = mono_bitset_clone (set1, 0);
565 if (mono_bitset_count (set2) != 1)
569 mono_bitset_invert (set2);
570 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
574 mono_bitset_clear (set2, 10);
575 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
580 set3 = mono_bitset_clone (set2, 0);
581 mono_bitset_union (set3, set1);
582 if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
586 mono_bitset_clear_all (set2);
587 if (mono_bitset_count (set2) != 0)
591 mono_bitset_invert (set2);
592 if (mono_bitset_count (set2) != mono_bitset_size (set2))
596 mono_bitset_set (set4, 0);
597 mono_bitset_set (set4, 1);
598 mono_bitset_set (set4, 10);
599 if (mono_bitset_count (set4) != 3)
604 for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
620 //g_print ("count got: %d at %d\n", count, i);
626 if (mono_bitset_find_first (set4, -1) != 0)
631 mono_bitset_set (set4, 31);
632 if (mono_bitset_find_first (set4, 10) != 31)
636 mono_bitset_free (set1);
638 set1 = mono_bitset_new (200, 0);
639 mono_bitset_set (set1, 0);
640 mono_bitset_set (set1, 1);
641 mono_bitset_set (set1, 10);
642 mono_bitset_set (set1, 31);
643 mono_bitset_set (set1, 150);
645 mono_bitset_free (set1);
646 mono_bitset_free (set2);
647 mono_bitset_free (set3);
648 mono_bitset_free (set4);
650 g_print ("total tests passed: %d\n", error - 1);