monobitset.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. /**
  2. * \file
  3. */
  4. #include <glib.h>
  5. #include <string.h>
  6. #include "monobitset.h"
  7. #include "config.h"
  8. #define BITS_PER_CHUNK MONO_BITSET_BITS_PER_CHUNK
  9. /**
  10. * mono_bitset_alloc_size:
  11. * \param max_size The number of bits you want to hold
  12. * \param flags unused
  13. * \returns the number of bytes required to hold the bitset.
  14. * Useful to allocate it on the stack or with mempool.
  15. * Use with \c mono_bitset_mem_new.
  16. */
  17. guint32
  18. mono_bitset_alloc_size (guint32 max_size, guint32 flags) {
  19. guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
  20. return sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY);
  21. }
  22. /**
  23. * mono_bitset_new:
  24. * \param max_size The numer of bits you want to hold
  25. * \param flags bitfield of flags
  26. * \returns a bitset of size \p max_size. It must be freed using
  27. * \c mono_bitset_free.
  28. */
  29. MonoBitSet *
  30. mono_bitset_new (guint32 max_size, guint32 flags) {
  31. guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
  32. MonoBitSet *result;
  33. result = (MonoBitSet *) g_malloc0 (sizeof (MonoBitSet) + sizeof (gsize) * (real_size - MONO_ZERO_LEN_ARRAY));
  34. result->size = real_size * BITS_PER_CHUNK;
  35. result->flags = flags;
  36. return result;
  37. }
  38. /**
  39. * mono_bitset_mem_new:
  40. * \param mem The location the bitset is stored
  41. * \param max_size The number of bits you want to hold
  42. * \param flags bitfield of flags
  43. *
  44. * Return \p mem, which is now a initialized bitset of size \p max_size. It is
  45. * not freed even if called with \c mono_bitset_free. \p mem must be at least
  46. * as big as \c mono_bitset_alloc_size returns for the same \p max_size.
  47. */
  48. MonoBitSet *
  49. mono_bitset_mem_new (gpointer mem, guint32 max_size, guint32 flags) {
  50. guint32 real_size = (max_size + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK;
  51. MonoBitSet *result = (MonoBitSet *) mem;
  52. result->size = real_size * BITS_PER_CHUNK;
  53. result->flags = flags | MONO_BITSET_DONT_FREE;
  54. return result;
  55. }
  56. /*
  57. * mono_bitset_free:
  58. * \param set bitset ptr to free
  59. *
  60. * Free bitset unless flags have \c MONO_BITSET_DONT_FREE set. Does not
  61. * free anything if flag \c MONO_BITSET_DONT_FREE is set or bitset was
  62. * made with \c mono_bitset_mem_new.
  63. */
  64. void
  65. mono_bitset_free (MonoBitSet *set) {
  66. if (set && !(set->flags & MONO_BITSET_DONT_FREE))
  67. g_free (set);
  68. }
  69. /**
  70. * mono_bitset_set:
  71. * \param set bitset ptr
  72. * \param pos set bit at this pos
  73. *
  74. * Set bit at \p pos, counting from 0.
  75. */
  76. void
  77. mono_bitset_set (MonoBitSet *set, guint32 pos) {
  78. int j = pos / BITS_PER_CHUNK;
  79. int bit = pos % BITS_PER_CHUNK;
  80. g_assert (pos < set->size);
  81. set->data [j] |= (gsize)1 << bit;
  82. }
  83. /**
  84. * mono_bitset_test:
  85. * \param set bitset ptr
  86. * \param pos test bit at this pos
  87. * Test bit at \p pos, counting from 0.
  88. * \returns a nonzero value if set, 0 otherwise.
  89. */
  90. int
  91. mono_bitset_test (const MonoBitSet *set, guint32 pos) {
  92. int j = pos / BITS_PER_CHUNK;
  93. int bit = pos % BITS_PER_CHUNK;
  94. g_return_val_if_fail (pos < set->size, 0);
  95. return (set->data [j] & ((gsize)1 << bit)) > 0;
  96. }
  97. /**
  98. * mono_bitset_test_bulk:
  99. * \param set bitset ptr
  100. * \param pos test bit at this pos
  101. * \returns 32/64 bits from the bitset, starting from \p pos, which must be
  102. * divisible with 32/64.
  103. */
  104. gsize
  105. mono_bitset_test_bulk (const MonoBitSet *set, guint32 pos) {
  106. int j = pos / BITS_PER_CHUNK;
  107. if (pos >= set->size)
  108. return 0;
  109. else
  110. return set->data [j];
  111. }
  112. /**
  113. * mono_bitset_clear:
  114. * \param set bitset ptr
  115. * \param pos unset bit at this pos
  116. *
  117. * Unset bit at \p pos, counting from 0.
  118. */
  119. void
  120. mono_bitset_clear (MonoBitSet *set, guint32 pos) {
  121. int j = pos / BITS_PER_CHUNK;
  122. int bit = pos % BITS_PER_CHUNK;
  123. g_assert (pos < set->size);
  124. set->data [j] &= ~((gsize)1 << bit);
  125. }
  126. /**
  127. * mono_bitset_clear_all:
  128. * \param set bitset ptr
  129. *
  130. * Unset all bits.
  131. */
  132. void
  133. mono_bitset_clear_all (MonoBitSet *set) {
  134. memset (set->data, 0, set->size / 8);
  135. }
  136. /**
  137. * mono_bitset_set_all:
  138. * \param set bitset ptr
  139. *
  140. * Set all bits.
  141. */
  142. void
  143. mono_bitset_set_all (MonoBitSet *set) {
  144. memset (set->data, -1, set->size / 8);
  145. }
  146. /**
  147. * mono_bitset_invert:
  148. * \param set bitset ptr
  149. *
  150. * Flip all bits.
  151. */
  152. void
  153. mono_bitset_invert (MonoBitSet *set) {
  154. int i;
  155. for (i = 0; i < set->size / BITS_PER_CHUNK; ++i)
  156. set->data [i] = ~set->data [i];
  157. }
  158. /**
  159. * mono_bitset_size:
  160. * \param set bitset ptr
  161. * \returns the number of bits this bitset can hold.
  162. */
  163. guint32
  164. mono_bitset_size (const MonoBitSet *set) {
  165. return set->size;
  166. }
  167. /*
  168. * should test wich version is faster.
  169. */
  170. #if 1
  171. /**
  172. * mono_bitset_count:
  173. * \param set bitset ptr
  174. * \returns number of bits that are set.
  175. */
  176. guint32
  177. mono_bitset_count (const MonoBitSet *set)
  178. {
  179. guint32 i, count;
  180. gsize d;
  181. count = 0;
  182. for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
  183. d = set->data [i];
  184. #if defined (__GNUC__) && !defined (HOST_WIN32)
  185. // The builtins do work on Win32, but can cause a not worthwhile runtime dependency.
  186. // See https://github.com/mono/mono/pull/14248.
  187. if (sizeof (gsize) == sizeof (unsigned int))
  188. count += __builtin_popcount (d);
  189. else
  190. count += __builtin_popcountll (d);
  191. #else
  192. while (d) {
  193. count ++;
  194. d &= (d - 1);
  195. }
  196. #endif
  197. }
  198. return count;
  199. }
  200. #else
  201. guint32
  202. mono_bitset_count (const MonoBitSet *set) {
  203. static const guint32 table [] = {
  204. 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF
  205. };
  206. guint32 i, count, val;
  207. count = 0;
  208. for (i = 0; i < set->size / BITS_PER_CHUNK;+i) {
  209. if (set->data [i]) {
  210. val = set->data [i];
  211. val = (val & table [0]) ((val >> 1) & table [0]);
  212. val = (val & table [1]) ((val >> 2) & table [1]);
  213. val = (val & table [2]) ((val >> 4) & table [2]);
  214. val = (val & table [3]) ((val >> 8) & table [3]);
  215. val = (val & table [4]) ((val >> 16) & table [4]);
  216. count += val;
  217. }
  218. }
  219. return count;
  220. }
  221. #endif
  222. #if 0
  223. const static int
  224. bitstart_mask [] = {
  225. 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
  226. 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
  227. 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
  228. 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
  229. 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
  230. 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
  231. 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
  232. 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
  233. 0x00000000
  234. };
  235. #define my_g_bit_nth_lsf(m,n) (ffs((m) & bitstart_mask [(n)+1])-1)
  236. #define my_g_bit_nth_lsf_nomask(m) (ffs((m))-1)
  237. #else
  238. static gint
  239. my_g_bit_nth_lsf (gsize mask, gint nth_bit)
  240. {
  241. nth_bit ++;
  242. mask >>= nth_bit;
  243. if ((mask == 0) || (nth_bit == BITS_PER_CHUNK))
  244. return -1;
  245. #if (defined(__i386__) && defined(__GNUC__))
  246. {
  247. int r;
  248. /* This depends on mask != 0 */
  249. __asm__("bsfl %1,%0\n\t"
  250. : "=r" (r) : "g" (mask));
  251. return nth_bit + r;
  252. }
  253. #elif defined(__x86_64) && defined(__GNUC__)
  254. {
  255. guint64 r;
  256. __asm__("bsfq %1,%0\n\t"
  257. : "=r" (r) : "rm" (mask));
  258. return nth_bit + r;
  259. }
  260. #else
  261. while (! (mask & 0x1)) {
  262. mask >>= 1;
  263. nth_bit ++;
  264. }
  265. return nth_bit;
  266. #endif
  267. }
  268. static gint
  269. my_g_bit_nth_lsf_nomask (gsize mask)
  270. {
  271. /* Mask is expected to be != 0 */
  272. #if (defined(__i386__) && defined(__GNUC__))
  273. int r;
  274. __asm__("bsfl %1,%0\n\t"
  275. : "=r" (r) : "rm" (mask));
  276. return r;
  277. #elif defined(__x86_64) && defined(__GNUC__)
  278. guint64 r;
  279. __asm__("bsfq %1,%0\n\t"
  280. : "=r" (r) : "rm" (mask));
  281. return r;
  282. #else
  283. int nth_bit = 0;
  284. while (! (mask & 0x1)) {
  285. mask >>= 1;
  286. nth_bit ++;
  287. }
  288. return nth_bit;
  289. #endif
  290. }
  291. #endif
  292. static int
  293. my_g_bit_nth_msf (gsize mask,
  294. gint nth_bit)
  295. {
  296. int i;
  297. if (nth_bit == 0)
  298. return -1;
  299. mask <<= BITS_PER_CHUNK - nth_bit;
  300. i = BITS_PER_CHUNK;
  301. while ((i > 0) && !(mask >> (BITS_PER_CHUNK - 8))) {
  302. mask <<= 8;
  303. i -= 8;
  304. }
  305. if (mask == 0)
  306. return -1;
  307. do {
  308. i--;
  309. if (mask & ((gsize)1 << (BITS_PER_CHUNK - 1)))
  310. return i - (BITS_PER_CHUNK - nth_bit);
  311. mask <<= 1;
  312. }
  313. while (mask);
  314. return -1;
  315. }
  316. static int
  317. find_first_unset (gsize mask, gint nth_bit)
  318. {
  319. do {
  320. nth_bit++;
  321. if (!(mask & ((gsize)1 << nth_bit))) {
  322. if (nth_bit == BITS_PER_CHUNK)
  323. /* On 64 bit platforms, 1 << 64 == 1 */
  324. return -1;
  325. else
  326. return nth_bit;
  327. }
  328. } while (nth_bit < BITS_PER_CHUNK);
  329. return -1;
  330. }
  331. /**
  332. * mono_bitset_find_start:
  333. * \param set bitset ptr
  334. * Equivalent to <code>mono_bitset_find_first (set, -1)</code> but faster.
  335. */
  336. int
  337. mono_bitset_find_start (const MonoBitSet *set)
  338. {
  339. int i;
  340. for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
  341. if (set->data [i])
  342. return my_g_bit_nth_lsf_nomask (set->data [i]) + i * BITS_PER_CHUNK;
  343. }
  344. return -1;
  345. }
  346. /**
  347. * mono_bitset_find_first:
  348. * \param set bitset ptr
  349. * \param pos pos to search after (not including)
  350. * \returns position of first set bit after \p pos. If \p pos < 0, begin search from
  351. * start. Return \c -1 if no bit set is found.
  352. */
  353. int
  354. mono_bitset_find_first (const MonoBitSet *set, gint pos) {
  355. int j;
  356. int bit;
  357. int result, i;
  358. if (pos < 0) {
  359. j = 0;
  360. bit = -1;
  361. } else {
  362. j = pos / BITS_PER_CHUNK;
  363. bit = pos % BITS_PER_CHUNK;
  364. g_assert (pos < set->size);
  365. }
  366. /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
  367. if (set->data [j]) {
  368. result = my_g_bit_nth_lsf (set->data [j], bit);
  369. if (result != -1)
  370. return result + j * BITS_PER_CHUNK;
  371. }
  372. for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
  373. if (set->data [i])
  374. return my_g_bit_nth_lsf (set->data [i], -1) + i * BITS_PER_CHUNK;
  375. }
  376. return -1;
  377. }
  378. /**
  379. * mono_bitset_find_last:
  380. * \param set bitset ptr
  381. * \param pos pos to search before (not including)
  382. * \returns position of last set bit before \p pos. If \p pos < 0 search is
  383. * started from the end. Returns \c -1 if no set bit is found.
  384. */
  385. int
  386. mono_bitset_find_last (const MonoBitSet *set, gint pos) {
  387. int j, bit, result, i;
  388. if (pos < 0)
  389. pos = set->size - 1;
  390. j = pos / BITS_PER_CHUNK;
  391. bit = pos % BITS_PER_CHUNK;
  392. g_return_val_if_fail (pos < set->size, -1);
  393. if (set->data [j]) {
  394. result = my_g_bit_nth_msf (set->data [j], bit);
  395. if (result != -1)
  396. return result + j * BITS_PER_CHUNK;
  397. }
  398. for (i = --j; i >= 0; --i) {
  399. if (set->data [i])
  400. return my_g_bit_nth_msf (set->data [i], BITS_PER_CHUNK) + i * BITS_PER_CHUNK;
  401. }
  402. return -1;
  403. }
  404. /**
  405. * mono_bitset_find_first_unset:
  406. * \param set bitset ptr
  407. * \param pos pos to search after (not including)
  408. * \returns position of first unset bit after \p pos. If \p pos < 0 begin search from
  409. * start. Return \c -1 if no bit set is found.
  410. */
  411. int
  412. mono_bitset_find_first_unset (const MonoBitSet *set, gint pos) {
  413. int j;
  414. int bit;
  415. int result, i;
  416. if (pos < 0) {
  417. j = 0;
  418. bit = -1;
  419. } else {
  420. j = pos / BITS_PER_CHUNK;
  421. bit = pos % BITS_PER_CHUNK;
  422. g_return_val_if_fail (pos < set->size, -1);
  423. }
  424. /*g_print ("find first from %d (j: %d, bit: %d)\n", pos, j, bit);*/
  425. if (set->data [j] != -1) {
  426. result = find_first_unset (set->data [j], bit);
  427. if (result != -1)
  428. return result + j * BITS_PER_CHUNK;
  429. }
  430. for (i = ++j; i < set->size / BITS_PER_CHUNK; ++i) {
  431. if (set->data [i] != -1) {
  432. return find_first_unset (set->data [i], -1) + i * BITS_PER_CHUNK;
  433. }
  434. }
  435. return -1;
  436. }
  437. /**
  438. * mono_bitset_clone:
  439. * \param set bitset ptr to clone
  440. * \param new_size number of bits the cloned bitset can hold
  441. * \returns a cloned bitset of size \p new_size. \c MONO_BITSET_DONT_FREE
  442. * unset in cloned bitset. If \p new_size is 0, the cloned object is just
  443. * as big.
  444. */
  445. MonoBitSet*
  446. mono_bitset_clone (const MonoBitSet *set, guint32 new_size) {
  447. MonoBitSet *result;
  448. if (!new_size)
  449. new_size = set->size;
  450. result = mono_bitset_new (new_size, set->flags);
  451. result->flags &= ~MONO_BITSET_DONT_FREE;
  452. memcpy (result->data, set->data, set->size / 8);
  453. return result;
  454. }
  455. /**
  456. * mono_bitset_copyto:
  457. * \param src bitset ptr to copy from
  458. * \param dest bitset ptr to copy to
  459. *
  460. * Copy one bitset to another.
  461. */
  462. void
  463. mono_bitset_copyto (const MonoBitSet *src, MonoBitSet *dest) {
  464. g_assert (dest->size <= src->size);
  465. memcpy (&dest->data, &src->data, dest->size / 8);
  466. }
  467. /**
  468. * mono_bitset_union:
  469. * \param dest bitset ptr to hold union
  470. * \param src bitset ptr to copy
  471. *
  472. * Make union of one bitset and another.
  473. */
  474. void
  475. mono_bitset_union (MonoBitSet *dest, const MonoBitSet *src) {
  476. int i, size;
  477. g_assert (src->size <= dest->size);
  478. size = dest->size / BITS_PER_CHUNK;
  479. for (i = 0; i < size; ++i)
  480. dest->data [i] |= src->data [i];
  481. }
  482. /**
  483. * mono_bitset_intersection:
  484. * \param dest bitset ptr to hold intersection
  485. * \param src bitset ptr to copy
  486. *
  487. * Make intersection of one bitset and another.
  488. */
  489. void
  490. mono_bitset_intersection (MonoBitSet *dest, const MonoBitSet *src) {
  491. int i, size;
  492. g_assert (src->size <= dest->size);
  493. size = dest->size / BITS_PER_CHUNK;
  494. for (i = 0; i < size; ++i)
  495. dest->data [i] &= src->data [i];
  496. }
  497. /**
  498. * mono_bitset_intersection_2:
  499. * \param dest bitset ptr to hold intersection
  500. * \param src1 first bitset
  501. * \param src2 second bitset
  502. *
  503. * Make intersection of two bitsets
  504. */
  505. void
  506. mono_bitset_intersection_2 (MonoBitSet *dest, const MonoBitSet *src1, const MonoBitSet *src2) {
  507. int i, size;
  508. g_assert (src1->size <= dest->size);
  509. g_assert (src2->size <= dest->size);
  510. size = dest->size / BITS_PER_CHUNK;
  511. for (i = 0; i < size; ++i)
  512. dest->data [i] = src1->data [i] & src2->data [i];
  513. }
  514. /**
  515. * mono_bitset_sub:
  516. * \param dest bitset ptr to hold bitset - src
  517. * \param src bitset ptr to copy
  518. *
  519. * Unset all bits in \p dest that are set in \p src.
  520. */
  521. void
  522. mono_bitset_sub (MonoBitSet *dest, const MonoBitSet *src) {
  523. int i, size;
  524. g_assert (src->size <= dest->size);
  525. size = src->size / BITS_PER_CHUNK;
  526. for (i = 0; i < size; ++i)
  527. dest->data [i] &= ~src->data [i];
  528. }
  529. /**
  530. * mono_bitset_equal:
  531. * \param src bitset ptr
  532. * \param src1 bitset ptr
  533. * \returns TRUE if their size are the same and the same bits are set in
  534. * both bitsets.
  535. */
  536. gboolean
  537. mono_bitset_equal (const MonoBitSet *src, const MonoBitSet *src1) {
  538. int i;
  539. if (src->size != src1->size)
  540. return FALSE;
  541. for (i = 0; i < src->size / BITS_PER_CHUNK; ++i)
  542. if (src->data [i] != src1->data [i])
  543. return FALSE;
  544. return TRUE;
  545. }
  546. /**
  547. * mono_bitset_foreach:
  548. * \param set bitset ptr
  549. * \param func Function to call for every set bit
  550. * \param data pass this as second arg to func
  551. * Calls \p func for every bit set in bitset. Argument 1 is the number of
  552. * the bit set, argument 2 is data
  553. */
  554. void
  555. mono_bitset_foreach (MonoBitSet *set, MonoBitSetFunc func, gpointer data)
  556. {
  557. int i, j;
  558. for (i = 0; i < set->size / BITS_PER_CHUNK; ++i) {
  559. if (set->data [i]) {
  560. for (j = 0; j < BITS_PER_CHUNK; ++j)
  561. if (set->data [i] & ((gsize)1 << j))
  562. func (j + i * BITS_PER_CHUNK, data);
  563. }
  564. }
  565. }
  566. gboolean
  567. mono_bitset_test_safe (const MonoBitSet *set, guint32 pos)
  568. {
  569. return set && set->size > pos && mono_bitset_test (set, pos);
  570. }
  571. #ifdef TEST_BITSET
  572. /*
  573. * Compile with:
  574. * gcc -g -Wall -DTEST_BITSET -o monobitset monobitset.c `pkg-config --cflags --libs glib-2.0`
  575. */
  576. int
  577. main() {
  578. MonoBitSet *set1, *set2, *set3, *set4;
  579. int error = 1;
  580. int count, i;
  581. set1 = mono_bitset_new (60, 0);
  582. set4 = mono_bitset_new (60, 0);
  583. if (mono_bitset_count (set1) != 0)
  584. return error;
  585. error++;
  586. mono_bitset_set (set1, 33);
  587. if (mono_bitset_count (set1) != 1)
  588. return error;
  589. error++;
  590. /* g_print("should be 33: %d\n", mono_bitset_find_first (set1, 0)); */
  591. if (mono_bitset_find_first (set1, 0) != 33)
  592. return error;
  593. error++;
  594. if (mono_bitset_find_first (set1, 33) != -1)
  595. return error;
  596. error++;
  597. /* test 5 */
  598. if (mono_bitset_find_first (set1, -100) != 33)
  599. return error;
  600. error++;
  601. if (mono_bitset_find_last (set1, -1) != 33)
  602. return error;
  603. error++;
  604. if (mono_bitset_find_last (set1, 33) != -1)
  605. return error;
  606. error++;
  607. if (mono_bitset_find_last (set1, -100) != 33)
  608. return error;
  609. error++;
  610. if (mono_bitset_find_last (set1, 34) != 33)
  611. return error;
  612. error++;
  613. /* test 10 */
  614. if (!mono_bitset_test (set1, 33))
  615. return error;
  616. error++;
  617. if (mono_bitset_test (set1, 32) || mono_bitset_test (set1, 34))
  618. return error;
  619. error++;
  620. set2 = mono_bitset_clone (set1, 0);
  621. if (mono_bitset_count (set2) != 1)
  622. return error;
  623. error++;
  624. mono_bitset_invert (set2);
  625. if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 1))
  626. return error;
  627. error++;
  628. mono_bitset_clear (set2, 10);
  629. if (mono_bitset_count (set2) != (mono_bitset_size (set2) - 2))
  630. return error;
  631. error++;
  632. /* test 15 */
  633. set3 = mono_bitset_clone (set2, 0);
  634. mono_bitset_union (set3, set1);
  635. if (mono_bitset_count (set3) != (mono_bitset_size (set3) - 1))
  636. return error;
  637. error++;
  638. mono_bitset_clear_all (set2);
  639. if (mono_bitset_count (set2) != 0)
  640. return error;
  641. error++;
  642. mono_bitset_invert (set2);
  643. if (mono_bitset_count (set2) != mono_bitset_size (set2))
  644. return error;
  645. error++;
  646. mono_bitset_set (set4, 0);
  647. mono_bitset_set (set4, 1);
  648. mono_bitset_set (set4, 10);
  649. if (mono_bitset_count (set4) != 3)
  650. return error;
  651. error++;
  652. count = 0;
  653. for (i = mono_bitset_find_first (set4, -1); i != -1; i = mono_bitset_find_first (set4, i)) {
  654. count ++;
  655. switch (count) {
  656. case 1:
  657. if (i != 0)
  658. return error;
  659. break;
  660. case 2:
  661. if (i != 1)
  662. return error;
  663. break;
  664. case 3:
  665. if (i != 10)
  666. return error;
  667. break;
  668. }
  669. /* g_print ("count got: %d at %d\n", count, i); */
  670. }
  671. if (count != 3)
  672. return error;
  673. error++;
  674. if (mono_bitset_find_first (set4, -1) != 0)
  675. return error;
  676. error++;
  677. /* 20 */
  678. mono_bitset_set (set4, 31);
  679. if (mono_bitset_find_first (set4, 10) != 31)
  680. return error;
  681. error++;
  682. mono_bitset_free (set1);
  683. set1 = mono_bitset_new (200, 0);
  684. mono_bitset_set (set1, 0);
  685. mono_bitset_set (set1, 1);
  686. mono_bitset_set (set1, 10);
  687. mono_bitset_set (set1, 31);
  688. mono_bitset_set (set1, 150);
  689. mono_bitset_free (set1);
  690. mono_bitset_free (set2);
  691. mono_bitset_free (set3);
  692. mono_bitset_free (set4);
  693. g_print ("total tests passed: %d\n", error - 1);
  694. return 0;
  695. }
  696. #endif