Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / utils / monobitset.c
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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*
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
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
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
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
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
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
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
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 
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