adding a merge map function #6

Merged
greg merged 12 commits from gburd/merge-map into main 2024-04-30 15:20:48 +00:00
2 changed files with 41 additions and 5 deletions
Showing only changes of commit b399e8af78 - Show all commits

View file

@ -825,7 +825,8 @@ __sm_get_fully_aligned_offset(size_t idx)
* *
* @param[in] map The sparsemap_t in question. * @param[in] map The sparsemap_t in question.
* @param[in] idx The index of the chunk map to locate. * @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 static size_t
__sm_get_chunk_map_offset(sparsemap_t *map, sparsemap_idx_t idx) __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_assert(s == __sm_get_aligned_offset(s));
__sm_chunk_t chunk; __sm_chunk_t chunk;
__sm_chunk_map_init(&chunk, p + sizeof(sm_idx_t)); __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; break;
} }
p += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&chunk); 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; 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. */ immediately; otherwise create an initial __sm_chunk_t. */
if (offset == -1) { if (offset == -1) {
if (value == false) { if (value == false) {
@ -1270,6 +1271,7 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other)
__sm_chunk_t dst_chunk; __sm_chunk_t dst_chunk;
__sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t)); __sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t));
__sm_chunk_map_merge(map, src_start, src_chunk); __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); 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 += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&dst_chunk);
dst_count--; dst_count--;
@ -1280,14 +1282,24 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other)
__sm_chunk_t src_chunk; __sm_chunk_t src_chunk;
__sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t)); __sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t));
size_t src_size = __sm_chunk_map_get_size(&src_chunk); 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; *(sm_idx_t *)dst = src_start;
/* Update the chunk count and data_used. */ /* Update the chunk count and data_used. */
__sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1); __sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1);
/* Carry on to the next chunk. */ /* 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); 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--; src_count--;
} }
} }

View file

@ -631,8 +631,10 @@ test_api_merge(const MunitParameter params[], void *data)
assert_ptr_not_null(map); assert_ptr_not_null(map);
assert_ptr_not_null(other); assert_ptr_not_null(other);
// Merge two empty maps to get an empty map.
sparsemap_merge(map, other); sparsemap_merge(map, other);
// Merge a single set bit in the first chunk into the empty map.
sparsemap_set(other, 0, true); sparsemap_set(other, 0, true);
sparsemap_merge(map, other); sparsemap_merge(map, other);
@ -642,6 +644,7 @@ test_api_merge(const MunitParameter params[], void *data)
sparsemap_clear(map); sparsemap_clear(map);
sparsemap_clear(other); sparsemap_clear(other);
// Merge two maps with the same single bit set.
sparsemap_set(map, 0, true); sparsemap_set(map, 0, true);
sparsemap_set(other, 0, true); sparsemap_set(other, 0, true);
sparsemap_merge(map, other); sparsemap_merge(map, other);
@ -649,6 +652,7 @@ test_api_merge(const MunitParameter params[], void *data)
sparsemap_clear(map); sparsemap_clear(map);
sparsemap_clear(other); sparsemap_clear(other);
// Merge an empty map with one that has the first bit set.
sparsemap_set(map, 0, true); sparsemap_set(map, 0, true);
sparsemap_merge(map, other); sparsemap_merge(map, other);
@ -680,12 +684,32 @@ test_api_merge(const MunitParameter params[], void *data)
assert_true(sparsemap_is_set(map, 8193)); assert_true(sparsemap_is_set(map, 8193));
for (int i = 0; i < 10000; i++) { 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; continue;
else else
assert_false(sparsemap_is_set(map, i)); 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); free(other);
return MUNIT_OK; return MUNIT_OK;
} }