From b399e8af7813a9bd3f0f217a0ccff5f2ea793f9c Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Tue, 30 Apr 2024 10:44:43 -0400 Subject: [PATCH] WIP --- src/sparsemap.c | 20 ++++++++++++++++---- tests/test.c | 26 +++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/sparsemap.c b/src/sparsemap.c index 1636d63..8c4530d 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -825,7 +825,8 @@ __sm_get_fully_aligned_offset(size_t idx) * * @param[in] map The sparsemap_t in question. * @param[in] idx The index of the chunk map to locate. - * @returns the byte offset of a __sm_chunk_t in m_data. + * @returns the byte offset of a __sm_chunk_t in m_data, or -1 there + * are no chunks. */ static size_t __sm_get_chunk_map_offset(sparsemap_t *map, sparsemap_idx_t idx) @@ -843,7 +844,7 @@ __sm_get_chunk_map_offset(sparsemap_t *map, sparsemap_idx_t idx) __sm_assert(s == __sm_get_aligned_offset(s)); __sm_chunk_t chunk; __sm_chunk_map_init(&chunk, p + sizeof(sm_idx_t)); - if (s >= idx || (unsigned long)idx < s + __sm_chunk_map_get_capacity(&chunk)) { + if (s >= idx || idx < s + __sm_chunk_map_get_capacity(&chunk)) { break; } p += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&chunk); @@ -1070,7 +1071,7 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value) return SPARSEMAP_IDX_MAX; } - /* If there is no __sm_chunk_t and the bit is set to zero then return + /* If there are no __sm_chunk_t and the bit is set to zero then return immediately; otherwise create an initial __sm_chunk_t. */ if (offset == -1) { if (value == false) { @@ -1270,6 +1271,7 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other) __sm_chunk_t dst_chunk; __sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t)); __sm_chunk_map_merge(map, src_start, src_chunk); + *(sm_idx_t *)dst = __sm_get_aligned_offset(src_start); src += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&src_chunk); dst += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&dst_chunk); dst_count--; @@ -1280,14 +1282,24 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other) __sm_chunk_t src_chunk; __sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t)); size_t src_size = __sm_chunk_map_get_size(&src_chunk); - __sm_insert_data(map, dst_start, src, src_size); + uint8_t buf[sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2] = { 0 }; + if (dst_count == 0) { + __sm_append_data(map, &buf[0], sizeof(buf)); + } else { + size_t offset = __sm_get_chunk_map_offset(map, dst_start); + __sm_insert_data(map, offset, &buf[0], sizeof(buf)); + } + memcpy(dst + sizeof(sm_idx_t), &src_chunk, src_size); *(sm_idx_t *)dst = src_start; /* Update the chunk count and data_used. */ __sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1); /* Carry on to the next chunk. */ + __sm_chunk_t dst_chunk; + __sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t)); src += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&src_chunk); + dst += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&dst_chunk); src_count--; } } diff --git a/tests/test.c b/tests/test.c index f1feeb8..82bef5c 100644 --- a/tests/test.c +++ b/tests/test.c @@ -631,8 +631,10 @@ test_api_merge(const MunitParameter params[], void *data) assert_ptr_not_null(map); assert_ptr_not_null(other); + // Merge two empty maps to get an empty map. sparsemap_merge(map, other); + // Merge a single set bit in the first chunk into the empty map. sparsemap_set(other, 0, true); sparsemap_merge(map, other); @@ -642,6 +644,7 @@ test_api_merge(const MunitParameter params[], void *data) sparsemap_clear(map); sparsemap_clear(other); + // Merge two maps with the same single bit set. sparsemap_set(map, 0, true); sparsemap_set(other, 0, true); sparsemap_merge(map, other); @@ -649,6 +652,7 @@ test_api_merge(const MunitParameter params[], void *data) sparsemap_clear(map); sparsemap_clear(other); + // Merge an empty map with one that has the first bit set. sparsemap_set(map, 0, true); sparsemap_merge(map, other); @@ -680,12 +684,32 @@ test_api_merge(const MunitParameter params[], void *data) assert_true(sparsemap_is_set(map, 8193)); for (int i = 0; i < 10000; i++) { - if (i == 2050 || i == 1 || i == 2049 || i == 4097 || i == 8193) + if (i == 2049 || i == 1 || i == 2050 || i == 4097 || i == 8193) continue; else assert_false(sparsemap_is_set(map, i)); } + sparsemap_clear(map); + sparsemap_clear(other); + + sparsemap_set(map, 0, true); + sparsemap_set(map, 2048, true); + sparsemap_set(map, 2049, true); + sparsemap_set(map, 8193, true); + for (int i = 2049; i < 4096; i++) { + sparsemap_set(other, i, true); + } + + sparsemap_merge(map, other); + + assert(sparsemap_is_set(map, 0)); + assert(sparsemap_is_set(map, 2048)); + assert(sparsemap_is_set(map, 8193)); + for (int i = 2049; i < 4096; i++) { + assert(sparsemap_is_set(map, i)); + } + free(other); return MUNIT_OK; }