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