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