fixes
This commit is contained in:
parent
6645665d82
commit
20b81983ae
3 changed files with 65 additions and 76 deletions
|
@ -114,7 +114,7 @@ typedef struct {
|
|||
sm_bitvec_t *m_data;
|
||||
} __sm_chunk_t;
|
||||
|
||||
struct sparsemap {
|
||||
struct __attribute__((aligned(8))) sparsemap {
|
||||
uint8_t *m_data; /* The serialized bitmap data */
|
||||
size_t m_capacity; /* The total size of m_data */
|
||||
size_t m_data_used; /* The used size of m_data */
|
||||
|
@ -764,19 +764,13 @@ __sm_append_data(sparsemap_t *map, uint8_t *buffer, size_t buffer_size)
|
|||
/**
|
||||
* Inserts data somewhere in the middle of m_data.
|
||||
*/
|
||||
static int
|
||||
void
|
||||
__sm_insert_data(sparsemap_t *map, size_t offset, uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
if (map->m_data_used + buffer_size > map->m_capacity) {
|
||||
__sm_assert(!"buffer overflow");
|
||||
abort();
|
||||
}
|
||||
|
||||
uint8_t *p = __sm_get_chunk_map_data(map, offset);
|
||||
memmove(p + buffer_size, p, map->m_data_used - offset);
|
||||
memcpy(p, buffer, buffer_size);
|
||||
map->m_data_used += buffer_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -944,6 +938,11 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value)
|
|||
ssize_t offset = __sm_get_chunk_map_offset(map, idx);
|
||||
bool dont_grow = false;
|
||||
|
||||
if (map->m_data_used + sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2 > map->m_capacity) {
|
||||
errno = ENOSPC;
|
||||
return SPARSEMAP_IDX_MAX;
|
||||
}
|
||||
|
||||
/* If there is no __sm_chunk_t and the bit is set to zero then return
|
||||
immediately; otherwise create an initial __sm_chunk_t. */
|
||||
if (offset == -1) {
|
||||
|
@ -959,8 +958,8 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value)
|
|||
|
||||
__sm_set_chunk_map_count(map, 1);
|
||||
|
||||
/* We already inserted an additional sm_bitvec_t; later on there
|
||||
is no need to grow the vector even further. */
|
||||
/* We already inserted an additional sm_bitvec_t; given that has happened
|
||||
there is no need to grow the vector even further. */
|
||||
dont_grow = true;
|
||||
offset = 0;
|
||||
}
|
||||
|
@ -1044,8 +1043,10 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value)
|
|||
offset += (ssize_t)(sizeof(sm_idx_t) + position * sizeof(sm_bitvec_t));
|
||||
__sm_insert_data(map, offset, (uint8_t *)&fill, sizeof(sm_bitvec_t));
|
||||
}
|
||||
code = __sm_chunk_map_set(&chunk, idx - start, value, &position, &fill, true);
|
||||
__sm_assert(code == SM_OK);
|
||||
__sm_when_diag({
|
||||
code = __sm_chunk_map_set(&chunk, idx - start, value, &position, &fill, true);
|
||||
__sm_assert(code == SM_OK);
|
||||
});
|
||||
break;
|
||||
case SM_NEEDS_TO_SHRINK:
|
||||
/* If the __sm_chunk_t is empty then remove it. */
|
||||
|
@ -1259,12 +1260,9 @@ sparsemap_select(sparsemap_t *map, sparsemap_idx_t n, bool value)
|
|||
|
||||
p += __sm_chunk_map_get_size(&chunk);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
assert(!"shouldn't be here");
|
||||
#endif
|
||||
return SPARSEMAP_IDX_MAX;
|
||||
return SPARSEMAP_IDX_MAX; // TODO... shouldn't be here?
|
||||
} else {
|
||||
return SPARSEMAP_IDX_MIN; // TODO... sparsemap_select(map, -n, value);
|
||||
return SPARSEMAP_IDX_MIN; // TODO... sparsemap_select(map, -n, value); seek from end, not start
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ has_sequential_set(int a[], int l, int r)
|
|||
int
|
||||
ensure_sequential_set(int a[], int l, int r)
|
||||
{
|
||||
if (!a || l == 0 || r < 1 || r > l) {
|
||||
if (!a || l == 0 || r < 1 || r > l - 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
107
tests/test.c
107
tests/test.c
|
@ -314,20 +314,23 @@ test_api_remaining_capacity(const MunitParameter params[], void *data)
|
|||
do {
|
||||
sparsemap_set(map, i++, true);
|
||||
cap = sparsemap_capacity_remaining(map);
|
||||
} while (cap > 1.0);
|
||||
// assert_true(i == 169985); when seed is 8675309
|
||||
assert_true(cap <= 1.0);
|
||||
} while (cap > 1.0 && errno != ENOSPC);
|
||||
errno = 0;
|
||||
assert_true(cap <= 2.0);
|
||||
|
||||
sparsemap_clear(map);
|
||||
cap = sparsemap_capacity_remaining(map);
|
||||
assert_true(cap > 99);
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
int p = munit_rand_int_range(0, 150000);
|
||||
sparsemap_set(map, p, true);
|
||||
i++;
|
||||
cap = sparsemap_capacity_remaining(map);
|
||||
} while (cap > 2.0);
|
||||
// assert_true(i == 64); when seed is 8675309
|
||||
assert_true(cap <= 2.0);
|
||||
} while (cap > 1.0 && errno != ENOSPC);
|
||||
errno = 0;
|
||||
assert_true(cap <= 1.0);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
@ -873,33 +876,32 @@ static MunitTest api_test_suite[] = {
|
|||
static void *
|
||||
test_scale_lots_o_spans_setup(const MunitParameter params[], void *user_data)
|
||||
{
|
||||
uint8_t *buf = munit_calloc(10 * 1024, sizeof(uint8_t));
|
||||
assert_ptr_not_null(buf);
|
||||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||
|
||||
sparsemap_init(map, buf, 10 * 1024);
|
||||
|
||||
(void)params;
|
||||
(void)user_data;
|
||||
sparsemap_t *map = sparsemap(10 * 1024);
|
||||
assert_ptr_not_null(map);
|
||||
return (void *)map;
|
||||
}
|
||||
static void
|
||||
test_scale_lots_o_spans_tear_down(void *fixture)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)fixture;
|
||||
assert_ptr_not_null(map->m_data);
|
||||
munit_free(map->m_data);
|
||||
test_api_tear_down(fixture);
|
||||
assert_ptr_not_null(map);
|
||||
munit_free(map);
|
||||
}
|
||||
static MunitResult
|
||||
test_scale_lots_o_spans(const MunitParameter params[], void *data)
|
||||
{
|
||||
size_t amt = 897915; // 268435456
|
||||
sparsemap_t *map = (sparsemap_t *)data;
|
||||
(void)params;
|
||||
|
||||
assert_ptr_not_null(map);
|
||||
|
||||
for (int i = 0; i < 268435456;) {
|
||||
for (size_t i = 0; i < amt;) {
|
||||
int l = i % 31 + 16;
|
||||
sm_add_span(map, 268435456, l);
|
||||
// TODO: sm_add_span(map, amt, l);
|
||||
sm_add_span(map, 10000, l);
|
||||
if (errno == ENOSPC) {
|
||||
map = sparsemap_set_data_size(map, sparsemap_get_capacity(map) * 2);
|
||||
errno = 0;
|
||||
|
@ -908,7 +910,6 @@ test_scale_lots_o_spans(const MunitParameter params[], void *data)
|
|||
/* ANSI esc code to clear line, carrage return, then print on the same line */
|
||||
// printf("\033[2K\r%d", i);
|
||||
// printf("%d\t%d\n", l, i);
|
||||
// fflush(stdout);
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
|
@ -917,21 +918,18 @@ test_scale_lots_o_spans(const MunitParameter params[], void *data)
|
|||
static void *
|
||||
test_scale_ondrej_setup(const MunitParameter params[], void *user_data)
|
||||
{
|
||||
uint8_t *buf = munit_calloc(1024, sizeof(uint8_t));
|
||||
assert_ptr_not_null(buf);
|
||||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||
|
||||
sparsemap_init(map, buf, 1024);
|
||||
|
||||
(void)params;
|
||||
(void)user_data;
|
||||
sparsemap_t *map = sparsemap(10 * 1024);
|
||||
assert_ptr_not_null(map);
|
||||
return (void *)map;
|
||||
}
|
||||
static void
|
||||
test_scale_ondrej_tear_down(void *fixture)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)fixture;
|
||||
assert_ptr_not_null(map->m_data);
|
||||
munit_free(map->m_data);
|
||||
test_api_tear_down(fixture);
|
||||
assert_ptr_not_null(map);
|
||||
munit_free(map);
|
||||
}
|
||||
static MunitResult
|
||||
test_scale_ondrej(const MunitParameter params[], void *data)
|
||||
|
@ -948,59 +946,49 @@ test_scale_ondrej(const MunitParameter params[], void *data)
|
|||
for (sparsemap_idx_t j = 0; j < stride; j++) {
|
||||
bool set = (i != needle) ? (j < 10) : (j < 9);
|
||||
sparsemap_set(map, i, set);
|
||||
if (errno == ENOSPC) {
|
||||
map = sparsemap_set_data_size(map, sparsemap_get_capacity(map) * 2);
|
||||
errno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// sm_add_span(map, 268435456, 9);
|
||||
|
||||
size_t b = sparsemap_span(map, 0, 8, true);
|
||||
if (SPARSEMAP_NOT_FOUND(b)) {
|
||||
printf("%ld\n", b);
|
||||
printf("%ld / %ld == %ld %ld\n", b, stride, b / stride, needle);
|
||||
} else {
|
||||
printf("not found\n");
|
||||
}
|
||||
/*
|
||||
size_t b = sparsemap_span(map, 0, 9, false); TODO
|
||||
printf("%ld (%d) / %d == %d", b, (int)b, stride, needle);
|
||||
fflush(stdout);
|
||||
assert_true(((int)b / stride) == needle);
|
||||
*/
|
||||
#endif
|
||||
sparsemap_idx_t a = sparsemap_span(map, 0, 9, false);
|
||||
assert_true((a / stride) == needle);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static void *
|
||||
test_scale_spans_come_spans_go_setup(const MunitParameter params[], void *user_data)
|
||||
{
|
||||
uint8_t *buf = munit_calloc(1024, sizeof(uint8_t));
|
||||
assert_ptr_not_null(buf);
|
||||
sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data);
|
||||
|
||||
sparsemap_init(map, buf, 1024);
|
||||
|
||||
(void)params;
|
||||
(void)user_data;
|
||||
sparsemap_t *map = sparsemap(10 * 1024);
|
||||
assert_ptr_not_null(map);
|
||||
return (void *)map;
|
||||
}
|
||||
static void
|
||||
test_scale_spans_come_spans_go_tear_down(void *fixture)
|
||||
{
|
||||
sparsemap_t *map = (sparsemap_t *)fixture;
|
||||
assert_ptr_not_null(map->m_data);
|
||||
munit_free(map->m_data);
|
||||
test_api_tear_down(fixture);
|
||||
assert_ptr_not_null(map);
|
||||
munit_free(map);
|
||||
}
|
||||
static MunitResult
|
||||
test_scale_spans_come_spans_go(const MunitParameter params[], void *data)
|
||||
{
|
||||
size_t amt = 897915; // 268435456, ~5e7 interations due to 2e9 / avg(l)
|
||||
sparsemap_t *map = (sparsemap_t *)data;
|
||||
(void)params;
|
||||
|
||||
assert_ptr_not_null(map);
|
||||
|
||||
/* ~5e7 interations due to 2e9 / avg(l) */
|
||||
for (int i = 0; i < 268435456;) {
|
||||
for (size_t i = 0; i < amt;) {
|
||||
int l = i % 31 + 16;
|
||||
sm_add_span(map, 268435456, l);
|
||||
sm_add_span(map, amt, l);
|
||||
if (errno == ENOSPC) {
|
||||
map = sparsemap_set_data_size(map, sparsemap_get_capacity(map) * 2);
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
/* After 10,000 spans are in there we consume a span every iteration. */
|
||||
if (l > 10000) {
|
||||
|
@ -1069,7 +1057,6 @@ test_scale_best_case(const MunitParameter params[], void *data)
|
|||
for (int i = 0; i < 172032; i++) {
|
||||
/* ANSI esc code to clear line, carrage return, then print on the same line */
|
||||
// printf("\033[2K\r%d", i);
|
||||
// fflush(stdout);
|
||||
sparsemap_set(map, i, true);
|
||||
}
|
||||
|
||||
|
@ -1116,7 +1103,6 @@ test_scale_worst_case(const MunitParameter params[], void *data)
|
|||
for (int i = 0; i < 7744; i += 2) {
|
||||
/* ANSI esc code to clear line, carrage return, then print on the same line */
|
||||
// printf("\033[2K\r%d", i);
|
||||
// fflush(stdout);
|
||||
sparsemap_set(map, i, true);
|
||||
}
|
||||
|
||||
|
@ -1260,6 +1246,11 @@ int
|
|||
main(int argc, char *argv[MUNIT_ARRAY_PARAM(argc + 1)])
|
||||
{
|
||||
struct user_data info;
|
||||
|
||||
/* Disable buffering on std{out,err} to avoid having to call fflush(). */
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
|
||||
return munit_suite_main(&main_test_suite, (void *)&info, argc, argv);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue