4 #include "monobitset.h"
7 #define BITS_PER_CHUNK MONO_BITSET_BITS_PER_CHUNK
10 * mono_bitset_alloc_size:
11 * @max_size: The number of bits you want to hold
14 * Return the number of bytes required to hold the bitset.
15 * Useful to allocate it on the stack or with mempool.
16 * Use with mono_bitset_mem_new ().
19 mono_bitset_alloc_size (guint32 max_size, guint32 flags) {
20 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
22 return sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY);
27 * @max_size: The numer of bits you want to hold
28 * @flags: bitfield of flags
30 * Return a bitset of size max_size. It must be freed using
34 mono_bitset_new (guint32 max_size, guint32 flags) {
35 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
38 result = g_malloc0 (sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY));
39 result->size = real_size * BITS_PER_CHUNK;
40 result->flags = flags;
45 * mono_bitset_mem_new:
46 * @mem: The location the bitset is stored
47 * @max_size: The number of bits you want to hold
48 * @flags: bitfield of flags
50 * Return mem, which is now a initialized bitset of size max_size. It is
51 * not freed even if called with mono_bitset_free. mem must be at least
52 * as big as mono_bitset_alloc_size returns for the same max_size.
55 mono_bitset_mem_new (gpointer mem, guint32 max_size, guint32 flags) {
56 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
57 MonoBitSet *result = mem;
59 result->size = real_size * BITS_PER_CHUNK;
60 result->flags = flags | MONO_BITSET_DONT_FREE;
66 * @set: bitset ptr to free
68 * Free bitset unless flags have MONO_BITSET_DONT_FREE set. Does not
69 * free anything if flag MONO_BITSET_DONT_FREE is set or bitset was
70 * made with mono_bitset_mem_new.
73 mono_bitset_free (MonoBitSet *set) {
74 if (!(set->flags & MONO_BITSET_DONT_FREE))
81 * @pos: set bit at this pos
83 * Set bit at pos @pos, counting from 0.
86 mono_bitset_set (MonoBitSet *set, guint32 pos) {
87 int j = pos / BITS_PER_CHUNK;
88 int bit = pos % BITS_PER_CHUNK;
90 g_assert (pos < set->size);
92 set->data [j] |= (gsize)1 << bit;
98 * @pos: test bit at this pos
100 * Test bit at pos @pos, counting from 0.
101 * Returns a value != 0 if set, 0 otherwise.
104 mono_bitset_test (const MonoBitSet *set, guint32 pos) {
105 int j = pos / BITS_PER_CHUNK;
106 int bit = pos % BITS_PER_CHUNK;
108 g_return_val_if_fail (pos < set->size, 0);
110 return (set->data [j] & ((gsize)1 << bit)) > 0;
114 * mono_bitset_test_bulk:
116 * @pos: test bit at this pos
118 * Return 32/64 bits from the bitset, starting from @pos, which must be
119 * divisible with 32/64.
122 mono_bitset_test_bulk (const MonoBitSet *set, guint32 pos) {
123 int j = pos / BITS_PER_CHUNK;
125 if (pos >= set->size)
128 return set->data [j];
134 * @pos: unset bit at this pos
136 * Unset bit at pos 'pos', counting from 0.
139 mono_bitset_clear (MonoBitSet *set, guint32 pos) {
140 int j = pos / BITS_PER_CHUNK;
141 int bit = pos % BITS_PER_CHUNK;
143 g_assert (pos < set->size);
145 set->data [j] &= ~((gsize)1 << bit);
149 * mono_bitset_clear_all:
155 mono_bitset_clear_all (MonoBitSet *set) {
156 memset (set->data, 0, set->size / 8);
160 * mono_bitset_set_all:
166 mono_bitset_set_all (MonoBitSet *set) {
167 memset (set->data, -1, set->size / 8);
171 * mono_bitset_invert:
177 mono_bitset_invert (MonoBitSet *set) {
179 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
180 set->data [i] = ~set->data [i];
187 * Returns the number of bits this bitset can hold.
190 mono_bitset_size (const MonoBitSet *set) {
195 * should test wich version is faster.
203 * return number of bits that is set.
206 mono_bitset_count (const MonoBitSet *set) {
211 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
214 count += __builtin_popcount (d);
226 mono_bitset_count (const MonoBitSet *set) {
227 static const guint32 table [] = {
228 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
230 guint32 i, count, val;
233 for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
236 val = (val & table [0]) ((val >> 1) & table [0]);
237 val = (val & table [1]) ((val >> 2) & table [1]);
238 val = (val & table [2]) ((val >> 4) & table [2]);
239 val = (val & table [3]) ((val >> 8) & table [3]);
240 val = (val & table [4]) ((val >> 16) & table [4]);
252 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
253 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
254 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
255 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
256 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
257 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
258 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
259 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
263 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
264 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
269 my_g_bit_nth_lsf (gsize mask, gint nth_bit)
274 if ((mask == 0) || (nth_bit == BITS_PER_CHUNK))
277 #if defined(__native_client__) && (defined(__i386__) || defined(__x86_64))
278 #define USE_X86_32BIT_INSTRUCTIONS 1
281 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
284 /* This depends on mask != 0 */
285 __asm__("bsfl %1,%0\n\t"
286 : "=r" (r) : "g" (mask));
289 #elif defined(__x86_64) && defined(__GNUC__)
293 __asm__("bsfq %1,%0\n\t"
294 : "=r" (r) : "rm" (mask));
298 while (! (mask & 0x1)) {
308 my_g_bit_nth_lsf_nomask (gsize mask)
310 /* Mask is expected to be != 0 */
311 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
314 __asm__("bsfl %1,%0\n\t"
315 : "=r" (r) : "rm" (mask));
317 #elif defined(__x86_64) && defined(__GNUC__)
320 __asm__("bsfq %1,%0\n\t"
321 : "=r" (r) : "rm" (mask));
326 while (! (mask & 0x1)) {
338 my_g_bit_nth_msf (gsize mask,
346 mask <<= BITS_PER_CHUNK - nth_bit;
349 while ((i > 0) && !(mask >> (BITS_PER_CHUNK - 8))) {
358 if (mask & ((gsize)1 << (BITS_PER_CHUNK - 1)))
359 return i - (BITS_PER_CHUNK - nth_bit);
368 find_first_unset (gsize mask, gint nth_bit)
372 if (!(mask & ((gsize)1 << nth_bit))) {
373 if (nth_bit == BITS_PER_CHUNK)
374 /* On 64 bit platforms, 1 << 64 == 1 */
379 } while (nth_bit < BITS_PER_CHUNK);
384 * mono_bitset_find_start:
387 * Equivalent to mono_bitset_find_first (set, -1) but faster.
390 mono_bitset_find_start (const MonoBitSet *set)
394 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
396 return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
402 * mono_bitset_find_first:
404 * @pos: pos to search _after_ (not including)
406 * Returns position of first set bit after @pos. If pos < 0 begin search from
407 * start. Return -1 if no bit set is found.
410 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
419 j = pos / BITS_PER_CHUNK;
420 bit = pos % BITS_PER_CHUNK;
421 g_assert (pos < set->size);
423 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
426 result = my_g_bit_nth_lsf (set->data [j], bit);
428 return result + j * BITS_PER_CHUNK;
430 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
432 return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
438 * mono_bitset_find_last:
440 * @pos: pos to search _before_ (not including)
442 * Returns position of last set bit before pos. If pos < 0 search is
443 * started from the end. Returns -1 if no set bit is found.
446 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
447 int j, bit, result, i;
452 j = pos / BITS_PER_CHUNK;
453 bit = pos % BITS_PER_CHUNK;
455 g_return_val_if_fail (pos < set->size, -1);
458 result = my_g_bit_nth_msf (set->data [j], bit);
460 return result + j * BITS_PER_CHUNK;
462 for (i = --j; i >= 0; --i) {
464 return my_g_bit_nth_msf (set->data [i], BITS_PER_CHUNK) + i * BITS_PER_CHUNK;
470 * mono_bitset_find_first_unset:
472 * @pos: pos to search _after_ (not including)
474 * Returns position of first unset bit after @pos. If pos < 0 begin search from
475 * start. Return -1 if no bit set is found.
478 mono_bitset_find_first_unset (const MonoBitSet *set, gint pos) {
487 j = pos / BITS_PER_CHUNK;
488 bit = pos % BITS_PER_CHUNK;
489 g_return_val_if_fail (pos < set->size, -1);
491 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
493 if (set->data [j] != -1) {
494 result = find_first_unset (set->data [j], bit);
496 return result + j * BITS_PER_CHUNK;
498 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
499 if (set->data [i] != -1) {
500 return find_first_unset (set->data [i], -1) + i * BITS_PER_CHUNK;
508 * @set: bitset ptr to clone
509 * @new_size: number of bits the cloned bitset can hold
511 * Return a cloned bitset of size new_size. MONO_BITSET_DONT_FREE
512 * unset in cloned bitset. If new_size is 0, the cloned object is just
516 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
520 new_size = set->size;
521 result = mono_bitset_new (new_size, set->flags);
522 result->flags &= ~MONO_BITSET_DONT_FREE;
523 memcpy (result->data, set->data, set->size / 8);
528 * mono_bitset_copyto:
529 * @src: bitset ptr to copy from
530 * @dest: bitset ptr to copy to
532 * Copy one bitset to another.
535 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
536 g_assert (dest->size <= src->size);
538 memcpy (&dest->data, &src->data, dest->size / 8);
543 * @dest: bitset ptr to hold union
544 * @src: bitset ptr to copy
546 * Make union of one bitset and another.
549 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
552 g_assert (src->size <= dest->size);
554 size = dest->size / BITS_PER_CHUNK;
555 for (i = 0; i < size; ++i)
556 dest->data [i] |= src->data [i];
560 * mono_bitset_intersection:
561 * @dest: bitset ptr to hold intersection
562 * @src: bitset ptr to copy
564 * Make intersection of one bitset and another.
567 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
570 g_assert (src->size <= dest->size);
572 size = dest->size / BITS_PER_CHUNK;
573 for (i = 0; i < size; ++i)
574 dest->data [i] &= src->data [i];
578 * mono_bitset_intersection_2:
579 * @dest: bitset ptr to hold intersection
580 * @src1: first bitset
581 * @src2: second bitset
583 * Make intersection of two bitsets
586 mono_bitset_intersection_2 (MonoBitSet *dest, const MonoBitSet *src1, const MonoBitSet *src2) {
589 g_assert (src1->size <= dest->size);
590 g_assert (src2->size <= dest->size);
592 size = dest->size / BITS_PER_CHUNK;
593 for (i = 0; i < size; ++i)
594 dest->data [i] = src1->data [i] & src2->data [i];
599 * @dest: bitset ptr to hold bitset - src
600 * @src: bitset ptr to copy
602 * Unset all bits in dest, which are set in src.
605 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
608 g_assert (src->size <= dest->size);
610 size = src->size / BITS_PER_CHUNK;
611 for (i = 0; i < size; ++i)
612 dest->data [i] &= ~src->data [i];
620 * return TRUE if their size are the same and the same bits are set in
624 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
626 if (src->size != src1->size)
629 for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
630 if (src->data [i] != src1->data [i])
636 * mono_bitset_foreach:
638 * @func: Function to call for every set bit
639 * @data: pass this as second arg to func
641 * Calls func for every bit set in bitset. Argument 1 is the number of
642 * the bit set, argument 2 is data
645 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
648 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
650 for (j = 0; j < BITS_PER_CHUNK; ++j)
651 if (set->data [i] & ((gsize)1 << j))
652 func (j + i * BITS_PER_CHUNK, data);
661 * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
665 MonoBitSet *set1, *set2, *set3, *set4;
669 set1 = mono_bitset_new (60, 0);
670 set4 = mono_bitset_new (60, 0);
672 if (mono_bitset_count (set1) != 0)
676 mono_bitset_set (set1, 33);
677 if (mono_bitset_count (set1) != 1)
681 /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */
683 if (mono_bitset_find_first (set1, 0) != 33)
687 if (mono_bitset_find_first (set1, 33) != -1)
692 if (mono_bitset_find_first (set1, -100) != 33)
696 if (mono_bitset_find_last (set1, -1) != 33)
700 if (mono_bitset_find_last (set1, 33) != -1)
704 if (mono_bitset_find_last (set1, -100) != 33)
708 if (mono_bitset_find_last (set1, 34) != 33)
713 if (!mono_bitset_test (set1, 33))
717 if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
721 set2 = mono_bitset_clone (set1, 0);
722 if (mono_bitset_count (set2) != 1)
726 mono_bitset_invert (set2);
727 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
731 mono_bitset_clear (set2, 10);
732 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
737 set3 = mono_bitset_clone (set2, 0);
738 mono_bitset_union (set3, set1);
739 if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
743 mono_bitset_clear_all (set2);
744 if (mono_bitset_count (set2) != 0)
748 mono_bitset_invert (set2);
749 if (mono_bitset_count (set2) != mono_bitset_size (set2))
753 mono_bitset_set (set4, 0);
754 mono_bitset_set (set4, 1);
755 mono_bitset_set (set4, 10);
756 if (mono_bitset_count (set4) != 3)
761 for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
777 /* g_print ("count got: %d at %d\n", count, i); */
783 if (mono_bitset_find_first (set4, -1) != 0)
788 mono_bitset_set (set4, 31);
789 if (mono_bitset_find_first (set4, 10) != 31)
793 mono_bitset_free (set1);
795 set1 = mono_bitset_new (200, 0);
796 mono_bitset_set (set1, 0);
797 mono_bitset_set (set1, 1);
798 mono_bitset_set (set1, 10);
799 mono_bitset_set (set1, 31);
800 mono_bitset_set (set1, 150);
802 mono_bitset_free (set1);
803 mono_bitset_free (set2);
804 mono_bitset_free (set3);
805 mono_bitset_free (set4);
807 g_print ("total tests passed: %d\n", error - 1);