Merge pull request #1222 from LogosBible/uri-trycreate
[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 = (MonoBitSet *) 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 = (MonoBitSet *) 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 #ifdef __GNUC__
214                 if (sizeof (gsize) == sizeof (unsigned long))
215                         count += __builtin_popcountl (d);
216                 else
217                         count += __builtin_popcount (d);
218 #else
219                 while (d) {
220                         count ++;
221                         d &= (d - 1);
222                 }
223 #endif
224         }
225         return count;
226 }
227 #else
228 guint32
229 mono_bitset_count (const MonoBitSet *set) {
230         static const guint32 table [] = {
231                 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
232         };
233         guint32 i, count, val;
234
235         count = 0;
236         for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
237                 if (set->data [i]) {
238                         val = set->data [i];
239                         val = (val & table [0]) ((val >> 1) & table [0]);
240                         val = (val & table [1]) ((val >> 2) & table [1]);
241                         val = (val & table [2]) ((val >> 4) & table [2]);
242                         val = (val & table [3]) ((val >> 8) & table [3]);
243                         val = (val & table [4]) ((val >> 16) & table [4]);
244                         count += val;
245                 }
246         }
247         return count;
248 }
249
250 #endif
251
252 #if 0
253 const static int 
254 bitstart_mask [] = {
255         0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
256         0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
257         0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
258         0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
259         0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
260         0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
261         0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
262         0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
263         0x00000000
264 };
265
266 #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
267 #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
268
269 #else
270
271 static inline gint
272 my_g_bit_nth_lsf (gsize mask, gint nth_bit)
273 {
274         nth_bit ++;
275         mask >>= nth_bit;
276
277         if ((mask == 0) || (nth_bit == BITS_PER_CHUNK))
278                 return -1;
279
280 #if defined(__native_client__) && (defined(__i386__) || defined(__x86_64))
281 #define USE_X86_32BIT_INSTRUCTIONS 1
282 #endif
283
284 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
285  {
286          int r;
287          /* This depends on mask != 0 */
288          __asm__("bsfl %1,%0\n\t"
289                          : "=r" (r) : "g" (mask)); 
290          return nth_bit + r;
291  }
292 #elif defined(__x86_64) && defined(__GNUC__)
293  {
294         guint64 r;
295
296         __asm__("bsfq %1,%0\n\t"
297                         : "=r" (r) : "rm" (mask));
298         return nth_bit + r;
299  }
300 #else
301         while (! (mask & 0x1)) {
302                 mask >>= 1;
303                 nth_bit ++;
304         }
305
306         return nth_bit;
307 #endif
308 }
309
310 static inline gint
311 my_g_bit_nth_lsf_nomask (gsize mask)
312 {
313         /* Mask is expected to be != 0 */
314 #if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS)
315         int r;
316
317         __asm__("bsfl %1,%0\n\t"
318                         : "=r" (r) : "rm" (mask));
319         return r;
320 #elif defined(__x86_64) && defined(__GNUC__)
321         guint64 r;
322
323         __asm__("bsfq %1,%0\n\t"
324                         : "=r" (r) : "rm" (mask));
325         return r;
326 #else
327         int nth_bit = 0;
328
329         while (! (mask & 0x1)) {
330                 mask >>= 1;
331                 nth_bit ++;
332         }
333
334         return nth_bit;
335 #endif
336 }
337
338 #endif
339
340 static inline int
341 my_g_bit_nth_msf (gsize mask,
342                gint   nth_bit)
343 {
344         int i;
345
346         if (nth_bit == 0)
347                 return -1;
348
349         mask <<= BITS_PER_CHUNK - nth_bit;
350
351         i = BITS_PER_CHUNK;
352         while ((i > 0) && !(mask >> (BITS_PER_CHUNK - 8))) {
353                 mask <<= 8;
354                 i -= 8;
355         }
356         if (mask == 0)
357                 return -1;
358
359         do {
360                 i--;
361                 if (mask & ((gsize)1 << (BITS_PER_CHUNK - 1)))
362                         return i - (BITS_PER_CHUNK - nth_bit);
363                 mask <<= 1;
364     }
365         while (mask);
366
367         return -1;
368 }
369
370 static int
371 find_first_unset (gsize mask, gint nth_bit)
372 {
373         do {
374                 nth_bit++;
375                 if (!(mask & ((gsize)1 << nth_bit))) {
376                         if (nth_bit == BITS_PER_CHUNK)
377                                 /* On 64 bit platforms, 1 << 64 == 1 */
378                                 return -1;
379                         else
380                                 return nth_bit;
381                 }
382         } while (nth_bit < BITS_PER_CHUNK);
383         return -1;
384 }
385
386 /*
387  * mono_bitset_find_start:
388  * @set: bitset ptr
389  *
390  * Equivalent to mono_bitset_find_first (set, -1) but faster.
391  */
392 int
393 mono_bitset_find_start   (const MonoBitSet *set)
394 {
395         int i;
396
397         for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
398                 if (set->data [i])
399                         return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
400         }
401         return -1;
402 }
403
404 /*
405  * mono_bitset_find_first:
406  * @set: bitset ptr
407  * @pos: pos to search _after_ (not including)
408  *
409  * Returns position of first set bit after @pos. If pos < 0 begin search from
410  * start. Return -1 if no bit set is found.
411  */
412 int
413 mono_bitset_find_first (const MonoBitSet *set, gint pos) {
414         int j;
415         int bit;
416         int result, i;
417
418         if (pos < 0) {
419                 j = 0;
420                 bit = -1;
421         } else {
422                 j = pos / BITS_PER_CHUNK;
423                 bit = pos % BITS_PER_CHUNK;
424                 g_assert (pos < set->size);
425         }
426         /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
427
428         if (set->data [j]) {
429                 result = my_g_bit_nth_lsf (set->data [j], bit);
430                 if (result != -1)
431                         return result + j * BITS_PER_CHUNK;
432         }
433         for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
434                 if (set->data [i])
435                         return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
436         }
437         return -1;
438 }
439
440 /*
441  * mono_bitset_find_last:
442  * @set: bitset ptr
443  * @pos: pos to search _before_ (not including)
444  *
445  * Returns position of last set bit before pos. If pos < 0 search is
446  * started from the end. Returns -1 if no set bit is found.
447  */
448 int
449 mono_bitset_find_last (const MonoBitSet *set, gint pos) {
450         int j, bit, result, i;
451
452         if (pos < 0)
453                 pos = set->size - 1;
454                 
455         j = pos / BITS_PER_CHUNK;
456         bit = pos % BITS_PER_CHUNK;
457
458         g_return_val_if_fail (pos < set->size, -1);
459
460         if (set->data [j]) {
461                 result = my_g_bit_nth_msf (set->data [j], bit);
462                 if (result != -1)
463                         return result + j * BITS_PER_CHUNK;
464         }
465         for (i = --j; i >= 0; --i) {
466                 if (set->data [i])
467                         return my_g_bit_nth_msf (set->data [i], BITS_PER_CHUNK) + i * BITS_PER_CHUNK;
468         }
469         return -1;
470 }
471
472 /*
473  * mono_bitset_find_first_unset:
474  * @set: bitset ptr
475  * @pos: pos to search _after_ (not including)
476  *
477  * Returns position of first unset bit after @pos. If pos < 0 begin search from
478  * start. Return -1 if no bit set is found.
479  */
480 int
481 mono_bitset_find_first_unset (const MonoBitSet *set, gint pos) {
482         int j;
483         int bit;
484         int result, i;
485
486         if (pos < 0) {
487                 j = 0;
488                 bit = -1;
489         } else {
490                 j = pos / BITS_PER_CHUNK;
491                 bit = pos % BITS_PER_CHUNK;
492                 g_return_val_if_fail (pos < set->size, -1);
493         }
494         /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
495
496         if (set->data [j] != -1) {
497                 result = find_first_unset (set->data [j], bit);
498                 if (result != -1)
499                         return result + j * BITS_PER_CHUNK;
500         }
501         for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
502                 if (set->data [i] != -1) {
503                         return find_first_unset (set->data [i], -1) + i * BITS_PER_CHUNK;
504                 }
505         }
506         return -1;
507 }
508
509 /*
510  * mono_bitset_clone:
511  * @set: bitset ptr to clone
512  * @new_size: number of bits the cloned bitset can hold
513  *
514  * Return a cloned bitset of size new_size. MONO_BITSET_DONT_FREE
515  * unset in cloned bitset. If new_size is 0, the cloned object is just
516  * as big.
517  */
518 MonoBitSet*
519 mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
520         MonoBitSet *result;
521
522         if (!new_size)
523                 new_size = set->size;
524         result = mono_bitset_new (new_size, set->flags);
525         result->flags &= ~MONO_BITSET_DONT_FREE;
526         memcpy (result->data, set->data, set->size / 8);
527         return result;
528 }
529
530 /*
531  * mono_bitset_copyto:
532  * @src: bitset ptr to copy from
533  * @dest: bitset ptr to copy to
534  *
535  * Copy one bitset to another.
536  */
537 void
538 mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
539         g_assert (dest->size <= src->size);
540
541         memcpy (&dest->data, &src->data, dest->size / 8);
542 }
543
544 /*
545  * mono_bitset_union:
546  * @dest: bitset ptr to hold union
547  * @src: bitset ptr to copy
548  *
549  * Make union of one bitset and another.
550  */
551 void
552 mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
553         int i, size;
554
555         g_assert (src->size <= dest->size);
556
557         size = dest->size / BITS_PER_CHUNK;
558         for (i = 0; i < size; ++i)
559                 dest->data [i] |= src->data [i];
560 }
561
562 /*
563  * mono_bitset_intersection:
564  * @dest: bitset ptr to hold intersection
565  * @src: bitset ptr to copy
566  *
567  * Make intersection of one bitset and another.
568  */
569 void
570 mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
571         int i, size;
572
573         g_assert (src->size <= dest->size);
574
575         size = dest->size / BITS_PER_CHUNK;
576         for (i = 0; i < size; ++i)
577                 dest->data [i] &= src->data [i];
578 }
579
580 /*
581  * mono_bitset_intersection_2:
582  * @dest: bitset ptr to hold intersection
583  * @src1: first bitset
584  * @src2: second bitset
585  *
586  * Make intersection of two bitsets
587  */
588 void
589 mono_bitset_intersection_2 (MonoBitSet *dest, const MonoBitSet *src1, const MonoBitSet *src2) {
590         int i, size;
591
592         g_assert (src1->size <= dest->size);
593         g_assert (src2->size <= dest->size);
594
595         size = dest->size / BITS_PER_CHUNK;
596         for (i = 0; i < size; ++i)
597                 dest->data [i] = src1->data [i] & src2->data [i];
598 }
599
600 /*
601  * mono_bitset_sub:
602  * @dest: bitset ptr to hold bitset - src
603  * @src: bitset ptr to copy
604  *
605  * Unset all bits in dest, which are set in src.
606  */
607 void
608 mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
609         int i, size;
610
611         g_assert (src->size <= dest->size);
612
613         size = src->size / BITS_PER_CHUNK;
614         for (i = 0; i < size; ++i)
615                 dest->data [i] &= ~src->data [i];
616 }
617
618 /*
619  * mono_bitset_equal:
620  * @src: bitset ptr
621  * @src1: bitset ptr
622  *
623  * return TRUE if their size are the same and the same bits are set in
624  * both bitsets.
625  */
626 gboolean
627 mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
628         int i;
629         if (src->size != src1->size)
630                 return FALSE;
631
632         for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
633                 if (src->data [i] != src1->data [i])
634                         return FALSE;
635         return TRUE;
636 }
637
638 /*
639  * mono_bitset_foreach:
640  * @set: bitset ptr
641  * @func: Function to call for every set bit
642  * @data: pass this as second arg to func
643  *
644  * Calls func for every bit set in bitset. Argument 1 is the number of
645  * the bit set, argument 2 is data
646  */
647 void
648 mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
649 {
650         int i, j;
651         for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
652                 if (set->data [i]) {
653                         for (j = 0; j < BITS_PER_CHUNK; ++j)
654                                 if (set->data [i] & ((gsize)1 << j))
655                                         func (j + i * BITS_PER_CHUNK, data);
656                 }
657         }
658 }
659
660 #ifdef TEST_BITSET
661
662 /*
663  * Compile with: 
664  * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
665  */
666 int 
667 main() {
668         MonoBitSet *set1, *set2, *set3, *set4;
669         int error = 1;
670         int count, i;
671
672         set1 = mono_bitset_new (60, 0);
673         set4 = mono_bitset_new (60, 0);
674
675         if (mono_bitset_count (set1) != 0)
676                 return error;
677         error++;
678         
679         mono_bitset_set (set1, 33);
680         if (mono_bitset_count (set1) != 1)
681                 return error;
682         error++;
683
684         /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */
685         
686         if (mono_bitset_find_first (set1, 0) != 33)
687                 return error;
688         error++;
689
690         if (mono_bitset_find_first (set1, 33) != -1)
691                 return error;
692         error++;
693
694         /* test 5 */
695         if (mono_bitset_find_first (set1, -100) != 33)
696                 return error;
697         error++;
698
699         if (mono_bitset_find_last (set1, -1) != 33)
700                 return error;
701         error++;
702
703         if (mono_bitset_find_last (set1, 33) != -1)
704                 return error;
705         error++;
706
707         if (mono_bitset_find_last (set1, -100) != 33)
708                 return error;
709         error++;
710
711         if (mono_bitset_find_last (set1, 34) != 33)
712                 return error;
713         error++;
714
715         /* test 10 */
716         if (!mono_bitset_test (set1, 33))
717                 return error;
718         error++;
719
720         if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
721                 return error;
722         error++;
723
724         set2 = mono_bitset_clone (set1, 0);
725         if (mono_bitset_count (set2) != 1)
726                 return error;
727         error++;
728
729         mono_bitset_invert (set2);
730         if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
731                 return error;
732         error++;
733
734         mono_bitset_clear (set2, 10);
735         if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
736                 return error;
737         error++;
738
739         /* test 15 */
740         set3 = mono_bitset_clone (set2, 0);
741         mono_bitset_union (set3, set1);
742         if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
743                 return error;
744         error++;
745
746         mono_bitset_clear_all (set2);
747         if (mono_bitset_count (set2) != 0)
748                 return error;
749         error++;
750
751         mono_bitset_invert (set2);
752         if (mono_bitset_count (set2) != mono_bitset_size (set2))
753                 return error;
754         error++;
755
756         mono_bitset_set (set4, 0);
757         mono_bitset_set (set4, 1);
758         mono_bitset_set (set4, 10);
759         if (mono_bitset_count (set4) != 3)
760                 return error;
761         error++;
762
763         count = 0;
764         for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
765                 count ++;
766                 switch (count) {
767                 case 1:
768                   if (i != 0)
769                     return error;
770                   break;
771                 case 2:
772                   if (i != 1)
773                     return error;
774                   break;
775                 case 3:
776                   if (i != 10)
777                     return error;
778                   break;
779                 }
780                 /* g_print ("count got: %d at %d\n", count, i); */
781         }
782         if (count != 3)
783                 return error;
784         error++;
785
786         if (mono_bitset_find_first (set4, -1) != 0)
787                 return error;
788         error++;
789
790         /* 20 */
791         mono_bitset_set (set4, 31);
792         if (mono_bitset_find_first (set4, 10) != 31)
793                 return error;
794         error++;
795
796         mono_bitset_free (set1);
797
798         set1 = mono_bitset_new (200, 0);
799         mono_bitset_set (set1, 0);
800         mono_bitset_set (set1, 1);
801         mono_bitset_set (set1, 10);
802         mono_bitset_set (set1, 31);
803         mono_bitset_set (set1, 150);
804
805         mono_bitset_free (set1);
806         mono_bitset_free (set2);
807         mono_bitset_free (set3);
808         mono_bitset_free (set4);
809
810         g_print ("total tests passed: %d\n", error - 1);
811         
812         return 0;
813 }
814
815 #endif