/* * call-seq: * bv.next_unset -> bit_num * * Returns the next unset bit in the bit-vector scanning from low order to * high order. This method should only be called on bit-vectors which have * been flipped (negated). You should call +#reset_scan+ before * calling this method if you want to scan from the beginning. It is * automatically reset when you first create the bit-vector. */ VALUE frt_bv_next_unset(VALUE self) { BitVector *bv; GET_BV(bv, self); return INT2FIX(bv_scan_next_unset(bv)); }
/** * Test simple BitVector scanning */ static void test_bv_scan(TestCase *tc, void *data) { int i; BitVector *bv = bv_new(); BitVector *not_bv; (void)data; /* suppress unused argument warning */ for (i = 6; i <= 10; i++) { bv_set(bv, i); } not_bv = bv_not(bv); for (i = 6; i <= 10; i++) { Aiequal(i, bv_scan_next(bv)); Aiequal(i, bv_scan_next_unset(not_bv)); } Aiequal(-1, bv_scan_next(bv)); Aiequal(-1, bv_scan_next_unset(bv)); bv_destroy(bv); bv_destroy(not_bv); }
/* * call-seq: * bv.each { |bit_num| } * * Iterate through all the set bits in the bit-vector yeilding each one in * order */ VALUE frt_bv_each(VALUE self) { BitVector *bv; int bit; GET_BV(bv, self); bv_scan_reset(bv); if (bv->extends_as_ones) { while ((bit = bv_scan_next_unset(bv)) >= 0) { rb_yield(INT2FIX(bit)); } } else { while ((bit = bv_scan_next(bv)) >= 0) { rb_yield(INT2FIX(bit)); } } return self; }
/* * call-seq: * bv.to_a * * Iterate through all the set bits in the bit-vector adding the index of * each set bit to an array. This is useful if you want to perform array * methods on the bit-vecter. If you want to convert an array to a bit_vector * simply do this; * * bv = [1, 12, 45, 367, 455].inject(BitVector.new) {|bv, i| bv.set(i)} */ VALUE frt_bv_to_a(VALUE self) { BitVector *bv; int bit; VALUE ary; GET_BV(bv, self); ary = rb_ary_new(); bv_scan_reset(bv); if (bv->extends_as_ones) { while ((bit = bv_scan_next_unset(bv)) >= 0) { rb_ary_push(ary, INT2FIX(bit)); } } else { while ((bit = bv_scan_next(bv)) >= 0) { rb_ary_push(ary, INT2FIX(bit)); } } return ary; }
/** * Stress test BitVector Scanning as well as bv_set_fast. This test has been * run successfully with BV_DENSE_SCAN_SIZE set to 20000000 and BV_SCAN_INC * set to 97. When running this test with high numbers, be sure use -q on the * command line or the test will take a very long time. */ static void test_bv_scan_stress(TestCase *tc, void *data) { int i; BitVector *bv = bv_new_capa(BV_SCAN_SIZE); BitVector *not_bv; (void)data; /* suppress unused argument warning */ for (i = BV_SCAN_INC; i < BV_SCAN_SIZE; i += BV_SCAN_INC) { bv_set_fast(bv, i); Aiequal(bv_get(bv, i), 1); Aiequal(bv_get(bv, i-1), 0); Aiequal(bv_get(bv, i+1), 0); } not_bv = bv_not(bv); for (i = BV_SCAN_INC; i < BV_SCAN_SIZE; i += BV_SCAN_INC) { Aiequal(i, bv_scan_next_from(bv, i - BV_SCAN_INC / 2)); Aiequal(i, bv_scan_next_unset_from(not_bv, i - BV_SCAN_INC / 2)); } Aiequal(-1, bv_scan_next_from(bv, i - BV_SCAN_INC / 2)); Aiequal(-1, bv_scan_next_unset_from(not_bv, i - BV_SCAN_INC / 2)); /* test scan_next_from where size is actually greater than the highest set * bit */ bv_unset(bv, bv->size); bv_set(not_bv, not_bv->size); bv_scan_reset(bv); bv_scan_reset(not_bv); for (i = BV_SCAN_INC; i < BV_SCAN_SIZE; i += BV_SCAN_INC) { Aiequal(i, bv_scan_next_from(bv, i - BV_SCAN_INC / 2)); Aiequal(i, bv_scan_next_unset_from(not_bv, i - BV_SCAN_INC / 2)); } Aiequal(-1, bv_scan_next_from(bv, i - BV_SCAN_INC / 2)); Aiequal(-1, bv_scan_next_unset_from(not_bv, i - BV_SCAN_INC / 2)); bv_scan_reset(bv); bv_scan_reset(not_bv); for (i = BV_SCAN_INC; i < BV_SCAN_SIZE; i += BV_SCAN_INC) { Aiequal(i, bv_scan_next(bv)); Aiequal(i, bv_scan_next_unset(not_bv)); } Aiequal(-1, bv_scan_next(bv)); Aiequal(-1, bv_scan_next_unset(not_bv)); bv_clear(bv); bv_destroy(not_bv); for (i = 0; i < BV_DENSE_SCAN_SIZE; i++) { bv_set(bv, i); } not_bv = bv_not(bv); for (i = 0; i < BV_DENSE_SCAN_SIZE; i++) { Aiequal(i, bv_scan_next_from(bv, i)); Aiequal(i, bv_scan_next_unset_from(not_bv, i)); } Aiequal(-1, bv_scan_next_from(bv, i)); Aiequal(-1, bv_scan_next_unset_from(not_bv, i)); bv_scan_reset(bv); bv_scan_reset(not_bv); for (i = 0; i < BV_DENSE_SCAN_SIZE; i++) { Aiequal(i, bv_scan_next(bv)); Aiequal(i, bv_scan_next_unset(not_bv)); } Aiequal(-1, bv_scan_next(bv)); Aiequal(-1, bv_scan_next_unset(not_bv)); bv_destroy(bv); bv_destroy(not_bv); }