1 /**
2 * \file
3 */
4
5 #include <glib.h>
6 #include <string.h>
7
8 #include "monobitset.h"
9 #include "config.h"
10
11 #define BITS_PER_CHUNK MONO_BITSET_BITS_PER_CHUNK
12
13 /**
14 * mono_bitset_alloc_size:
15 * \param max_size The number of bits you want to hold
16 * \param flags unused
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.
20 */
21 guint32
mono_bitset_alloc_size(guint32 max_size,guint32 flags)22 mono_bitset_alloc_size (guint32 max_size, guint32 flags) {
23 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
24
25 return sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY);
26 }
27
28 /**
29 * mono_bitset_new:
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.
34 */
35 MonoBitSet *
mono_bitset_new(guint32 max_size,guint32 flags)36 mono_bitset_new (guint32 max_size, guint32 flags) {
37 guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
38 MonoBitSet *result;
39
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;
43 return result;
44 }
45
46 /**
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
51 *
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.
55 */
56 MonoBitSet *
mono_bitset_mem_new(gpointer mem,guint32 max_size,guint32 flags)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;
60
61 result->size = real_size * BITS_PER_CHUNK;
62 result->flags = flags | MONO_BITSET_DONT_FREE;
63 return result;
64 }
65
66 /*
67 * mono_bitset_free:
68 * \param set bitset ptr to free
69 *
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.
73 */
74 void
mono_bitset_free(MonoBitSet * set)75 mono_bitset_free (MonoBitSet *set) {
76 if (!(set->flags & MONO_BITSET_DONT_FREE))
77 g_free (set);
78 }
79
80 /**
81 * mono_bitset_set:
82 * \param set bitset ptr
83 * \param pos set bit at this pos
84 *
85 * Set bit at \p pos, counting from 0.
86 */
87 void
mono_bitset_set(MonoBitSet * set,guint32 pos)88 mono_bitset_set (MonoBitSet *set, guint32 pos) {
89 int j = pos / BITS_PER_CHUNK;
90 int bit = pos % BITS_PER_CHUNK;
91
92 g_assert (pos < set->size);
93
94 set->data [j] |= (gsize)1 << bit;
95 }
96
97 /**
98 * mono_bitset_test:
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.
103 */
104 int
mono_bitset_test(const MonoBitSet * set,guint32 pos)105 mono_bitset_test (const MonoBitSet *set, guint32 pos) {
106 int j = pos / BITS_PER_CHUNK;
107 int bit = pos % BITS_PER_CHUNK;
108
109 g_return_val_if_fail (pos < set->size, 0);
110
111 return (set->data [j] & ((gsize)1 << bit)) > 0;
112 }
113
114 /**
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.
120 */
121 gsize
mono_bitset_test_bulk(const MonoBitSet * set,guint32 pos)122 mono_bitset_test_bulk (const MonoBitSet *set, guint32 pos) {
123 int j = pos / BITS_PER_CHUNK;
124
125 if (pos >= set->size)
126 return 0;
127 else
128 return set->data [j];
129 }
130
131 /**
132 * mono_bitset_clear:
133 * \param set bitset ptr
134 * \param pos unset bit at this pos
135 *
136 * Unset bit at \p pos, counting from 0.
137 */
138 void
mono_bitset_clear(MonoBitSet * set,guint32 pos)139 mono_bitset_clear (MonoBitSet *set, guint32 pos) {
140 int j = pos / BITS_PER_CHUNK;
141 int bit = pos % BITS_PER_CHUNK;
142
143 g_assert (pos < set->size);
144
145 set->data [j] &= ~((gsize)1 << bit);
146 }
147
148 /**
149 * mono_bitset_clear_all:
150 * \param set bitset ptr
151 *
152 * Unset all bits.
153 */
154 void
mono_bitset_clear_all(MonoBitSet * set)155 mono_bitset_clear_all (MonoBitSet *set) {
156 memset (set->data, 0, set->size / 8);
157 }
158
159 /**
160 * mono_bitset_set_all:
161 * \param set bitset ptr
162 *
163 * Set all bits.
164 */
165 void
mono_bitset_set_all(MonoBitSet * set)166 mono_bitset_set_all (MonoBitSet *set) {
167 memset (set->data, -1, set->size / 8);
168 }
169
170 /**
171 * mono_bitset_invert:
172 * \param set bitset ptr
173 *
174 * Flip all bits.
175 */
176 void
mono_bitset_invert(MonoBitSet * set)177 mono_bitset_invert (MonoBitSet *set) {
178 int i;
179 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
180 set->data [i] = ~set->data [i];
181 }
182
183 /**
184 * mono_bitset_size:
185 * \param set bitset ptr
186 * \returns the number of bits this bitset can hold.
187 */
188 guint32
mono_bitset_size(const MonoBitSet * set)189 mono_bitset_size (const MonoBitSet *set) {
190 return set->size;
191 }
192
193 /*
194 * should test wich version is faster.
195 */
196 #if 1
197
198 /**
199 * mono_bitset_count:
200 * \param set bitset ptr
201 * \returns number of bits that are set.
202 */
203 guint32
mono_bitset_count(const MonoBitSet * set)204 mono_bitset_count (const MonoBitSet *set) {
205 guint32 i, count;
206 gsize d;
207
208 count = 0;
209 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
210 d = set->data [i];
211 #ifdef __GNUC__
212 if (sizeof (gsize) == sizeof (unsigned int))
213 count += __builtin_popcount (d);
214 else
215 count += __builtin_popcountll (d);
216 #else
217 while (d) {
218 count ++;
219 d &= (d - 1);
220 }
221 #endif
222 }
223 return count;
224 }
225 #else
226 guint32
mono_bitset_count(const MonoBitSet * set)227 mono_bitset_count (const MonoBitSet *set) {
228 static const guint32 table [] = {
229 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
230 };
231 guint32 i, count, val;
232
233 count = 0;
234 for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
235 if (set->data [i]) {
236 val = set->data [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]);
242 count += val;
243 }
244 }
245 return count;
246 }
247
248 #endif
249
250 #if 0
251 const static int
252 bitstart_mask [] = {
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,
261 0x00000000
262 };
263
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)
266
267 #else
268
269 static inline gint
my_g_bit_nth_lsf(gsize mask,gint nth_bit)270 my_g_bit_nth_lsf (gsize mask, gint nth_bit)
271 {
272 nth_bit ++;
273 mask >>= nth_bit;
274
275 if ((mask == 0) || (nth_bit == BITS_PER_CHUNK))
276 return -1;
277
278 #if (defined(__i386__) && defined(__GNUC__))
279 {
280 int r;
281 /* This depends on mask != 0 */
282 __asm__("bsfl %1,%0\n\t"
283 : "=r" (r) : "g" (mask));
284 return nth_bit + r;
285 }
286 #elif defined(__x86_64) && defined(__GNUC__)
287 {
288 guint64 r;
289
290 __asm__("bsfq %1,%0\n\t"
291 : "=r" (r) : "rm" (mask));
292 return nth_bit + r;
293 }
294 #else
295 while (! (mask & 0x1)) {
296 mask >>= 1;
297 nth_bit ++;
298 }
299
300 return nth_bit;
301 #endif
302 }
303
304 static inline gint
my_g_bit_nth_lsf_nomask(gsize mask)305 my_g_bit_nth_lsf_nomask (gsize mask)
306 {
307 /* Mask is expected to be != 0 */
308 #if (defined(__i386__) && defined(__GNUC__))
309 int r;
310
311 __asm__("bsfl %1,%0\n\t"
312 : "=r" (r) : "rm" (mask));
313 return r;
314 #elif defined(__x86_64) && defined(__GNUC__)
315 guint64 r;
316
317 __asm__("bsfq %1,%0\n\t"
318 : "=r" (r) : "rm" (mask));
319 return r;
320 #else
321 int nth_bit = 0;
322
323 while (! (mask & 0x1)) {
324 mask >>= 1;
325 nth_bit ++;
326 }
327
328 return nth_bit;
329 #endif
330 }
331
332 #endif
333
334 static inline int
my_g_bit_nth_msf(gsize mask,gint nth_bit)335 my_g_bit_nth_msf (gsize mask,
336 gint nth_bit)
337 {
338 int i;
339
340 if (nth_bit == 0)
341 return -1;
342
343 mask <<= BITS_PER_CHUNK - nth_bit;
344
345 i = BITS_PER_CHUNK;
346 while ((i > 0) && !(mask >> (BITS_PER_CHUNK - 8))) {
347 mask <<= 8;
348 i -= 8;
349 }
350 if (mask == 0)
351 return -1;
352
353 do {
354 i--;
355 if (mask & ((gsize)1 << (BITS_PER_CHUNK - 1)))
356 return i - (BITS_PER_CHUNK - nth_bit);
357 mask <<= 1;
358 }
359 while (mask);
360
361 return -1;
362 }
363
364 static int
find_first_unset(gsize mask,gint nth_bit)365 find_first_unset (gsize mask, gint nth_bit)
366 {
367 do {
368 nth_bit++;
369 if (!(mask & ((gsize)1 << nth_bit))) {
370 if (nth_bit == BITS_PER_CHUNK)
371 /* On 64 bit platforms, 1 << 64 == 1 */
372 return -1;
373 else
374 return nth_bit;
375 }
376 } while (nth_bit < BITS_PER_CHUNK);
377 return -1;
378 }
379
380 /**
381 * mono_bitset_find_start:
382 * \param set bitset ptr
383 * Equivalent to <code>mono_bitset_find_first (set, -1)</code> but faster.
384 */
385 int
mono_bitset_find_start(const MonoBitSet * set)386 mono_bitset_find_start (const MonoBitSet *set)
387 {
388 int i;
389
390 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
391 if (set->data [i])
392 return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
393 }
394 return -1;
395 }
396
397 /**
398 * mono_bitset_find_first:
399 * \param set bitset ptr
400 * \param pos pos to search after (not including)
401 * \returns position of first set bit after \p pos. If \p pos < 0, begin search from
402 * start. Return \c -1 if no bit set is found.
403 */
404 int
mono_bitset_find_first(const MonoBitSet * set,gint pos)405 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
406 int j;
407 int bit;
408 int result, i;
409
410 if (pos < 0) {
411 j = 0;
412 bit = -1;
413 } else {
414 j = pos / BITS_PER_CHUNK;
415 bit = pos % BITS_PER_CHUNK;
416 g_assert (pos < set->size);
417 }
418 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
419
420 if (set->data [j]) {
421 result = my_g_bit_nth_lsf (set->data [j], bit);
422 if (result != -1)
423 return result + j * BITS_PER_CHUNK;
424 }
425 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
426 if (set->data [i])
427 return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
428 }
429 return -1;
430 }
431
432 /**
433 * mono_bitset_find_last:
434 * \param set bitset ptr
435 * \param pos pos to search before (not including)
436 * \returns position of last set bit before \p pos. If \p pos < 0 search is
437 * started from the end. Returns \c -1 if no set bit is found.
438 */
439 int
mono_bitset_find_last(const MonoBitSet * set,gint pos)440 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
441 int j, bit, result, i;
442
443 if (pos < 0)
444 pos = set->size - 1;
445
446 j = pos / BITS_PER_CHUNK;
447 bit = pos % BITS_PER_CHUNK;
448
449 g_return_val_if_fail (pos < set->size, -1);
450
451 if (set->data [j]) {
452 result = my_g_bit_nth_msf (set->data [j], bit);
453 if (result != -1)
454 return result + j * BITS_PER_CHUNK;
455 }
456 for (i = --j; i >= 0; --i) {
457 if (set->data [i])
458 return my_g_bit_nth_msf (set->data [i], BITS_PER_CHUNK) + i * BITS_PER_CHUNK;
459 }
460 return -1;
461 }
462
463 /**
464 * mono_bitset_find_first_unset:
465 * \param set bitset ptr
466 * \param pos pos to search after (not including)
467 * \returns position of first unset bit after \p pos. If \p pos < 0 begin search from
468 * start. Return \c -1 if no bit set is found.
469 */
470 int
mono_bitset_find_first_unset(const MonoBitSet * set,gint pos)471 mono_bitset_find_first_unset (const MonoBitSet *set, gint pos) {
472 int j;
473 int bit;
474 int result, i;
475
476 if (pos < 0) {
477 j = 0;
478 bit = -1;
479 } else {
480 j = pos / BITS_PER_CHUNK;
481 bit = pos % BITS_PER_CHUNK;
482 g_return_val_if_fail (pos < set->size, -1);
483 }
484 /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
485
486 if (set->data [j] != -1) {
487 result = find_first_unset (set->data [j], bit);
488 if (result != -1)
489 return result + j * BITS_PER_CHUNK;
490 }
491 for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
492 if (set->data [i] != -1) {
493 return find_first_unset (set->data [i], -1) + i * BITS_PER_CHUNK;
494 }
495 }
496 return -1;
497 }
498
499 /**
500 * mono_bitset_clone:
501 * \param set bitset ptr to clone
502 * \param new_size number of bits the cloned bitset can hold
503 * \returns a cloned bitset of size \p new_size. \c MONO_BITSET_DONT_FREE
504 * unset in cloned bitset. If \p new_size is 0, the cloned object is just
505 * as big.
506 */
507 MonoBitSet*
mono_bitset_clone(const MonoBitSet * set,guint32 new_size)508 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
509 MonoBitSet *result;
510
511 if (!new_size)
512 new_size = set->size;
513 result = mono_bitset_new (new_size, set->flags);
514 result->flags &= ~MONO_BITSET_DONT_FREE;
515 memcpy (result->data, set->data, set->size / 8);
516 return result;
517 }
518
519 /**
520 * mono_bitset_copyto:
521 * \param src bitset ptr to copy from
522 * \param dest bitset ptr to copy to
523 *
524 * Copy one bitset to another.
525 */
526 void
mono_bitset_copyto(const MonoBitSet * src,MonoBitSet * dest)527 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
528 g_assert (dest->size <= src->size);
529
530 memcpy (&dest->data, &src->data, dest->size / 8);
531 }
532
533 /**
534 * mono_bitset_union:
535 * \param dest bitset ptr to hold union
536 * \param src bitset ptr to copy
537 *
538 * Make union of one bitset and another.
539 */
540 void
mono_bitset_union(MonoBitSet * dest,const MonoBitSet * src)541 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
542 int i, size;
543
544 g_assert (src->size <= dest->size);
545
546 size = dest->size / BITS_PER_CHUNK;
547 for (i = 0; i < size; ++i)
548 dest->data [i] |= src->data [i];
549 }
550
551 /**
552 * mono_bitset_intersection:
553 * \param dest bitset ptr to hold intersection
554 * \param src bitset ptr to copy
555 *
556 * Make intersection of one bitset and another.
557 */
558 void
mono_bitset_intersection(MonoBitSet * dest,const MonoBitSet * src)559 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
560 int i, size;
561
562 g_assert (src->size <= dest->size);
563
564 size = dest->size / BITS_PER_CHUNK;
565 for (i = 0; i < size; ++i)
566 dest->data [i] &= src->data [i];
567 }
568
569 /**
570 * mono_bitset_intersection_2:
571 * \param dest bitset ptr to hold intersection
572 * \param src1 first bitset
573 * \param src2 second bitset
574 *
575 * Make intersection of two bitsets
576 */
577 void
mono_bitset_intersection_2(MonoBitSet * dest,const MonoBitSet * src1,const MonoBitSet * src2)578 mono_bitset_intersection_2 (MonoBitSet *dest, const MonoBitSet *src1, const MonoBitSet *src2) {
579 int i, size;
580
581 g_assert (src1->size <= dest->size);
582 g_assert (src2->size <= dest->size);
583
584 size = dest->size / BITS_PER_CHUNK;
585 for (i = 0; i < size; ++i)
586 dest->data [i] = src1->data [i] & src2->data [i];
587 }
588
589 /**
590 * mono_bitset_sub:
591 * \param dest bitset ptr to hold bitset - src
592 * \param src bitset ptr to copy
593 *
594 * Unset all bits in \p dest that are set in \p src.
595 */
596 void
mono_bitset_sub(MonoBitSet * dest,const MonoBitSet * src)597 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
598 int i, size;
599
600 g_assert (src->size <= dest->size);
601
602 size = src->size / BITS_PER_CHUNK;
603 for (i = 0; i < size; ++i)
604 dest->data [i] &= ~src->data [i];
605 }
606
607 /**
608 * mono_bitset_equal:
609 * \param src bitset ptr
610 * \param src1 bitset ptr
611 * \returns TRUE if their size are the same and the same bits are set in
612 * both bitsets.
613 */
614 gboolean
mono_bitset_equal(const MonoBitSet * src,const MonoBitSet * src1)615 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
616 int i;
617 if (src->size != src1->size)
618 return FALSE;
619
620 for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
621 if (src->data [i] != src1->data [i])
622 return FALSE;
623 return TRUE;
624 }
625
626 /**
627 * mono_bitset_foreach:
628 * \param set bitset ptr
629 * \param func Function to call for every set bit
630 * \param data pass this as second arg to func
631 * Calls \p func for every bit set in bitset. Argument 1 is the number of
632 * the bit set, argument 2 is data
633 */
634 void
mono_bitset_foreach(MonoBitSet * set,MonoBitSetFunc func,gpointer data)635 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
636 {
637 int i, j;
638 for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
639 if (set->data [i]) {
640 for (j = 0; j < BITS_PER_CHUNK; ++j)
641 if (set->data [i] & ((gsize)1 << j))
642 func (j + i * BITS_PER_CHUNK, data);
643 }
644 }
645 }
646
647 #ifdef TEST_BITSET
648
649 /*
650 * Compile with:
651 * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
652 */
653 int
main()654 main() {
655 MonoBitSet *set1, *set2, *set3, *set4;
656 int error = 1;
657 int count, i;
658
659 set1 = mono_bitset_new (60, 0);
660 set4 = mono_bitset_new (60, 0);
661
662 if (mono_bitset_count (set1) != 0)
663 return error;
664 error++;
665
666 mono_bitset_set (set1, 33);
667 if (mono_bitset_count (set1) != 1)
668 return error;
669 error++;
670
671 /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */
672
673 if (mono_bitset_find_first (set1, 0) != 33)
674 return error;
675 error++;
676
677 if (mono_bitset_find_first (set1, 33) != -1)
678 return error;
679 error++;
680
681 /* test 5 */
682 if (mono_bitset_find_first (set1, -100) != 33)
683 return error;
684 error++;
685
686 if (mono_bitset_find_last (set1, -1) != 33)
687 return error;
688 error++;
689
690 if (mono_bitset_find_last (set1, 33) != -1)
691 return error;
692 error++;
693
694 if (mono_bitset_find_last (set1, -100) != 33)
695 return error;
696 error++;
697
698 if (mono_bitset_find_last (set1, 34) != 33)
699 return error;
700 error++;
701
702 /* test 10 */
703 if (!mono_bitset_test (set1, 33))
704 return error;
705 error++;
706
707 if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
708 return error;
709 error++;
710
711 set2 = mono_bitset_clone (set1, 0);
712 if (mono_bitset_count (set2) != 1)
713 return error;
714 error++;
715
716 mono_bitset_invert (set2);
717 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
718 return error;
719 error++;
720
721 mono_bitset_clear (set2, 10);
722 if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
723 return error;
724 error++;
725
726 /* test 15 */
727 set3 = mono_bitset_clone (set2, 0);
728 mono_bitset_union (set3, set1);
729 if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
730 return error;
731 error++;
732
733 mono_bitset_clear_all (set2);
734 if (mono_bitset_count (set2) != 0)
735 return error;
736 error++;
737
738 mono_bitset_invert (set2);
739 if (mono_bitset_count (set2) != mono_bitset_size (set2))
740 return error;
741 error++;
742
743 mono_bitset_set (set4, 0);
744 mono_bitset_set (set4, 1);
745 mono_bitset_set (set4, 10);
746 if (mono_bitset_count (set4) != 3)
747 return error;
748 error++;
749
750 count = 0;
751 for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
752 count ++;
753 switch (count) {
754 case 1:
755 if (i != 0)
756 return error;
757 break;
758 case 2:
759 if (i != 1)
760 return error;
761 break;
762 case 3:
763 if (i != 10)
764 return error;
765 break;
766 }
767 /* g_print ("count got: %d at %d\n", count, i); */
768 }
769 if (count != 3)
770 return error;
771 error++;
772
773 if (mono_bitset_find_first (set4, -1) != 0)
774 return error;
775 error++;
776
777 /* 20 */
778 mono_bitset_set (set4, 31);
779 if (mono_bitset_find_first (set4, 10) != 31)
780 return error;
781 error++;
782
783 mono_bitset_free (set1);
784
785 set1 = mono_bitset_new (200, 0);
786 mono_bitset_set (set1, 0);
787 mono_bitset_set (set1, 1);
788 mono_bitset_set (set1, 10);
789 mono_bitset_set (set1, 31);
790 mono_bitset_set (set1, 150);
791
792 mono_bitset_free (set1);
793 mono_bitset_free (set2);
794 mono_bitset_free (set3);
795 mono_bitset_free (set4);
796
797 g_print ("total tests passed: %d\n", error - 1);
798
799 return 0;
800 }
801
802 #endif
803