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_invert:
161 mono_bitset_invert (MonoBitSet *set) {
163 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
164 set->data [i] = ~set->data [i];
171 * Returns the number of bits this bitset can hold.
174 mono_bitset_size (const MonoBitSet *set) {
179 * should test wich version is faster.
187 * return number of bits that is set.
190 mono_bitset_count (const MonoBitSet *set) {
191 static const unsigned char table [16] = {
192 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
195 const unsigned char *b;
198 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
199 /* there is probably some asm code that can do this much faster */
201 b = (unsigned char*) (set->data + i);
202 count += table [b [0] & 0xf];
203 count += table [b [0] >> 4];
204 count += table [b [1] & 0xf];
205 count += table [b [1] >> 4];
206 count += table [b [2] & 0xf];
207 count += table [b [2] >> 4];
208 count += table [b [3] & 0xf];
209 count += table [b [3] >> 4];
216 mono_bitset_count (const MonoBitSet *set) {
217 static const guint32 table [] = {
218 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
220 guint32 i, count, val;
223 for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
226 val = (val & table [0]) ((val >> 1) & table [0]);
227 val = (val & table [1]) ((val >> 2) & table [1]);
228 val = (val & table [2]) ((val >> 4) & table [2]);
229 val = (val & table [3]) ((val >> 8) & table [3]);
230 val = (val & table [4]) ((val >> 16) & table [4]);
242 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
243 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
244 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
245 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
246 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
247 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
248 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
249 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
253 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
254 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
258 my_g_bit_nth_lsf (guint32 mask, gint nth_bit)
262 if (mask & (1 << (gulong) nth_bit))
264 } while (nth_bit < 31);
267 #define my_g_bit_nth_lsf_nomask(m) (my_g_bit_nth_lsf((m),-1))
271 * mono_bitset_find_start:
274 * Equivalent to mono_bitset_find_first (set, -1) but faster.
277 mono_bitset_find_start (const MonoBitSet *set)
281 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
283 return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
289 * mono_bitset_find_first:
291 * @pos: pos to search _after_ (not including)
293 * Returns position of first set bit after @pos. If pos < 0 begin search from
294 * start. Return -1 if no bit set is found.
297 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
306 j = pos / BITS_PER_CHUNK;
307 bit = pos % BITS_PER_CHUNK;
308 g_return_val_if_fail (pos < set->size, -1);
310 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
313 result = my_g_bit_nth_lsf (set->data [j], bit);
315 return result + j * BITS_PER_CHUNK;
317 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
319 return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
325 * mono_bitset_find_last:
327 * @pos: pos to search _before_ (not including)
329 * Returns position of last set bit before pos. If pos < 0 search is
330 * started from the end. Returns -1 if no set bit is found.
333 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
334 int j, bit, result, i;
339 j = pos / BITS_PER_CHUNK;
340 bit = pos % BITS_PER_CHUNK;
342 g_return_val_if_fail (pos < set->size, -1);
345 result = g_bit_nth_msf (set->data [j], bit);
347 return result + j * BITS_PER_CHUNK;
349 for (i = --j; i >= 0; --i) {
351 return g_bit_nth_msf (set->data [i], -1) + i * BITS_PER_CHUNK;
358 * @set: bitset ptr to clone
359 * @new_size: number of bits the cloned bitset can hold
361 * Return a cloned bitset of size new_size. MONO_BITSET_DONT_FREE
362 * unset in cloned bitset. If new_size is 0, the cloned object is just
366 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
370 new_size = set->size;
371 result = mono_bitset_new (new_size, set->flags);
372 result->flags &= ~MONO_BITSET_DONT_FREE;
373 memcpy (result->data, set->data, set->size / 8);
378 * mono_bitset_copyto:
379 * @src: bitset ptr to copy from
380 * @dest: bitset ptr to copy to
382 * Copy one bitset to another.
385 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
388 g_return_if_fail (dest->size <= src->size);
390 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
391 dest->data [i] = src->data [i];
396 * @dest: bitset ptr to hold union
397 * @src: bitset ptr to copy
399 * Make union of one bitset and another.
402 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
405 g_return_if_fail (src->size <= dest->size);
407 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
408 dest->data [i] |= src->data [i];
412 * mono_bitset_intersection:
413 * @dest: bitset ptr to hold intersection
414 * @src: bitset ptr to copy
416 * Make intersection of one bitset and another.
419 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
422 g_return_if_fail (src->size <= dest->size);
424 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
425 dest->data [i] = dest->data [i] & src->data [i];
430 * @dest: bitset ptr to hold bitset - src
431 * @src: bitset ptr to copy
433 * Unset all bits in dest, which are set in src.
436 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
439 g_return_if_fail (src->size <= dest->size);
441 for (i = 0; i < dest->size / BITS_PER_CHUNK; ++i)
442 dest->data [i] &= ~src->data [i];
450 * return TRUE if their size are the same and the same bits are set in
454 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
456 if (src->size != src1->size)
459 for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
460 if (src->data [i] != src1->data [i])
466 * mono_bitset_foreach:
468 * @func: Function to call for every set bit
469 * @data: pass this as second arg to func
471 * Calls func for every bit set in bitset. Argument 1 is the number of
472 * the bit set, argument 2 is data
475 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
478 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
480 for (j = 0; j < BITS_PER_CHUNK; ++j)
481 if (set->data [i] & (1 << j))
482 func (j + i * BITS_PER_CHUNK, data);
491 * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
495 MonoBitSet *set1, *set2, *set3, *set4;
499 set1 = mono_bitset_new (60, 0);
500 set4 = mono_bitset_new (60, 0);
502 if (mono_bitset_count (set1) != 0)
506 mono_bitset_set (set1, 33);
507 if (mono_bitset_count (set1) != 1)
511 //g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0));
513 if (mono_bitset_find_first (set1, 0) != 33)
517 if (mono_bitset_find_first (set1, 33) != -1)
522 if (mono_bitset_find_first (set1, -100) != 33)
526 if (mono_bitset_find_last (set1, -1) != 33)
530 if (mono_bitset_find_last (set1, 33) != -1)
534 if (mono_bitset_find_last (set1, -100) != 33)
538 if (mono_bitset_find_last (set1, 34) != 33)
543 if (!mono_bitset_test (set1, 33))
547 if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
551 set2 = mono_bitset_clone (set1, 0);
552 if (mono_bitset_count (set2) != 1)
556 mono_bitset_invert (set2);
557 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
561 mono_bitset_clear (set2, 10);
562 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
567 set3 = mono_bitset_clone (set2, 0);
568 mono_bitset_union (set3, set1);
569 if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
573 mono_bitset_clear_all (set2);
574 if (mono_bitset_count (set2) != 0)
578 mono_bitset_invert (set2);
579 if (mono_bitset_count (set2) != mono_bitset_size (set2))
583 mono_bitset_set (set4, 0);
584 mono_bitset_set (set4, 1);
585 mono_bitset_set (set4, 10);
586 if (mono_bitset_count (set4) != 3)
591 for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
607 //g_print ("count got: %d at %d\n", count, i);
613 if (mono_bitset_find_first (set4, -1) != 0)
618 mono_bitset_set (set4, 31);
619 if (mono_bitset_find_first (set4, 10) != 31)
623 mono_bitset_free (set1);
625 set1 = mono_bitset_new (200, 0);
626 mono_bitset_set (set1, 0);
627 mono_bitset_set (set1, 1);
628 mono_bitset_set (set1, 10);
629 mono_bitset_set (set1, 31);
630 mono_bitset_set (set1, 150);
632 mono_bitset_free (set1);
633 mono_bitset_free (set2);
634 mono_bitset_free (set3);
635 mono_bitset_free (set4);
637 g_print ("total tests passed: %d\n", error - 1);