use new set/unset/assign API

This commit is contained in:
Gregory Burd 2024-07-29 05:31:55 -04:00
parent b032d61b63
commit e5906249b4
10 changed files with 149 additions and 272 deletions

View file

@ -15,8 +15,8 @@ set(SOURCE_DIR .)
set(HEADER_DIR . test)
set(COMMON_CMAKE_C_FLAGS "-Wall -Wextra -Wpedantic")
set(CMAKE_C_FLAGS_DEBUG "-DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_TESTING -DDEBUG -g -O0")
set(CMAKE_C_FLAGS_PROFILE "-DSPARSEMAP_DIAGNOSTIC -DDEBUG -g -Og -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope")
set(CMAKE_C_FLAGS_DEBUG "-DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_TESTING -DDEBUG -g -Og")
set(CMAKE_C_FLAGS_PROFILE "-g -Og -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope")
set(CMAKE_C_FLAGS_RELEASE "-Ofast")
# Include all header files from the header directory
@ -76,7 +76,7 @@ add_custom_target(run_ex_4 COMMAND ex_4 WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_executable(test test/test.c test/munit.c test/qc.c test/common.c)
target_link_libraries(test PRIVATE sparsemap)
target_include_directories(test PRIVATE ${HEADER_DIR})
set_source_files_properties(test/test.c PROPERTIES COMPILE_FLAGS "-DDEBUG -DDIAGNOSTIC -DSPARSEMAP_TESTING" )
set_source_files_properties(test/test.c PROPERTIES COMPILE_FLAGS "-DDEBUG -DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_TESTING" )
add_custom_target(run_test COMMAND test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Add soak program

View file

@ -74,9 +74,9 @@ typedef struct {
} __sm_chunk_t;
// TODO remove me, this is only used for debugging.
#ifdef SPARSEMAP_DIAGNOSTIC
#ifdef SPARSEMAP_TESTING
static char *QCC_showChunk(void *value, int len);
static char *_qcc_format_chunk(__sm_idx_t start, __sm_chunk_t * chunk);
static char *_qcc_format_chunk(__sm_idx_t start, __sm_chunk_t *chunk);
#endif
enum __SM_CHUNK_INFO {
@ -647,6 +647,7 @@ __sm_chunk_set_bit(__sm_chunk_t *chunk, sparsemap_idx_t idx, size_t *pos)
* @note, the caller MUST to perform the relevant actions and call set() again,
* this time with \b retried = true.
*/
// TODO remove me... use __sm_chunk_bit_set/unset()
static int
__sm_chunk_set(__sm_chunk_t *chunk, size_t idx, bool value, size_t *pos, __sm_bitvec_t *fill, bool retried)
{
@ -1435,7 +1436,7 @@ sparsemap_is_set(sparsemap_t *map, sparsemap_idx_t idx)
}
sparsemap_idx_t
bidx_clear(sparsemap_t *map, sparsemap_idx_t idx)
sparsemap_unset(sparsemap_t *map, sparsemap_idx_t idx)
{
__sm_assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD);
@ -1717,7 +1718,7 @@ bidx_clear(sparsemap_t *map, sparsemap_idx_t idx)
* don't need to allocate it now.
*/
static sparsemap_idx_t
__bidx_set(sparsemap_t *map, sparsemap_idx_t idx, uint8_t *p, size_t offset, __sm_bitvec_t *v)
__sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, uint8_t *p, size_t offset, __sm_bitvec_t *v)
{
size_t pos = v ? -1 : 0;
__sm_chunk_t chunk;
@ -1759,7 +1760,7 @@ __bidx_set(sparsemap_t *map, sparsemap_idx_t idx, uint8_t *p, size_t offset, __s
}
sparsemap_idx_t
bidx_set(sparsemap_t *map, sparsemap_idx_t idx)
sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx)
{
__sm_assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD);
@ -1780,7 +1781,7 @@ bidx_set(sparsemap_t *map, sparsemap_idx_t idx)
__sm_set_chunk_count(map, 1);
__sm_bitvec_t *v = (__sm_bitvec_t *)(uintptr_t)p + SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t);
return __bidx_set(map, idx, p, 0, v);
return __sparsemap_set(map, idx, p, 0, v);
}
/* Try to locate a chunk for this idx. We could find that:
@ -1803,7 +1804,7 @@ bidx_set(sparsemap_t *map, sparsemap_idx_t idx)
__sm_set_chunk_count(map, __sm_get_chunk_count(map) + 1);
__sm_bitvec_t *v = (__sm_bitvec_t *)(uintptr_t)p + SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t);
return __bidx_set(map, idx, p, offset, v);
return __sparsemap_set(map, idx, p, offset, v);
}
__sm_chunk_t chunk;
@ -1870,10 +1871,10 @@ bidx_set(sparsemap_t *map, sparsemap_idx_t idx)
__sm_set_chunk_count(map, __sm_get_chunk_count(map) + 1);
__sm_bitvec_t *v = (__sm_bitvec_t *)(uintptr_t)p + SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t);
return __bidx_set(map, idx, p, offset, v);
return __sparsemap_set(map, idx, p, offset, v);
}
__sm_idx_t ret_idx = __bidx_set(map, idx, p, offset, NULL);
__sm_idx_t ret_idx = __sparsemap_set(map, idx, p, offset, NULL);
/* Did this chunk become all ones, can we compact it with adjacent chunks? */
if (chunk.m_data[0] == ~(__sm_bitvec_t)0) {
@ -1944,169 +1945,15 @@ bidx_set(sparsemap_t *map, sparsemap_idx_t idx)
}
sparsemap_idx_t
bidx_set_to(sparsemap_t *map, sparsemap_idx_t idx, bool value)
sparsemap_assign(sparsemap_t *map, sparsemap_idx_t idx, bool value)
{
if (value) {
return bidx_set(map, idx);
return sparsemap_set(map, idx);
} else {
return bidx_clear(map, idx);
return sparsemap_unset(map, idx);
}
}
sparsemap_idx_t
sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value)
{
return bidx_set_to(map, idx, value);
__sm_assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD);
/* Locate the __sm_chunk_t for this index */
ssize_t offset = __sm_get_chunk_offset(map, idx);
bool dont_grow = false;
/* If we're going to set a new bit there is the potential that we'll need
* additional space in the buffer, ensure we have enough. */
if (value && map->m_data_used + SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t) * 2 > map->m_capacity) {
errno = ENOSPC;
return SPARSEMAP_IDX_MAX;
}
/* No chunks exists, the map is empty, create one now... */
if (offset == -1) {
/* ...unless we're trying to turn a bit off (when `value` is false) in which
* case we're done (because the bit is implictly "unset" at that `idx`). */
if (value == false) {
return idx;
}
/* Append a newly initialized vector to the end of the buffer. */
uint8_t buf[SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t) * 2] = { 0 };
__sm_append_data(map, &buf[0], sizeof(buf));
/* Fetch that new chunk at index 0 and set its starting offset relative to
* `idx`. */
offset = 0;
uint8_t *p = __sm_get_chunk_data(map, offset);
*(__sm_idx_t *)p = __sm_get_chunk_aligned_offset(idx);
__sm_set_chunk_count(map, 1);
/* Now that we have inserted a chunk should avoid doing so again; there is
* no need to grow the vector. */
dont_grow = true;
}
/* Now we either find the pre-existing chunk for this `idx` or the one we just
* created above. */
uint8_t *p = __sm_get_chunk_data(map, offset);
__sm_idx_t start = *(__sm_idx_t *)p;
__sm_assert(start == __sm_get_chunk_aligned_offset(start));
/* The new index is smaller than the first __sm_chunk_t: create a new
* __sm_chunk_t and insert it at the front. */
if (idx < start) {
if (value == false) {
/* nothing to do */
return idx;
}
uint8_t buf[SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t) * 2] = { 0 };
__sm_insert_data(map, offset, &buf[0], sizeof(buf));
size_t aligned_idx = __sm_get_chunk_aligned_offset(idx);
#if 0
if (start - aligned_idx < SM_CHUNK_MAX_CAPACITY) {
__sm_chunk_t chunk;
__sm_chunk_init(&chunk, p + SM_SIZEOF_OVERHEAD);
if (__sm_chunk_reduce_capacity(&chunk, start - aligned_idx)) {
/* The __sm_chunk_t is empty then remove it. */
__sm_remove_data(map, offset, SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t) * 2);
__sm_set_chunk_count(map, __sm_get_chunk_count(map) - 1);
}
}
#endif
*(__sm_idx_t *)p = start = aligned_idx;
/* We just added another chunk! */
__sm_set_chunk_count(map, __sm_get_chunk_count(map) + 1);
/* We already inserted an additional __sm_bitvec_t; later on there
* is no need to grow the vector even further. */
dont_grow = true;
}
/* A __sm_chunk_t exists, but the new index exceeds its capacities: create
* a new __sm_chunk_t and insert it after the current one. */
else {
__sm_chunk_t chunk;
__sm_chunk_init(&chunk, p + SM_SIZEOF_OVERHEAD);
if (idx - start >= (sparsemap_idx_t)__sm_chunk_get_capacity(&chunk)) {
if (value == false) {
/* nothing to do */
return idx;
}
size_t size = __sm_chunk_get_size(&chunk);
offset += (SM_SIZEOF_OVERHEAD + size);
p += SM_SIZEOF_OVERHEAD + size;
uint8_t buf[SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t) * 2] = { 0 };
__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) {
start = __sm_get_chunk_aligned_offset(idx);
}
*(__sm_idx_t *)p = start;
__sm_assert(start == __sm_get_chunk_aligned_offset(start));
/* We just added another chunk! */
__sm_set_chunk_count(map, __sm_get_chunk_count(map) + 1);
/* We already inserted an additional __sm_bitvec_t; later on there
* is no need to grow the vector even further. */
dont_grow = true;
}
}
__sm_chunk_t chunk;
__sm_chunk_init(&chunk, p + SM_SIZEOF_OVERHEAD);
/* Now update the __sm_chunk_t. */
size_t position;
__sm_bitvec_t fill;
int code = __sm_chunk_set(&chunk, idx - start, value, &position, &fill, false);
switch (code) {
case SM_OK:
break;
case SM_NEEDS_TO_GROW:
if (!dont_grow) {
offset += (SM_SIZEOF_OVERHEAD + position * sizeof(__sm_bitvec_t));
__sm_insert_data(map, offset, (uint8_t *)&fill, sizeof(__sm_bitvec_t));
}
__sm_chunk_set(&chunk, idx - start, value, &position, &fill, true);
break;
case SM_NEEDS_TO_SHRINK:
/* If the __sm_chunk_t is empty then remove it. */
if (__sm_chunk_is_empty(&chunk)) {
__sm_assert(position == 1);
__sm_remove_data(map, offset, SM_SIZEOF_OVERHEAD + sizeof(__sm_bitvec_t) * 2);
__sm_set_chunk_count(map, __sm_get_chunk_count(map) - 1);
} else {
offset += (SM_SIZEOF_OVERHEAD + position * sizeof(__sm_bitvec_t));
__sm_remove_data(map, offset, sizeof(__sm_bitvec_t));
}
break;
default:
__sm_assert(!"shouldn't be here");
#ifdef DEBUG
abort();
#endif
break;
}
__sm_assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD);
return idx;
}
sparsemap_idx_t
sparsemap_get_starting_offset(sparsemap_t *map)
{
@ -2335,7 +2182,7 @@ sparsemap_merge(sparsemap_t *destination, sparsemap_t *source)
__sm_merge_chunk(destination, src_start, dst_start, overlap, &dst_chunk, &src_chunk);
for (size_t n = src_start + overlap; n <= src_end; n++) {
if (sparsemap_is_set(source, n)) {
sparsemap_set(destination, n, true);
sparsemap_set(destination, n);
}
}
src_count--;
@ -2462,7 +2309,7 @@ sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other)
__sm_bitvec_t fill;
size_t pos;
__sm_chunk_set(&d_chunk, j - start, true, &pos, &fill, true);
sparsemap_set(map, j, false);
sparsemap_unset(map, j);
}
}
}
@ -2740,7 +2587,6 @@ _qcc_format_chunk(__sm_idx_t start, __sm_chunk_t *chunk)
str += sprintf(str, "");
mixed++;
break;
default:
}
}
str = buf + sprintf(buf, "%.10u\t%s%s", start, desc_str, mixed ? " :: " : "");
@ -3009,7 +2855,7 @@ _tst_get_chunk_offset(QCC_GenValue **vals, int len, QCC_Stamp **stamp)
// per and with exactly one additional bitvec per so we should observe...
for (int i = 0; i < rnd_nvec; i++) {
sparsemap_idx_t l = offset + (i * SM_CHUNK_MAX_CAPACITY);
sparsemap_set(map, l, true);
sparsemap_set(map, l);
}
for (int i = 0; i < rnd_nvec; i++) {
size_t expected_offset = __sm_get_chunk_offset(map, offset + (i * SM_CHUNK_MAX_CAPACITY));
@ -3022,7 +2868,7 @@ _tst_get_chunk_offset(QCC_GenValue **vals, int len, QCC_Stamp **stamp)
// Now for RLE, first let's clear and check a full chunk.
sparsemap_clear(map);
for (int i = 0; i < SM_CHUNK_MAX_CAPACITY; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
for (int i = 0; i < SM_CHUNK_MAX_CAPACITY; i++) {
if (__sm_get_chunk_offset(map, i) != 0) {
@ -3034,37 +2880,37 @@ _tst_get_chunk_offset(QCC_GenValue **vals, int len, QCC_Stamp **stamp)
}
// This should trigger the transformation of the 0th chunk into RLE.
sparsemap_set(map, SM_CHUNK_MAX_CAPACITY, true);
sparsemap_set(map, SM_CHUNK_MAX_CAPACITY);
if (__sm_get_chunk_offset(map, SM_CHUNK_MAX_CAPACITY) != 0) {
return QCC_FAIL;
}
// This should trigger the transformation of the 0th chunk back to sparse.
sparsemap_set(map, SM_CHUNK_MAX_CAPACITY, false);
sparsemap_unset(map, SM_CHUNK_MAX_CAPACITY);
if (__sm_get_chunk_offset(map, SM_CHUNK_MAX_CAPACITY) != 0) {
return QCC_FAIL;
}
// This should trigger the transformation of the 0th chunk into RLE again.
for (int i = 0; i < 3000; i++) {
sparsemap_set(map, SM_CHUNK_MAX_CAPACITY + i, true);
sparsemap_set(map, SM_CHUNK_MAX_CAPACITY + i);
}
// This should trigger the transformation of the 0th chunk back to sparse,
// but also create a second and third sparse chunks.
sparsemap_set(map, 0, false);
sparsemap_unset(map, 0);
if (__sm_get_chunk_offset(map, 0) != 0) {
return QCC_FAIL;
}
sparsemap_set(map, 0, true);
sparsemap_set(map, 0);
// This will split the chunk into two chunks; sparse, RLE.
sparsemap_set(map, 129, false);
sparsemap_unset(map, 129);
if (__sm_get_chunk_offset(map, 129) != 0) {
return QCC_FAIL;
}
sparsemap_set(map, 129, true);
sparsemap_set(map, 129);
// This will split the chunk into three chunks; sparse, sparse, RLE.
sparsemap_set(map, 2050, false);
sparsemap_unset(map, 2050);
if (__sm_get_chunk_offset(map, 0) != 0) {
return QCC_FAIL;
}
@ -3074,10 +2920,10 @@ _tst_get_chunk_offset(QCC_GenValue **vals, int len, QCC_Stamp **stamp)
if (__sm_get_chunk_offset(map, 2050 + SM_CHUNK_MAX_CAPACITY) != 2 * SM_SIZEOF_OVERHEAD + 3 * sizeof(__sm_bitvec_t)) {
return QCC_FAIL;
}
sparsemap_set(map, 2050, true);
sparsemap_set(map, 2050);
// This won't split the chunk, it just shrinks the RLE by one.
sparsemap_set(map, 5047, false);
sparsemap_unset(map, 5047);
if (__sm_get_chunk_offset(map, 5046) != 0) {
return QCC_FAIL;
}

View file

@ -227,7 +227,7 @@ size_t sparsemap_get_capacity(sparsemap_t *map);
*/
bool sparsemap_is_set(sparsemap_t *map, sparsemap_idx_t idx);
/** @brief Sets the bit at index \b idx to \b value.
/** @brief Assigns the bit at 0-based index \b idx to \b value.
*
* A sparsemap has a fixed size buffer with a capacity that can be exhausted by
* when calling this function. In such cases the return value is not equal to
@ -237,10 +237,41 @@ bool sparsemap_is_set(sparsemap_t *map, sparsemap_idx_t idx);
*
* @param[in] map The sparsemap reference.
* @param[in] idx The 0-based offset into the bitmap index to modify.
* @param[in] value When true idx set to 1, otherwise idx set to 0.
* @returns the \b idx supplied on success or SPARSEMAP_IDX_MAX on error
* with \b errno set to ENOSPC when the map is full.
*/
sparsemap_idx_t sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value);
sparsemap_idx_t sparsemap_assign(sparsemap_t *map, sparsemap_idx_t idx, bool value);
/** @brief Sets the bit at 0-based index \b idx to 1.
*
* A sparsemap has a fixed size buffer with a capacity that can be exhausted by
* when calling this function. In such cases the return value is not equal to
* the provided \b idx and errno is set to ENOSPC. In such situations it is
* possible to grow the data size and retry the set() operation under certain
* circumstances (see #sparsemap() and #sparsemap_set_data_size()).
*
* @param[in] map The sparsemap reference.
* @param[in] idx The 0-based offset into the bitmap index to set to 1;
* @returns the \b idx supplied on success or SPARSEMAP_IDX_MAX on error
* with \b errno set to ENOSPC when the map is full.
*/
sparsemap_idx_t sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx);
/** @brief Unsets the bit at 0-based index \b idx (sets it to 0).
*
* A sparsemap has a fixed size buffer with a capacity that can be exhausted by
* when calling this function. In such cases the return value is not equal to
* the provided \b idx and errno is set to ENOSPC. In such situations it is
* possible to grow the data size and retry the set() operation under certain
* circumstances (see #sparsemap() and #sparsemap_set_data_size()).
*
* @param[in] map The sparsemap reference.
* @param[in] idx The 0-based offset into the bitmap index to unset.
* @returns the \b idx supplied on success or SPARSEMAP_IDX_MAX on error
* with \b errno set to ENOSPC when the map is full.
*/
sparsemap_idx_t sparsemap_unset(sparsemap_t *map, sparsemap_idx_t idx);
/** @brief Returns the byte size of the data buffer that has been used thus far.
*

View file

@ -347,7 +347,7 @@ bitmap_from_uint32(sparsemap_t *map, uint32_t number)
{
for (int i = 0; i < 32; i++) {
bool bit = number & (1 << i);
sparsemap_set(map, i, bit);
sparsemap_assign(map, i, bit);
}
}
@ -398,7 +398,7 @@ sm_bitmap_from_uint64(sparsemap_t *map, int offset, uint64_t number)
{
for (int i = offset; i < 64; i++) {
bool bit = number & ((uint64_t)1 << i);
sparsemap_set(map, i, bit);
sparsemap_assign(map, i, bit);
}
}
@ -416,7 +416,7 @@ sm_add_span(sparsemap_t *map, int map_size, int span_length)
}
} while (attempts);
for (sparsemap_idx_t i = placed_at; i < placed_at + span_length; i++) {
if (sparsemap_set(map, i, true) != i) {
if (sparsemap_set(map, i) != i) {
return placed_at; // TODO error?
}
}

View file

@ -35,16 +35,16 @@ main()
uint8_t buffer2[1024];
sparsemap_init(map, buffer, sizeof(buffer));
assert(sparsemap_get_size(map) == size);
sparsemap_set(map, 0, true);
sparsemap_set(map, 0);
assert(sparsemap_get_size(map) == size + 4 + 8 + 8);
assert(sparsemap_is_set(map, 0) == true);
assert(sparsemap_get_size(map) == size + 4 + 8 + 8);
assert(sparsemap_is_set(map, 1) == false);
sparsemap_set(map, 0, false);
sparsemap_unset(map, 0);
assert(sparsemap_get_size(map) == size);
sparsemap_clear(map);
sparsemap_set(map, 64, true);
sparsemap_set(map, 64);
assert(sparsemap_is_set(map, 64) == true);
assert(sparsemap_get_size(map) == size + 4 + 8 + 8);
@ -54,7 +54,7 @@ main()
// set [0..100000]
for (int i = 0; i < 100000; i++) {
assert(sparsemap_is_set(map, i) == false);
sparsemap_set(map, i, true);
sparsemap_set(map, i);
if (i > 5) {
for (int j = i - 5; j <= i; j++) {
assert(sparsemap_is_set(map, j) == true);
@ -73,7 +73,7 @@ main()
// unset [0..10000]
for (int i = 0; i < 10000; i++) {
assert(sparsemap_is_set(map, i) == true);
sparsemap_set(map, i, false);
sparsemap_unset(map, i);
assert(sparsemap_is_set(map, i) == false);
}
@ -87,7 +87,7 @@ main()
// set [10000..0]
for (int i = 10000; i >= 0; i--) {
assert(sparsemap_is_set(map, i) == false);
sparsemap_set(map, i, true);
sparsemap_set(map, i);
assert(sparsemap_is_set(map, i) == true);
}
@ -106,7 +106,7 @@ main()
// unset [10000..0]
for (int i = 10000; i >= 0; i--) {
assert(sparsemap_is_set(map, i) == true);
sparsemap_set(map, i, false);
sparsemap_unset(map, i);
assert(sparsemap_is_set(map, i) == false);
}
@ -117,13 +117,13 @@ main()
fprintf(stderr, ".");
sparsemap_clear(map);
sparsemap_set(map, 0, true);
sparsemap_set(map, 2048 * 2 + 1, true);
sparsemap_set(map, 0);
sparsemap_set(map, 2048 * 2 + 1);
assert(sparsemap_is_set(map, 0) == true);
assert(sparsemap_is_set(map, 2048 * 2 + 0) == false);
assert(sparsemap_is_set(map, 2048 * 2 + 1) == true);
assert(sparsemap_is_set(map, 2048 * 2 + 2) == false);
sparsemap_set(map, 2048, true);
sparsemap_set(map, 2048);
assert(sparsemap_is_set(map, 0) == true);
assert(sparsemap_is_set(map, 2047) == false);
assert(sparsemap_is_set(map, 2048) == true);
@ -137,7 +137,7 @@ main()
fprintf(stderr, ".");
for (int i = 0; i < 100000; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
for (int i = 0; i < 100000; i++) {
assert(sparsemap_select(map, i, true) == (unsigned)i);
@ -147,7 +147,7 @@ main()
fprintf(stderr, ".");
for (int i = 1; i < 513; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
for (int i = 1; i < 513; i++) {
assert(sparsemap_select(map, i - 1, true) == (unsigned)i);
@ -157,7 +157,7 @@ main()
fprintf(stderr, ".");
for (size_t i = 0; i < 8; i++) {
sparsemap_set(map, i * 10, true);
sparsemap_set(map, i * 10);
}
for (size_t i = 0; i < 8; i++) {
assert(sparsemap_select(map, i, true) == (sparsemap_idx_t)i * 10);
@ -168,7 +168,7 @@ main()
sparsemap_init(sm2, buffer2, sizeof(buffer2));
sparsemap_clear(sm2);
for (int i = 0; i < 2048 * 2; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
sparsemap_split(map, 2048, sm2);
for (int i = 0; i < 2048; i++) {
@ -185,7 +185,7 @@ main()
sparsemap_init(sm2, buffer2, sizeof(buffer2));
sparsemap_clear(map);
for (int i = 0; i < 2048 * 3; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
assert(sparsemap_is_set(map, i) == true);
}
sparsemap_split(map, 64, sm2);

View file

@ -33,13 +33,13 @@ main(void)
// when the map is full.
for (i = 0; i < 7744; i++) {
if (!i % 2) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
assert(sparsemap_is_set(map, i) == true);
}
}
// On 1024 KiB of buffer with every other bit set the map holds 7744 bits
// and then runs out of space. This next _set() call will fail.
sparsemap_set(map, ++i, true);
sparsemap_set(map, ++i);
assert(sparsemap_is_set(map, i) == true);
return 0;
}

View file

@ -62,11 +62,11 @@ main(void)
// set all the bits on in a random order
for (i = 0; i < 1024; i++) {
__diag("set %d\n", array[i]);
sparsemap_set(map, array[i], true);
sparsemap_set(map, array[i]);
assert(sparsemap_is_set(map, array[i]) == true);
}
sparsemap_set(map, 1025, true);
sparsemap_set(map, 1025);
assert(sparsemap_is_set(map, 1025) == true);
return 0;

View file

@ -35,7 +35,7 @@ main(void)
// set all the bits on in a random order
for (i = 0; i < TEST_ARRAY_SIZE; i++) {
sparsemap_set(map, array[i], true);
sparsemap_set(map, array[i]);
assert(sparsemap_is_set(map, array[i]) == true);
}
@ -55,7 +55,7 @@ main(void)
shuffle(array, TEST_ARRAY_SIZE);
print_spans(array, TEST_ARRAY_SIZE);
for (i = 0; i < TEST_ARRAY_SIZE; i++) {
sparsemap_set(map, array[i], true);
sparsemap_set(map, array[i]);
assert(sparsemap_is_set(map, array[i]) == true);
}
has_span(map, array, TEST_ARRAY_SIZE, (int)len);

View file

@ -377,7 +377,7 @@ _sparsemap_set(sparsemap_t **_map, sparsemap_idx_t idx, bool value)
{
sparsemap_t *map = *_map, *new_map = NULL;
do {
sparsemap_idx_t l = sparsemap_set(map, idx, value);
sparsemap_idx_t l = sparsemap_assign(map, idx, value);
if (l != idx) {
if (errno == ENOSPC) {
size_t capacity = sparsemap_get_capacity(map) + 64;

View file

@ -50,7 +50,7 @@ populate_map(sparsemap_t *map, int size, int max_value)
shuffle(array, size);
before = sparsemap_count(map);
for (int i = 0; i < size; i++) {
sparsemap_set(map, array[i], true);
sparsemap_set(map, array[i]);
bool set = sparsemap_is_set(map, array[i]);
assert_true(set);
}
@ -206,7 +206,7 @@ test_api_clear(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
sparsemap_set(map, 42, true);
sparsemap_set(map, 42);
assert_true(sparsemap_is_set(map, 42));
sparsemap_clear(map);
assert_false(sparsemap_is_set(map, 42));
@ -315,7 +315,7 @@ test_api_remaining_capacity(const MunitParameter params[], void *data)
int i = 0;
double cap;
do {
sparsemap_set(map, i++, true);
sparsemap_set(map, i++);
cap = sparsemap_capacity_remaining(map);
} while (cap > 1.0 && errno != ENOSPC);
errno = 0;
@ -328,7 +328,7 @@ test_api_remaining_capacity(const MunitParameter params[], void *data)
i = 0;
do {
int p = munit_rand_int_range(0, 150000);
sparsemap_set(map, p, true);
sparsemap_set(map, p);
i++;
cap = sparsemap_capacity_remaining(map);
} while (cap > 1.0 && errno != ENOSPC);
@ -366,7 +366,7 @@ test_api_get_capacity(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
sparsemap_set(map, 42, true);
sparsemap_set(map, 42);
assert_true(sparsemap_is_set(map, 42));
assert_true(sparsemap_get_capacity(map) == 1024);
@ -401,7 +401,7 @@ test_api_is_set(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
sparsemap_set(map, 42, true);
sparsemap_set(map, 42);
assert_true(sparsemap_is_set(map, 42));
return MUNIT_OK;
@ -436,12 +436,12 @@ test_api_set(const MunitParameter params[], void *data)
assert_false(sparsemap_is_set(map, 1));
assert_false(sparsemap_is_set(map, 8192));
sparsemap_set(map, 1, true);
sparsemap_set(map, 8192, true);
sparsemap_set(map, 1);
sparsemap_set(map, 8192);
assert_true(sparsemap_is_set(map, 1));
assert_true(sparsemap_is_set(map, 8192));
sparsemap_set(map, 1, false);
sparsemap_set(map, 8192, false);
sparsemap_unset(map, 1);
sparsemap_unset(map, 8192);
assert_false(sparsemap_is_set(map, 1));
assert_false(sparsemap_is_set(map, 8192));
@ -513,15 +513,15 @@ test_api_count(const MunitParameter params[], void *data)
assert_true(sparsemap_count(map) == 1024);
sparsemap_clear(map);
sparsemap_set(map, 0, true);
sparsemap_set(map, 0);
assert_true(sparsemap_count(map) == 1);
sparsemap_set(map, 8675309, true);
sparsemap_set(map, 8675309);
assert_true(sparsemap_count(map) == 2);
sparsemap_clear(map);
for (int i = 0; i < 512; i++) {
sparsemap_set(map, i + 13, true);
sparsemap_set(map, i + 13);
}
assert_true(sparsemap_count(map) == 512);
@ -577,31 +577,31 @@ test_api_get_start_offset(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
sparsemap_set(map, 0, true);
sparsemap_set(map, 0);
assert_true(sparsemap_get_starting_offset(map) == 0);
sparsemap_clear(map);
sparsemap_set(map, 1, true);
sparsemap_set(map, 1);
assert_true(sparsemap_get_starting_offset(map) == 1);
sparsemap_clear(map);
sparsemap_set(map, 1025, true);
sparsemap_set(map, 1025);
assert_true(sparsemap_get_starting_offset(map) == 1025);
sparsemap_clear(map);
for (int i = 0; i < 1000; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
assert_true(sparsemap_get_starting_offset(map) == 0);
sparsemap_clear(map);
for (int i = 0; i < 1000; i++) {
sparsemap_set(map, i + 1024, true);
sparsemap_set(map, i + 1024);
}
assert_true(sparsemap_get_starting_offset(map) == 1024);
sparsemap_clear(map);
sparsemap_set(map, 13012, true);
sparsemap_set(map, 13012);
assert_true(sparsemap_get_starting_offset(map) == 13012);
return MUNIT_OK;
@ -634,20 +634,20 @@ test_api_get_end_offset(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
sparsemap_set(map, 0, true);
sparsemap_set(map, 0);
assert_true(sparsemap_get_ending_offset(map) == 0);
sparsemap_clear(map);
sparsemap_set(map, 0, true);
sparsemap_set(map, 1, true);
sparsemap_set(map, 0);
sparsemap_set(map, 1);
assert_true(sparsemap_get_ending_offset(map) == 1);
sparsemap_clear(map);
sparsemap_set(map, 0, true);
sparsemap_set(map, 67, true);
sparsemap_set(map, 1002, true);
sparsemap_set(map, 3087, true);
sparsemap_set(map, 13012, true);
sparsemap_set(map, 0);
sparsemap_set(map, 67);
sparsemap_set(map, 1002);
sparsemap_set(map, 3087);
sparsemap_set(map, 13012);
assert_true(sparsemap_get_ending_offset(map) == 13012);
return MUNIT_OK;
@ -676,9 +676,9 @@ test_api_get_start_offset_roll(const MunitParameter params[], void *data)
(void)params;
for (sparsemap_idx_t i = 0; i < 10 * 2048; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
if (i > 2047) {
sparsemap_set(map, i - 2048, false);
sparsemap_unset(map, i - 2048);
assert_true(sparsemap_get_starting_offset(map) == i - 2047);
// printf("%d\t%d\t%zu\n", i, i - 2047, sparsemap_get_starting_offset(map));
}
@ -761,7 +761,7 @@ test_api_split(const MunitParameter params[], void *data)
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);
assert_true(sparsemap_set(map, i + seg) == i + seg);
}
for (sparsemap_idx_t i = 0; i < 1024; i++) {
assert_true(sparsemap_is_set(map, i + seg));
@ -785,7 +785,7 @@ test_api_split(const MunitParameter params[], void *data)
}
for (sparsemap_idx_t i = 0; i < 100; i++) {
assert_true(sparsemap_set(map, i, true) == i);
assert_true(sparsemap_set(map, i) == i);
}
for (sparsemap_idx_t i = 0; i < 100; i++) {
assert_true(sparsemap_is_set(map, i));
@ -808,7 +808,7 @@ test_api_split(const MunitParameter params[], void *data)
sparsemap_init(&portion, buf, 1024);
for (sparsemap_idx_t i = 0; i < 13; i++) {
assert_true(sparsemap_set(map, i + 24, true) == i + 24);
assert_true(sparsemap_set(map, i + 24) == i + 24);
}
offset = sparsemap_split(map, SPARSEMAP_IDX_MAX, &portion);
@ -859,7 +859,7 @@ test_api_merge(const MunitParameter params[], void *data)
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);
sparsemap_merge(map, other);
assert_true(sparsemap_is_set(other, 0));
assert_true(sparsemap_is_set(map, 0));
@ -867,32 +867,32 @@ test_api_merge(const MunitParameter params[], void *data)
sparsemap_clear(other);
// Merge two maps with the same single bit set.
sparsemap_set(map, 0, true);
sparsemap_set(other, 0, true);
sparsemap_set(map, 0);
sparsemap_set(other, 0);
sparsemap_merge(map, other);
assert_true(sparsemap_is_set(map, 0));
sparsemap_clear(map);
sparsemap_clear(other);
// Merge an empty map with one that has the first bit set.
sparsemap_set(map, 0, true);
sparsemap_set(map, 0);
sparsemap_merge(map, other);
assert_true(sparsemap_is_set(map, 0));
sparsemap_clear(map);
sparsemap_clear(other);
sparsemap_set(other, 2049, true);
sparsemap_set(other, 2049);
sparsemap_merge(map, other);
assert_true(sparsemap_is_set(map, 2049));
sparsemap_clear(map);
sparsemap_clear(other);
sparsemap_set(other, 1, true);
sparsemap_set(other, 2049, true);
sparsemap_set(map, 2050, true);
sparsemap_set(other, 4097, true);
sparsemap_set(map, 6113, true);
sparsemap_set(other, 8193, true);
sparsemap_set(other, 1);
sparsemap_set(other, 2049);
sparsemap_set(map, 2050);
sparsemap_set(other, 4097);
sparsemap_set(map, 6113);
sparsemap_set(other, 8193);
sparsemap_merge(map, other);
assert_true(sparsemap_is_set(map, 1));
assert_true(sparsemap_is_set(map, 2049));
@ -909,11 +909,11 @@ test_api_merge(const MunitParameter params[], void *data)
sparsemap_clear(map);
sparsemap_clear(other);
sparsemap_set(map, 0, true);
sparsemap_set(map, 2048, true);
sparsemap_set(map, 8193, true);
sparsemap_set(map, 0);
sparsemap_set(map, 2048);
sparsemap_set(map, 8193);
for (int i = 2049; i < 4096; i++) {
sparsemap_set(other, i, true);
sparsemap_set(other, i);
}
sparsemap_merge(map, other);
assert(sparsemap_is_set(map, 0));
@ -926,7 +926,7 @@ test_api_merge(const MunitParameter params[], void *data)
sparsemap_clear(other);
for (int i = 2049; i < 4096; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
sparsemap_split(map, 2051, other);
for (int i = 2049; i < 4096; i++) {
@ -1053,9 +1053,9 @@ test_api_select_neg(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
sparsemap_set(map, 42, true);
sparsemap_set(map, 420, true);
sparsemap_set(map, 4200, true);
sparsemap_set(map, 42);
sparsemap_set(map, 420);
sparsemap_set(map, 4200);
f = sparsemap_select(map, 0, false);
assert_true(f == 0);
@ -1100,7 +1100,7 @@ test_api_rank_true(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
for (int i = 0; i < 10; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
/* rank() is also 0-based, for consistency (and confusion sake); consider the
range as [start, end] of [0, 9] counts the bits set in the first 10
@ -1114,10 +1114,10 @@ test_api_rank_true(const MunitParameter params[], void *data)
sparsemap_clear(map);
for (int i = 0; i < 10000; i++) {
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
sparsemap_idx_t hole = 4999;
sparsemap_set(map, hole, false);
sparsemap_unset(map, hole);
for (size_t i = 0; i < 10000; i++) {
for (size_t j = i; j < 10000; j++) {
size_t amt = (i > j) ? 0 : j - i + 1 - ((hole >= i && j >= hole) ? 1 : 0);
@ -1167,7 +1167,7 @@ test_api_rank_false(const MunitParameter params[], void *data)
// One chunk means not so empty now!
sparsemap_idx_t hole = 4999;
sparsemap_set(map, hole, true);
sparsemap_set(map, hole);
for (size_t i = 0; i < 10000; i++) {
for (size_t j = i; j < 10000; j++) {
int amt = (i > j) ? 0 : j - i + 1 - ((hole >= i && j >= hole) ? 1 : 0);
@ -1177,8 +1177,8 @@ test_api_rank_false(const MunitParameter params[], void *data)
}
sparsemap_clear(map);
sparsemap_set(map, 1, true);
sparsemap_set(map, 11, true);
sparsemap_set(map, 1);
sparsemap_set(map, 11);
r = sparsemap_rank(map, 0, 11, false);
assert_true(r == 10);
@ -1467,7 +1467,7 @@ test_scale_alternating(const MunitParameter params[], void *data)
for (sparsemap_idx_t i = 0; i < (1000 * 8192); i++) {
if (i % 2) {
if (sparsemap_set(map, i, true) != i) {
if (sparsemap_set(map, i) != i) {
// printf("%zu\n", i);
break;
}
@ -1523,7 +1523,7 @@ test_scale_spans_come_spans_go(const MunitParameter params[], void *data)
assert_true(sparsemap_is_set(map, j) == true);
}
for (int j = b; j < s; j++) {
sparsemap_set(map, j, false);
sparsemap_unset(map, j);
}
for (int j = b; j < s; j++) {
assert_true(sparsemap_is_set(map, j) == false);
@ -1575,7 +1575,7 @@ 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);
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
return MUNIT_OK;
@ -1619,7 +1619,7 @@ 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);
sparsemap_set(map, i, true);
sparsemap_set(map, i);
}
return MUNIT_OK;