From f5b500087dce29848eb6cc4ba009f7a2d75646e1 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Mon, 13 May 2024 12:46:25 -0400 Subject: [PATCH] split --- Makefile | 8 +++---- src/sparsemap.c | 21 +++++++++--------- tests/test.c | 59 ++++++++++++++++++++++++++++--------------------- 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 8ed2f3f..1eb2aa4 100644 --- a/Makefile +++ b/Makefile @@ -6,16 +6,16 @@ SHARED_LIB = libsparsemap.so LIBS = -lm #CFLAGS = -Wall -Wextra -Wpedantic -Of -std=c11 -Iinclude/ -fPIC #CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC -CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -fPIC -#CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -fPIC +#CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -fPIC +CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -fPIC #CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC #CFLAGS = -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -fPIC #CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11 -Iinclude/ -fPIC #CFLAGS = -Wall -Wextra -Wpedantic -Og -g -fsanitize=all -fhardened -std=c11 -Iinclude/ -fPIC #TEST_FLAGS = -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -Itests/ -fPIC -#TEST_FLAGS = -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -Itests/ -fPIC -TEST_FLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -Itests/ -fPIC +TEST_FLAGS = -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -Itests/ -fPIC +#TEST_FLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -Itests/ -fPIC #TEST_FLAGS = -DDEBUG -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11 -Iinclude/ -fPIC TESTS = tests/test tests/soak diff --git a/src/sparsemap.c b/src/sparsemap.c index 76bd5d9..0da2391 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -228,7 +228,7 @@ static void __sm_chunk_reduce_capacity(__sm_chunk_t *chunk, size_t capacity) { __sm_assert(capacity % SM_BITS_PER_VECTOR == 0); - __sm_assert(capacity < SM_CHUNK_MAX_CAPACITY); + __sm_assert(capacity <= SM_CHUNK_MAX_CAPACITY); if (capacity >= SM_CHUNK_MAX_CAPACITY) { return; @@ -1251,7 +1251,7 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value) __sm_insert_data(map, offset, &buf[0], sizeof(buf)); start += __sm_chunk_get_capacity(&chunk); - if ((sparsemap_idx_t)start + SM_CHUNK_MAX_CAPACITY < idx) { + if ((sparsemap_idx_t)start + SM_CHUNK_MAX_CAPACITY <= idx) { start = __sm_get_chunk_aligned_offset(idx); } *(sm_idx_t *)p = start; @@ -1610,7 +1610,7 @@ sparsemap_merge(sparsemap_t *destination, sparsemap_t *source) sparsemap_idx_t sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other) { - if (offset == 0) { + if (!(offset == SPARSEMAP_IDX_MAX) && (offset < 0 || offset >= sparsemap_get_ending_offset(map))) { return 0; } @@ -1631,10 +1631,6 @@ sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other) /* |src| points to the source-chunk */ uint8_t *src = __sm_get_chunk_data(map, 0); - /* |offset| is relative to the beginning of this sparsemap_t; best - make it absolute. */ - offset += *(sm_idx_t *)src; - bool in_middle = false; uint8_t *prev = src; size_t i, count = __sm_get_chunk_count(map); @@ -1688,14 +1684,17 @@ sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other) __sm_chunk_t d_chunk; __sm_chunk_init(&d_chunk, dst); - __sm_chunk_reduce_capacity(&d_chunk, capacity - (offset % capacity)); + __sm_chunk_reduce_capacity(&d_chunk, __sm_get_vector_aligned_offset(capacity - (offset % capacity))); /* Now copy the bits. */ sparsemap_idx_t d = offset; + sparsemap_idx_t b = __sm_get_vector_aligned_offset(offset % capacity); for (size_t j = offset % capacity; j < capacity; j++, d++) { if (__sm_chunk_is_set(&s_chunk, j)) { - sparsemap_set(other, d, true); - sparsemap_set(map, d, false); // TODO remove, and fix reduce_capacity below + assert(sparsemap_set(other, d, true) == d); + if (j > b && (j - b) % capacity < SM_BITS_PER_VECTOR) { + sparsemap_set(map, d, false); + } } } @@ -1705,7 +1704,7 @@ sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other) i++; /* Reduce the capacity of the source-chunk effectively erases bits. */ - // TODO: __sm_chunk_reduce_capacity(&s_chunk, offset % capacity); + __sm_chunk_reduce_capacity(&s_chunk, b + SM_BITS_PER_VECTOR); } /* Now continue with all remaining chunks. */ diff --git a/tests/test.c b/tests/test.c index 0513539..a4f461d 100644 --- a/tests/test.c +++ b/tests/test.c @@ -720,35 +720,43 @@ test_api_split(const MunitParameter params[], void *data) sparsemap_init(&portion, buf, 1024); - for (int i = 0; i < 1024; i++) { - sparsemap_set(map, i, true); - } - for (int i = 0; i < 1024; i++) { - assert_true(sparsemap_is_set(map, i)); - assert_false(sparsemap_is_set(&portion, i)); - } - sparsemap_split(map, 512, &portion); - for (int i = 0; i < 512; i++) { - assert_true(sparsemap_is_set(map, i)); - assert_false(sparsemap_is_set(&portion, i)); - } - for (int i = 513; i < 1024; i++) { - assert_false(sparsemap_is_set(map, i)); - assert_true(sparsemap_is_set(&portion, i)); + for (sparsemap_idx_t off = 0; off < 1024; off++) { + for (sparsemap_idx_t seg = 0; seg < 10 * 1024; seg += 1024) { + + for (sparsemap_idx_t i = 0; i < 1024; i++) { + assert_true(sparsemap_set(map, i + seg, true) == i + seg); + } + for (sparsemap_idx_t i = 0; i < 1024; i++) { + assert_true(sparsemap_is_set(map, i + seg)); + assert_false(sparsemap_is_set(&portion, i + seg)); + } + + sparsemap_split(map, seg + off, &portion); + + for (sparsemap_idx_t i = 0; i < off; i++) { + assert_true(sparsemap_is_set(map, i + seg)); + assert_false(sparsemap_is_set(&portion, i + seg)); + } + for (sparsemap_idx_t i = off + 1; i < 1024; i++) { + assert_false(sparsemap_is_set(map, i + seg)); + assert_true(sparsemap_is_set(&portion, i + seg)); + } + + sparsemap_clear(map); + sparsemap_clear(&portion); + } } - sparsemap_clear(map); - sparsemap_clear(&portion); - - for (int i = 0; i < 100; i++) { - sparsemap_set(map, i, true); + for (sparsemap_idx_t i = 0; i < 100; i++) { + assert_true(sparsemap_set(map, i, true) == i); } - for (int i = 0; i < 100; i++) { + for (sparsemap_idx_t i = 0; i < 100; i++) { assert_true(sparsemap_is_set(map, i)); assert_false(sparsemap_is_set(&portion, i)); } sparsemap_idx_t offset = sparsemap_split(map, SPARSEMAP_IDX_MAX, &portion); + for (size_t i = 0; i < offset; i++) { assert_true(sparsemap_is_set(map, i)); assert_false(sparsemap_is_set(&portion, i)); @@ -762,16 +770,17 @@ test_api_split(const MunitParameter params[], void *data) sparsemap_clear(map); sparsemap_init(&portion, buf, 1024); - for (int i = 0; i < 13; i++) { - sparsemap_set(map, i + 24, true); + for (sparsemap_idx_t i = 0; i < 13; i++) { + assert_true(sparsemap_set(map, i + 24, true) == i + 24); } offset = sparsemap_split(map, SPARSEMAP_IDX_MAX, &portion); - for (size_t i = 0; i < offset - 24; i++) { + + for (sparsemap_idx_t i = 0; i < offset - 24; i++) { assert_true(sparsemap_is_set(map, i + 24)); assert_false(sparsemap_is_set(&portion, i + 24)); } - for (int i = offset - 24; i < 13; i++) { + for (sparsemap_idx_t i = offset - 24; i < 13; i++) { assert_false(sparsemap_is_set(map, i + 24)); assert_true(sparsemap_is_set(&portion, i + 24)); }