4 #include "monobitset.h"
7 #define BITS_PER_CHUNK MONO_BITSET_BITS_PER_CHUNK
10 * mono_bitset_alloc_size:
11 * @max_size: The numer 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
) {
213 /* there is probably some asm code that can do this much faster */
215 #if SIZEOF_VOID_P == 8
216 /* http://www.jjj.de/bitwizardry/bitwizardrypage.html */
217 d
-= (d
>>1) & 0x5555555555555555;
218 d
= ((d
>>2) & 0x3333333333333333) + (d
& 0x3333333333333333);
219 d
= ((d
>>4) + d
) & 0x0f0f0f0f0f0f0f0f;
220 d
*= 0x0101010101010101;
223 /* http://aggregate.org/MAGIC/ */
224 d
-= ((d
>> 1) & 0x55555555);
225 d
= (((d
>> 2) & 0x33333333) + (d
& 0x33333333));
226 d
= (((d
>> 4) + d
) & 0x0f0f0f0f);
229 count
+= (d
& 0x0000003f);
237 mono_bitset_count (const MonoBitSet
*set
) {
238 static const guint32 table
[] = {
239 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
241 guint32 i
, count
, val
;
244 for (i
= 0; i
< set
->size
/ BITS_PER_CHUNK
;+i
) {
247 val
= (val
& table
[0]) ((val
>> 1) & table
[0]);
248 val
= (val
& table
[1]) ((val
>> 2) & table
[1]);
249 val
= (val
& table
[2]) ((val
>> 4) & table
[2]);
250 val
= (val
& table
[3]) ((val
>> 8) & table
[3]);
251 val
= (val
& table
[4]) ((val
>> 16) & table
[4]);
263 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
264 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
265 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
266 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
267 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
268 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
269 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
270 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
274 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
275 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
280 my_g_bit_nth_lsf (gsize mask
, gint nth_bit
)
285 if ((mask
== 0) || (nth_bit
== BITS_PER_CHUNK
))
288 #if defined(__i386__) && defined(__GNUC__)
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__)
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);