8 #include "monobitset.h"
11 #define BITS_PER_CHUNK MONO_BITSET_BITS_PER_CHUNK
14 * mono_bitset_alloc_size:
15 * \param max_size The number of bits you want to hold
17 * \returns the number of bytes required to hold the bitset.
18 * Useful to allocate it on the stack or with mempool.
19 * Use with \c mono_bitset_mem_new.
22 mono_bitset_alloc_size (guint32 max_size, guint32 flags) {
23 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
25 return sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY);
30 * \param max_size The numer of bits you want to hold
31 * \param flags bitfield of flags
32 * \returns a bitset of size \p max_size. It must be freed using
33 * \c mono_bitset_free.
36 mono_bitset_new (guint32 max_size, guint32 flags) {
37 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
40 result = (MonoBitSet *) g_malloc0 (sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY));
41 result->size = real_size * BITS_PER_CHUNK;
42 result->flags = flags;
47 * mono_bitset_mem_new:
48 * \param mem The location the bitset is stored
49 * \param max_size The number of bits you want to hold
50 * \param flags bitfield of flags
52 * Return \p mem, which is now a initialized bitset of size \p max_size. It is
53 * not freed even if called with \c mono_bitset_free. \p mem must be at least
54 * as big as \c mono_bitset_alloc_size returns for the same \p max_size.
57 mono_bitset_mem_new (gpointer mem, guint32 max_size, guint32 flags) {
58 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
59 MonoBitSet *result = (MonoBitSet *) mem;
61 result->size = real_size * BITS_PER_CHUNK;
62 result->flags = flags | MONO_BITSET_DONT_FREE;
68 * \param set bitset ptr to free
70 * Free bitset unless flags have \c MONO_BITSET_DONT_FREE set. Does not
71 * free anything if flag \c MONO_BITSET_DONT_FREE is set or bitset was
72 * made with \c mono_bitset_mem_new.
75 mono_bitset_free (MonoBitSet *set) {
76 if (!(set->flags & MONO_BITSET_DONT_FREE))
82 * \param set bitset ptr
83 * \param pos set bit at this pos
85 * Set bit at \p pos, counting from 0.
88 mono_bitset_set (MonoBitSet *set, guint32 pos) {
89 int j = pos / BITS_PER_CHUNK;
90 int bit = pos % BITS_PER_CHUNK;
92 g_assert (pos < set->size);
94 set->data [j] |= (gsize)1 << bit;
99 * \param set bitset ptr
100 * \param pos test bit at this pos
101 * Test bit at \p pos, counting from 0.
102 * \returns a nonzero value if set, 0 otherwise.
105 mono_bitset_test (const MonoBitSet *set, guint32 pos) {
106 int j = pos / BITS_PER_CHUNK;
107 int bit = pos % BITS_PER_CHUNK;
109 g_return_val_if_fail (pos < set->size, 0);
111 return (set->data [j] & ((gsize)1 << bit)) > 0;
115 * mono_bitset_test_bulk:
116 * \param set bitset ptr
117 * \param pos test bit at this pos
118 * \returns 32/64 bits from the bitset, starting from \p 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];
133 * \param set bitset ptr
134 * \param pos unset bit at this pos
136 * Unset bit at \p 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:
150 * \param set bitset ptr
155 mono_bitset_clear_all (MonoBitSet *set) {
156 memset (set->data, 0, set->size / 8);
160 * mono_bitset_set_all:
161 * \param set bitset ptr
166 mono_bitset_set_all (MonoBitSet *set) {
167 memset (set->data, -1, set->size / 8);
171 * mono_bitset_invert:
172 * \param set bitset ptr
177 mono_bitset_invert (MonoBitSet *set) {
179 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
180 set->data [i] = ~set->data [i];
185 * \param set bitset ptr
186 * \returns the number of bits this bitset can hold.
189 mono_bitset_size (const MonoBitSet *set) {
194 * should test wich version is faster.
200 * \param set bitset ptr
201 * \returns number of bits that are set.
204 mono_bitset_count (const MonoBitSet *set) {
209 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
212 if (sizeof (gsize) == sizeof (unsigned int))
213 count += __builtin_popcount (d);
215 count += __builtin_popcountll (d);
227 mono_bitset_count (const MonoBitSet *set) {
228 static const guint32 table [] = {
229 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
231 guint32 i, count, val;
234 for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
237 val = (val & table [0]) ((val >> 1) & table [0]);
238 val = (val & table [1]) ((val >> 2) & table [1]);
239 val = (val & table [2]) ((val >> 4) & table [2]);
240 val = (val & table [3]) ((val >> 8) & table [3]);
241 val = (val & table [4]) ((val >> 16) & table [4]);
253 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
254 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
255 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
256 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
257 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
258 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
259 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
260 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
264 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
265 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
270 my_g_bit_nth_lsf (gsize mask, gint nth_bit)
275 if ((mask == 0) || (nth_bit == BITS_PER_CHUNK))
278 #if defined(__native_client__) && (defined(__i386__) || defined(__x86_64))
279 #define USE_X86_32BIT_INSTRUCTIONS 1
282 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
285 /* This depends on mask != 0 */
286 __asm__("bsfl %1,%0\n\t"
287 : "=r" (r) : "g" (mask));
290 #elif defined(__x86_64) && defined(__GNUC__)
294 __asm__("bsfq %1,%0\n\t"
295 : "=r" (r) : "rm" (mask));
299 while (! (mask & 0x1)) {
309 my_g_bit_nth_lsf_nomask (gsize mask)
311 /* Mask is expected to be != 0 */
312 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
315 __asm__("bsfl %1,%0\n\t"
316 : "=r" (r) : "rm" (mask));
318 #elif defined(__x86_64) && defined(__GNUC__)
321 __asm__("bsfq %1,%0\n\t"
322 : "=r" (r) : "rm" (mask));
327 while (! (mask & 0x1)) {
339 my_g_bit_nth_msf (gsize mask,
347 mask <<= BITS_PER_CHUNK - nth_bit;
350 while ((i > 0) && !(mask >> (BITS_PER_CHUNK - 8))) {
359 if (mask & ((gsize)1 << (BITS_PER_CHUNK - 1)))
360 return i - (BITS_PER_CHUNK - nth_bit);
369 find_first_unset (gsize mask, gint nth_bit)
373 if (!(mask & ((gsize)1 << nth_bit))) {
374 if (nth_bit == BITS_PER_CHUNK)
375 /* On 64 bit platforms, 1 << 64 == 1 */
380 } while (nth_bit < BITS_PER_CHUNK);
385 * mono_bitset_find_start:
386 * \param set bitset ptr
387 * Equivalent to <code>mono_bitset_find_first (set, -1)</code> 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:
403 * \param set bitset ptr
404 * \param pos pos to search after (not including)
405 * \returns position of first set bit after \p pos. If \p pos < 0, begin search from
406 * start. Return \c -1 if no bit set is found.
409 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
418 j = pos / BITS_PER_CHUNK;
419 bit = pos % BITS_PER_CHUNK;
420 g_assert (pos < set->size);
422 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
425 result = my_g_bit_nth_lsf (set->data [j], bit);
427 return result + j * BITS_PER_CHUNK;
429 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
431 return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
437 * mono_bitset_find_last:
438 * \param set bitset ptr
439 * \param pos pos to search before (not including)
440 * \returns position of last set bit before \p pos. If \p pos < 0 search is
441 * started from the end. Returns \c -1 if no set bit is found.
444 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
445 int j, bit, result, i;
450 j = pos / BITS_PER_CHUNK;
451 bit = pos % BITS_PER_CHUNK;
453 g_return_val_if_fail (pos < set->size, -1);
456 result = my_g_bit_nth_msf (set->data [j], bit);
458 return result + j * BITS_PER_CHUNK;
460 for (i = --j; i >= 0; --i) {
462 return my_g_bit_nth_msf (set->data [i], BITS_PER_CHUNK) + i * BITS_PER_CHUNK;
468 * mono_bitset_find_first_unset:
469 * \param set bitset ptr
470 * \param pos pos to search after (not including)
471 * \returns position of first unset bit after \p pos. If \p pos < 0 begin search from
472 * start. Return \c -1 if no bit set is found.
475 mono_bitset_find_first_unset (const MonoBitSet *set, gint pos) {
484 j = pos / BITS_PER_CHUNK;
485 bit = pos % BITS_PER_CHUNK;
486 g_return_val_if_fail (pos < set->size, -1);
488 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
490 if (set->data [j] != -1) {
491 result = find_first_unset (set->data [j], bit);
493 return result + j * BITS_PER_CHUNK;
495 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
496 if (set->data [i] != -1) {
497 return find_first_unset (set->data [i], -1) + i * BITS_PER_CHUNK;
505 * \param set bitset ptr to clone
506 * \param new_size number of bits the cloned bitset can hold
507 * \returns a cloned bitset of size \p new_size. \c MONO_BITSET_DONT_FREE
508 * unset in cloned bitset. If \p new_size is 0, the cloned object is just
512 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
516 new_size = set->size;
517 result = mono_bitset_new (new_size, set->flags);
518 result->flags &= ~MONO_BITSET_DONT_FREE;
519 memcpy (result->data, set->data, set->size / 8);
524 * mono_bitset_copyto:
525 * \param src bitset ptr to copy from
526 * \param dest bitset ptr to copy to
528 * Copy one bitset to another.
531 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
532 g_assert (dest->size <= src->size);
534 memcpy (&dest->data, &src->data, dest->size / 8);
539 * \param dest bitset ptr to hold union
540 * \param src bitset ptr to copy
542 * Make union of one bitset and another.
545 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
548 g_assert (src->size <= dest->size);
550 size = dest->size / BITS_PER_CHUNK;
551 for (i = 0; i < size; ++i)
552 dest->data [i] |= src->data [i];
556 * mono_bitset_intersection:
557 * \param dest bitset ptr to hold intersection
558 * \param src bitset ptr to copy
560 * Make intersection of one bitset and another.
563 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
566 g_assert (src->size <= dest->size);
568 size = dest->size / BITS_PER_CHUNK;
569 for (i = 0; i < size; ++i)
570 dest->data [i] &= src->data [i];
574 * mono_bitset_intersection_2:
575 * \param dest bitset ptr to hold intersection
576 * \param src1 first bitset
577 * \param src2 second bitset
579 * Make intersection of two bitsets
582 mono_bitset_intersection_2 (MonoBitSet *dest, const MonoBitSet *src1, const MonoBitSet *src2) {
585 g_assert (src1->size <= dest->size);
586 g_assert (src2->size <= dest->size);
588 size = dest->size / BITS_PER_CHUNK;
589 for (i = 0; i < size; ++i)
590 dest->data [i] = src1->data [i] & src2->data [i];
595 * \param dest bitset ptr to hold bitset - src
596 * \param src bitset ptr to copy
598 * Unset all bits in \p dest that are set in \p src.
601 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
604 g_assert (src->size <= dest->size);
606 size = src->size / BITS_PER_CHUNK;
607 for (i = 0; i < size; ++i)
608 dest->data [i] &= ~src->data [i];
613 * \param src bitset ptr
614 * \param src1 bitset ptr
615 * \returns TRUE if their size are the same and the same bits are set in
619 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
621 if (src->size != src1->size)
624 for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
625 if (src->data [i] != src1->data [i])
631 * mono_bitset_foreach:
632 * \param set bitset ptr
633 * \param func Function to call for every set bit
634 * \param data pass this as second arg to func
635 * Calls \p func for every bit set in bitset. Argument 1 is the number of
636 * the bit set, argument 2 is data
639 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
642 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
644 for (j = 0; j < BITS_PER_CHUNK; ++j)
645 if (set->data [i] & ((gsize)1 << j))
646 func (j + i * BITS_PER_CHUNK, data);
655 * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
659 MonoBitSet *set1, *set2, *set3, *set4;
663 set1 = mono_bitset_new (60, 0);
664 set4 = mono_bitset_new (60, 0);
666 if (mono_bitset_count (set1) != 0)
670 mono_bitset_set (set1, 33);
671 if (mono_bitset_count (set1) != 1)
675 /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */
677 if (mono_bitset_find_first (set1, 0) != 33)
681 if (mono_bitset_find_first (set1, 33) != -1)
686 if (mono_bitset_find_first (set1, -100) != 33)
690 if (mono_bitset_find_last (set1, -1) != 33)
694 if (mono_bitset_find_last (set1, 33) != -1)
698 if (mono_bitset_find_last (set1, -100) != 33)
702 if (mono_bitset_find_last (set1, 34) != 33)
707 if (!mono_bitset_test (set1, 33))
711 if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
715 set2 = mono_bitset_clone (set1, 0);
716 if (mono_bitset_count (set2) != 1)
720 mono_bitset_invert (set2);
721 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
725 mono_bitset_clear (set2, 10);
726 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
731 set3 = mono_bitset_clone (set2, 0);
732 mono_bitset_union (set3, set1);
733 if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
737 mono_bitset_clear_all (set2);
738 if (mono_bitset_count (set2) != 0)
742 mono_bitset_invert (set2);
743 if (mono_bitset_count (set2) != mono_bitset_size (set2))
747 mono_bitset_set (set4, 0);
748 mono_bitset_set (set4, 1);
749 mono_bitset_set (set4, 10);
750 if (mono_bitset_count (set4) != 3)
755 for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
771 /* g_print ("count got: %d at %d\n", count, i); */
777 if (mono_bitset_find_first (set4, -1) != 0)
782 mono_bitset_set (set4, 31);
783 if (mono_bitset_find_first (set4, 10) != 31)
787 mono_bitset_free (set1);
789 set1 = mono_bitset_new (200, 0);
790 mono_bitset_set (set1, 0);
791 mono_bitset_set (set1, 1);
792 mono_bitset_set (set1, 10);
793 mono_bitset_set (set1, 31);
794 mono_bitset_set (set1, 150);
796 mono_bitset_free (set1);
797 mono_bitset_free (set2);
798 mono_bitset_free (set3);
799 mono_bitset_free (set4);
801 g_print ("total tests passed: %d\n", error - 1);