diff --git a/src/sparsemap.c b/src/sparsemap.c index f66df43..a7f44cd 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -429,10 +429,9 @@ __sm_chunk_map_select(__sm_chunk_t *map, size_t n, ssize_t *pnew_n) * Counts the set bits in the range [first, last] inclusive. */ static size_t -__sm_chunk_map_rank(__sm_chunk_t *map, size_t first, size_t last, size_t *after) +__sm_chunk_map_rank(__sm_chunk_t *map, size_t last, size_t *after) { size_t ret = 0; - (void)first; // TODO register uint8_t *p = (uint8_t *)map->m_data; for (size_t i = 0; i < sizeof(sm_bitvec_t); i++, p++) { @@ -480,24 +479,10 @@ __sm_chunk_map_rank(__sm_chunk_t *map, size_t first, size_t last, size_t *after) *after = 0; } } else { - uint64_t mask_l, mask_r, mask; - if (*after > 0) { - if (*after > last) { - *after = *after - last; - /* This gives us 'last' number of ones on the right. */ - mask_r = ((uint64_t)1 << last) - 1; - } else { - /* This gives us '*after' number of ones on the right. */ - mask_r = (((uint64_t)1 << *after) - 1); - *after = 0; - } - /* Used to shift the mask_r block to the left 'last' times. */ - mask_l = ((uint64_t)1 << (last + 1)); - mask = mask_l - 1 - mask_r; - } else { - mask = UINT64_MAX >> (SM_BITS_PER_VECTOR - last - 1); - } - /* Create a mask for the range between *after and last. */ + uint64_t mask; + /* Create a mask for the range between after and last inclusive [*after, last]. */ + mask = ((uint64_t)1 << (last + 1)) - 1 - (((uint64_t)1 << *after) - 1); + *after -= (*after > last) ? last : *after; uint64_t mw = w & mask; ret += popcountll(mw); return (ret); @@ -1207,7 +1192,7 @@ sparsemap_rank(sparsemap_t *map, size_t first, size_t last) __sm_chunk_t chunk; __sm_chunk_map_init(&chunk, p); - result += __sm_chunk_map_rank(&chunk, first - start, last - start, &after); + result += __sm_chunk_map_rank(&chunk, last - start, &after); p += __sm_chunk_map_get_size(&chunk); } return (result); diff --git a/tests/test.c b/tests/test.c index 35df997..f829762 100644 --- a/tests/test.c +++ b/tests/test.c @@ -550,16 +550,16 @@ test_api_rank(const MunitParameter params[], void *data) /* 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. */ - r1 = sparsemap_rank(map, 0, 9); - r2 = rank_uint64((uint64_t)-1, 0, 9); + r1 = rank_uint64((uint64_t)-1, 0, 9); + r2 = sparsemap_rank(map, 0, 9); assert_true(r1 == r2); assert_true(sparsemap_rank(map, 0, 9) == 10); assert_true(sparsemap_rank(map, 1000, 1050) == 0); 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); + r1 = rank_uint64((uint64_t)-1, i, j); + r2 = sparsemap_rank(map, i, j); assert_true(r1 == r2); } } @@ -592,20 +592,29 @@ test_api_span(const MunitParameter params[], void *data) assert_ptr_not_null(map); - int located_at, placed_at, amt = 5000; - for (int i = 1; i < amt; i++) { - for (int j = 1; j < amt / 10; j++) { - sparsemap_clear(map); - placed_at = create_sequential_set_in_empty_map(map, amt, j); -// whats_set(map, amt); - located_at = sparsemap_span(map, 0, j); - assert_true(located_at == placed_at); -//TODO located_at = sparsemap_span(map, (placed_at < j ? 0 : placed_at / 2), i); -// assert_true(placed_at == located_at); + int located_at, placed_at, amt = 5000; + for (int i = 1; i < amt; i++) { + for (int j = 1; j < amt / 10; j++) { + sparsemap_clear(map); + placed_at = create_sequential_set_in_empty_map(map, amt, j); + located_at = sparsemap_span(map, 0, j); + assert_true(located_at == placed_at); + } } - } - return MUNIT_OK; + for (int i = 1; i < amt; i++) { + for (int j = 1; j < amt / 10; j++) { + sparsemap_clear(map); + populate_map(map, 1024, 3 * 1024); + placed_at = create_sequential_set_in_empty_map(map, amt, j); + located_at = sparsemap_span(map, 0, j); + assert_true(located_at <= placed_at); + //TODO located_at = sparsemap_span(map, (placed_at < j ? 0 : placed_at / 2), i); + // assert_true(placed_at == located_at); + } + } + + return MUNIT_OK; } static MunitTest api_test_suite[] = { { (char *)"/api/static_init", test_api_static_init, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },