adding a merge map function #6
2 changed files with 41 additions and 5 deletions
|
@ -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--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
tests/test.c
26
tests/test.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue