more rank() tests; found/fixed bug
This commit is contained in:
parent
845523c807
commit
26bb560eb7
4 changed files with 70 additions and 8 deletions
|
@ -44,6 +44,7 @@
|
||||||
pkg-config
|
pkg-config
|
||||||
python3
|
python3
|
||||||
ripgrep
|
ripgrep
|
||||||
|
valgrind
|
||||||
];
|
];
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
libbacktrace
|
libbacktrace
|
||||||
|
|
|
@ -499,10 +499,11 @@ __sm_chunk_map_rank(__sm_chunk_t *map, size_t first, size_t last, size_t *after)
|
||||||
*after = 0;
|
*after = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t k = ks; k < last && k < sizeof(sm_bitvec_t); k++) {
|
uint64_t mask = ((uint64_t)1 << (last + 1)) - 1 - (((uint64_t)1 << ks) - 1);
|
||||||
if (w & ((sm_bitvec_t)1 << k)) {
|
uint64_t masked = w & mask;
|
||||||
ret++;
|
while (masked) {
|
||||||
}
|
ret += masked & 1;
|
||||||
|
masked >>= 1;
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,3 +264,30 @@ bitmap_from_uint64(sparsemap_t *map, uint64_t number) {
|
||||||
sparsemap_set(map, i, bit);
|
sparsemap_set(map, i, bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
rank_uint64(uint64_t number, int n, int p)
|
||||||
|
{
|
||||||
|
if (p < n || p > 63) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a mask for the range between n and p.
|
||||||
|
This works by shifting 1 to the left (p+1) times, subtracting 1 to have
|
||||||
|
a sequence of p 1's, then shifting n times to the left to position it
|
||||||
|
starting at n. Finally, subtracting (1 << n) - 1 removes the bits below
|
||||||
|
n from the mask. */
|
||||||
|
uint64_t mask = ((uint64_t)1 << (p + 1)) - 1 - (((uint64_t)1 << n) - 1);
|
||||||
|
|
||||||
|
/* Apply the mask and count the set bits in the result. */
|
||||||
|
uint64_t maskedNumber = number & mask;
|
||||||
|
|
||||||
|
/* Count the bits set in maskedNumber. */
|
||||||
|
uint32_t count = 0;
|
||||||
|
while (maskedNumber) {
|
||||||
|
count += maskedNumber & 1;
|
||||||
|
maskedNumber >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
41
tests/test.c
41
tests/test.c
|
@ -439,7 +439,7 @@ test_api_select_setup(const MunitParameter params[], void *user_data)
|
||||||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||||
|
|
||||||
sparsemap_init(map, buf, 1024, 0);
|
sparsemap_init(map, buf, 1024, 0);
|
||||||
populate_map(map, 1024, 3 * 1024);
|
bitmap_from_uint64(map, ((uint64_t)0xfeedface << 32) | 0xbadc0ffee);
|
||||||
|
|
||||||
return (void *)map;
|
return (void *)map;
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,11 @@ test_api_select(const MunitParameter params[], void *data)
|
||||||
|
|
||||||
assert_ptr_not_null(map);
|
assert_ptr_not_null(map);
|
||||||
|
|
||||||
size_t size = sparsemap_select(map, 1);
|
/* NOTE: select() is 0-based, to get the bit position of the 1st logical bit set
|
||||||
|
call select(map, 0), to get the 18th, select(map, 17), etc. */
|
||||||
|
assert_true(sparsemap_select(map, 0) == 1);
|
||||||
|
assert_true(sparsemap_select(map, 4) == 6);
|
||||||
|
assert_true(sparsemap_select(map, 17) == 26);
|
||||||
|
|
||||||
return MUNIT_OK;
|
return MUNIT_OK;
|
||||||
}
|
}
|
||||||
|
@ -470,7 +474,6 @@ test_api_rank_setup(const MunitParameter params[], void *user_data)
|
||||||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||||
|
|
||||||
sparsemap_init(map, buf, 1024, 0);
|
sparsemap_init(map, buf, 1024, 0);
|
||||||
populate_map(map, 1024, 3 * 1024);
|
|
||||||
|
|
||||||
return (void *)map;
|
return (void *)map;
|
||||||
}
|
}
|
||||||
|
@ -484,12 +487,42 @@ test_api_rank_tear_down(void *fixture)
|
||||||
static MunitResult
|
static MunitResult
|
||||||
test_api_rank(const MunitParameter params[], void *data)
|
test_api_rank(const MunitParameter params[], void *data)
|
||||||
{
|
{
|
||||||
|
int rank;
|
||||||
sparsemap_t *map = (sparsemap_t *)data;
|
sparsemap_t *map = (sparsemap_t *)data;
|
||||||
(void)params;
|
(void)params;
|
||||||
|
|
||||||
assert_ptr_not_null(map);
|
assert_ptr_not_null(map);
|
||||||
|
|
||||||
size_t size = sparsemap_rank(map, 0, 1);
|
for (int i = 0; i < 10; i++) {
|
||||||
|
sparsemap_set(map, i, true);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assert_true(sparsemap_is_set(map, i));
|
||||||
|
}
|
||||||
|
for (int i = 10; i < 1000; i++) {
|
||||||
|
assert_true(!sparsemap_is_set(map, i));
|
||||||
|
}
|
||||||
|
/* rank() is also 0-based, for consistency (and confusion sake); consider the
|
||||||
|
range as [start, end] of [0, 9] counts the bits set in the first 10
|
||||||
|
positions (starting from the LSB) in the index. */
|
||||||
|
int r1 = sparsemap_rank(map, 0, 9);
|
||||||
|
int r2 = rank_uint64((uint64_t)-1, 0, 9);
|
||||||
|
assert_true(r1 == r2);
|
||||||
|
assert_true(sparsemap_rank(map, 0, 9) == 10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
for (int j = i; j < 10; j++) {
|
||||||
|
r1 = sparsemap_rank(map, i, j);
|
||||||
|
r2 = rank_uint64((uint64_t)-1, i, j);
|
||||||
|
assert_true(r1 == r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sparsemap_clear(map);
|
||||||
|
uint64_t bits = ((uint64_t)0xfeedface << 32) | 0xbadc0ffee;
|
||||||
|
bitmap_from_uint64(map, bits);
|
||||||
|
rank = sparsemap_rank(map, 3, 18);
|
||||||
|
assert_true(rank == rank_uint64(bits, 3, 18));
|
||||||
|
|
||||||
return MUNIT_OK;
|
return MUNIT_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue