8 #include "monobitset.h"
11 #define BITS_PER_CHUNK MONO_BITSET_BITS_PER_CHUNK
14 * mono_bitset_alloc_size:
15 * @max_size: The number of bits you want to hold
18 * Return the number of bytes required to hold the bitset.
19 * Useful to allocate it on the stack or with mempool.
20 * Use with mono_bitset_mem_new ().
23 mono_bitset_alloc_size (guint32 max_size, guint32 flags) {
24 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
26 return sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY);
31 * @max_size: The numer of bits you want to hold
32 * @flags: bitfield of flags
34 * Return a bitset of size max_size. It must be freed using
38 mono_bitset_new (guint32 max_size, guint32 flags) {
39 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
42 result = (MonoBitSet *) g_malloc0 (sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY));
43 result->size = real_size * BITS_PER_CHUNK;
44 result->flags = flags;
49 * mono_bitset_mem_new:
50 * @mem: The location the bitset is stored
51 * @max_size: The number of bits you want to hold
52 * @flags: bitfield of flags
54 * Return mem, which is now a initialized bitset of size max_size. It is
55 * not freed even if called with mono_bitset_free. mem must be at least
56 * as big as mono_bitset_alloc_size returns for the same max_size.
59 mono_bitset_mem_new (gpointer mem, guint32 max_size, guint32 flags) {
60 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
61 MonoBitSet *result = (MonoBitSet *) mem;
63 result->size = real_size * BITS_PER_CHUNK;
64 result->flags = flags | MONO_BITSET_DONT_FREE;
70 * @set: bitset ptr to free
72 * Free bitset unless flags have MONO_BITSET_DONT_FREE set. Does not
73 * free anything if flag MONO_BITSET_DONT_FREE is set or bitset was
74 * made with mono_bitset_mem_new.
77 mono_bitset_free (MonoBitSet *set) {
78 if (!(set->flags & MONO_BITSET_DONT_FREE))
85 * @pos: set bit at this pos
87 * Set bit at pos @pos, counting from 0.
90 mono_bitset_set (MonoBitSet *set, guint32 pos) {
91 int j = pos / BITS_PER_CHUNK;
92 int bit = pos % BITS_PER_CHUNK;
94 g_assert (pos < set->size);
96 set->data [j] |= (gsize)1 << bit;
102 * @pos: test bit at this pos
104 * Test bit at pos @pos, counting from 0.
105 * Returns a value != 0 if set, 0 otherwise.
108 mono_bitset_test (const MonoBitSet *set, guint32 pos) {
109 int j = pos / BITS_PER_CHUNK;
110 int bit = pos % BITS_PER_CHUNK;
112 g_return_val_if_fail (pos < set->size, 0);
114 return (set->data [j] & ((gsize)1 << bit)) > 0;
118 * mono_bitset_test_bulk:
120 * @pos: test bit at this pos
122 * Return 32/64 bits from the bitset, starting from @pos, which must be
123 * divisible with 32/64.
126 mono_bitset_test_bulk (const MonoBitSet *set, guint32 pos) {
127 int j = pos / BITS_PER_CHUNK;
129 if (pos >= set->size)
132 return set->data [j];
138 * @pos: unset bit at this pos
140 * Unset bit at pos 'pos', counting from 0.
143 mono_bitset_clear (MonoBitSet *set, guint32 pos) {
144 int j = pos / BITS_PER_CHUNK;
145 int bit = pos % BITS_PER_CHUNK;
147 g_assert (pos < set->size);
149 set->data [j] &= ~((gsize)1 << bit);
153 * mono_bitset_clear_all:
159 mono_bitset_clear_all (MonoBitSet *set) {
160 memset (set->data, 0, set->size / 8);
164 * mono_bitset_set_all:
170 mono_bitset_set_all (MonoBitSet *set) {
171 memset (set->data, -1, set->size / 8);
175 * mono_bitset_invert:
181 mono_bitset_invert (MonoBitSet *set) {
183 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
184 set->data [i] = ~set->data [i];
191 * Returns the number of bits this bitset can hold.
194 mono_bitset_size (const MonoBitSet *set) {
199 * should test wich version is faster.
207 * return number of bits that is set.
210 mono_bitset_count (const MonoBitSet *set) {
215 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
218 if (sizeof (gsize) == sizeof (unsigned int))
219 count += __builtin_popcount (d);
221 count += __builtin_popcountll (d);
233 mono_bitset_count (const MonoBitSet *set) {
234 static const guint32 table [] = {
235 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
237 guint32 i, count, val;
240 for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
243 val = (val & table [0]) ((val >> 1) & table [0]);
244 val = (val & table [1]) ((val >> 2) & table [1]);
245 val = (val & table [2]) ((val >> 4) & table [2]);
246 val = (val & table [3]) ((val >> 8) & table [3]);
247 val = (val & table [4]) ((val >> 16) & table [4]);
259 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
260 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
261 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
262 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
263 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
264 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
265 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
266 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
270 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
271 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
276 my_g_bit_nth_lsf (gsize mask, gint nth_bit)
281 if ((mask == 0) || (nth_bit == BITS_PER_CHUNK))
284 #if defined(__native_client__) && (defined(__i386__) || defined(__x86_64))
285 #define USE_X86_32BIT_INSTRUCTIONS 1
288 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
291 /* This depends on mask != 0 */
292 __asm__("bsfl %1,%0\n\t"
293 : "=r" (r) : "g" (mask));
296 #elif defined(__x86_64) && defined(__GNUC__)
300 __asm__("bsfq %1,%0\n\t"
301 : "=r" (r) : "rm" (mask));
305 while (! (mask & 0x1)) {
315 my_g_bit_nth_lsf_nomask (gsize mask)
317 /* Mask is expected to be != 0 */
318 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
321 __asm__("bsfl %1,%0\n\t"
322 : "=r" (r) : "rm" (mask));
324 #elif defined(__x86_64) && defined(__GNUC__)
327 __asm__("bsfq %1,%0\n\t"
328 : "=r" (r) : "rm" (mask));
333 while (! (mask & 0x1)) {
345 my_g_bit_nth_msf (gsize mask,
353 mask <<= BITS_PER_CHUNK - nth_bit;
356 while ((i > 0) && !(mask >> (BITS_PER_CHUNK - 8))) {
365 if (mask & ((gsize)1 << (BITS_PER_CHUNK - 1)))
366 return i - (BITS_PER_CHUNK - nth_bit);
375 find_first_unset (gsize mask, gint nth_bit)
379 if (!(mask & ((gsize)1 << nth_bit))) {
380 if (nth_bit == BITS_PER_CHUNK)
381 /* On 64 bit platforms, 1 << 64 == 1 */
386 } while (nth_bit < BITS_PER_CHUNK);
391 * mono_bitset_find_start:
394 * Equivalent to mono_bitset_find_first (set, -1) but faster.
397 mono_bitset_find_start (const MonoBitSet *set)
401 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
403 return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
409 * mono_bitset_find_first:
411 * @pos: pos to search _after_ (not including)
413 * Returns position of first set bit after @pos. If pos < 0 begin search from
414 * start. Return -1 if no bit set is found.
417 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
426 j = pos / BITS_PER_CHUNK;
427 bit = pos % BITS_PER_CHUNK;
428 g_assert (pos < set->size);
430 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
433 result = my_g_bit_nth_lsf (set->data [j], bit);
435 return result + j * BITS_PER_CHUNK;
437 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
439 return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
445 * mono_bitset_find_last:
447 * @pos: pos to search _before_ (not including)
449 * Returns position of last set bit before pos. If pos < 0 search is
450 * started from the end. Returns -1 if no set bit is found.
453 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
454 int j, bit, result, i;
459 j = pos / BITS_PER_CHUNK;
460 bit = pos % BITS_PER_CHUNK;
462 g_return_val_if_fail (pos < set->size, -1);
465 result = my_g_bit_nth_msf (set->data [j], bit);
467 return result + j * BITS_PER_CHUNK;
469 for (i = --j; i >= 0; --i) {
471 return my_g_bit_nth_msf (set->data [i], BITS_PER_CHUNK) + i * BITS_PER_CHUNK;
477 * mono_bitset_find_first_unset:
479 * @pos: pos to search _after_ (not including)
481 * Returns position of first unset bit after @pos. If pos < 0 begin search from
482 * start. Return -1 if no bit set is found.
485 mono_bitset_find_first_unset (const MonoBitSet *set, gint pos) {
494 j = pos / BITS_PER_CHUNK;
495 bit = pos % BITS_PER_CHUNK;
496 g_return_val_if_fail (pos < set->size, -1);
498 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
500 if (set->data [j] != -1) {
501 result = find_first_unset (set->data [j], bit);
503 return result + j * BITS_PER_CHUNK;
505 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
506 if (set->data [i] != -1) {
507 return find_first_unset (set->data [i], -1) + i * BITS_PER_CHUNK;
515 * @set: bitset ptr to clone
516 * @new_size: number of bits the cloned bitset can hold
518 * Return a cloned bitset of size new_size. MONO_BITSET_DONT_FREE
519 * unset in cloned bitset. If new_size is 0, the cloned object is just
523 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
527 new_size = set->size;
528 result = mono_bitset_new (new_size, set->flags);
529 result->flags &= ~MONO_BITSET_DONT_FREE;
530 memcpy (result->data, set->data, set->size / 8);
535 * mono_bitset_copyto:
536 * @src: bitset ptr to copy from
537 * @dest: bitset ptr to copy to
539 * Copy one bitset to another.
542 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
543 g_assert (dest->size <= src->size);
545 memcpy (&dest->data, &src->data, dest->size / 8);
550 * @dest: bitset ptr to hold union
551 * @src: bitset ptr to copy
553 * Make union of one bitset and another.
556 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
559 g_assert (src->size <= dest->size);
561 size = dest->size / BITS_PER_CHUNK;
562 for (i = 0; i < size; ++i)
563 dest->data [i] |= src->data [i];
567 * mono_bitset_intersection:
568 * @dest: bitset ptr to hold intersection
569 * @src: bitset ptr to copy
571 * Make intersection of one bitset and another.
574 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
577 g_assert (src->size <= dest->size);
579 size = dest->size / BITS_PER_CHUNK;
580 for (i = 0; i < size; ++i)
581 dest->data [i] &= src->data [i];
585 * mono_bitset_intersection_2:
586 * @dest: bitset ptr to hold intersection
587 * @src1: first bitset
588 * @src2: second bitset
590 * Make intersection of two bitsets
593 mono_bitset_intersection_2 (MonoBitSet *dest, const MonoBitSet *src1, const MonoBitSet *src2) {
596 g_assert (src1->size <= dest->size);
597 g_assert (src2->size <= dest->size);
599 size = dest->size / BITS_PER_CHUNK;
600 for (i = 0; i < size; ++i)
601 dest->data [i] = src1->data [i] & src2->data [i];
606 * @dest: bitset ptr to hold bitset - src
607 * @src: bitset ptr to copy
609 * Unset all bits in dest, which are set in src.
612 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
615 g_assert (src->size <= dest->size);
617 size = src->size / BITS_PER_CHUNK;
618 for (i = 0; i < size; ++i)
619 dest->data [i] &= ~src->data [i];
627 * return TRUE if their size are the same and the same bits are set in
631 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
633 if (src->size != src1->size)
636 for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
637 if (src->data [i] != src1->data [i])
643 * mono_bitset_foreach:
645 * @func: Function to call for every set bit
646 * @data: pass this as second arg to func
648 * Calls func for every bit set in bitset. Argument 1 is the number of
649 * the bit set, argument 2 is data
652 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
655 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
657 for (j = 0; j < BITS_PER_CHUNK; ++j)
658 if (set->data [i] & ((gsize)1 << j))
659 func (j + i * BITS_PER_CHUNK, data);
668 * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
672 MonoBitSet *set1, *set2, *set3, *set4;
676 set1 = mono_bitset_new (60, 0);
677 set4 = mono_bitset_new (60, 0);
679 if (mono_bitset_count (set1) != 0)
683 mono_bitset_set (set1, 33);
684 if (mono_bitset_count (set1) != 1)
688 /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */
690 if (mono_bitset_find_first (set1, 0) != 33)
694 if (mono_bitset_find_first (set1, 33) != -1)
699 if (mono_bitset_find_first (set1, -100) != 33)
703 if (mono_bitset_find_last (set1, -1) != 33)
707 if (mono_bitset_find_last (set1, 33) != -1)
711 if (mono_bitset_find_last (set1, -100) != 33)
715 if (mono_bitset_find_last (set1, 34) != 33)
720 if (!mono_bitset_test (set1, 33))
724 if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
728 set2 = mono_bitset_clone (set1, 0);
729 if (mono_bitset_count (set2) != 1)
733 mono_bitset_invert (set2);
734 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
738 mono_bitset_clear (set2, 10);
739 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
744 set3 = mono_bitset_clone (set2, 0);
745 mono_bitset_union (set3, set1);
746 if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
750 mono_bitset_clear_all (set2);
751 if (mono_bitset_count (set2) != 0)
755 mono_bitset_invert (set2);
756 if (mono_bitset_count (set2) != mono_bitset_size (set2))
760 mono_bitset_set (set4, 0);
761 mono_bitset_set (set4, 1);
762 mono_bitset_set (set4, 10);
763 if (mono_bitset_count (set4) != 3)
768 for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
784 /* g_print ("count got: %d at %d\n", count, i); */
790 if (mono_bitset_find_first (set4, -1) != 0)
795 mono_bitset_set (set4, 31);
796 if (mono_bitset_find_first (set4, 10) != 31)
800 mono_bitset_free (set1);
802 set1 = mono_bitset_new (200, 0);
803 mono_bitset_set (set1, 0);
804 mono_bitset_set (set1, 1);
805 mono_bitset_set (set1, 10);
806 mono_bitset_set (set1, 31);
807 mono_bitset_set (set1, 150);
809 mono_bitset_free (set1);
810 mono_bitset_free (set2);
811 mono_bitset_free (set3);
812 mono_bitset_free (set4);
814 g_print ("total tests passed: %d\n", error - 1);