sparsemap/examples/ex_4.c

179 lines
4.5 KiB
C
Raw Normal View History

2024-04-06 01:17:14 +00:00
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "../include/sparsemap.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
#define __diag(...) \
do { \
fprintf(stderr, "%s:%d:%s(): ", __FILE__, __LINE__, __func__); \
fprintf(stderr, __VA_ARGS__); \
} while (0)
#pragma GCC diagnostic pop
#define SEED
/* https://burtleburtle.net/bob/rand/smallprng.html */
typedef struct rnd_ctx {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
} rnd_ctx_t;
#define __rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
uint32_t
__random(rnd_ctx_t *x)
{
uint32_t e = x->a - __rot(x->b, 27);
x->a = x->b ^ __rot(x->c, 17);
x->b = x->c + x->d;
x->c = x->d + e;
x->d = e + x->a;
return x->d;
}
void
__random_seed(rnd_ctx_t *x, uint32_t seed)
{
uint32_t i;
x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
for (i = 0; i < 20; ++i) {
(void)__random(x);
}
}
void
shuffle(rnd_ctx_t *prng, int *array, size_t n)
{
size_t i, j;
if (n > 1) {
for (i = n - 1; i > 0; i--) {
j = (unsigned int)(__random(prng) % (i + 1));
// XOR swap algorithm
if (i != j) { // avoid self-swap leading to zero-ing the element
array[i] = array[i] ^ array[j];
array[j] = array[i] ^ array[j];
array[i] = array[i] ^ array[j];
}
}
}
}
bool
2024-04-06 01:42:46 +00:00
was_set(size_t bit, const int array[])
2024-04-06 01:17:14 +00:00
{
for (int i = 0; i < 1024; i++) {
2024-04-06 01:42:46 +00:00
if (array[i] == (int)bit) {
2024-04-06 01:17:14 +00:00
return true;
2024-04-06 01:42:46 +00:00
}
2024-04-06 01:17:14 +00:00
}
return false;
}
#define TEST_ARRAY_SIZE 1024
int
main(void)
{
int i = 0;
size_t rank;
rnd_ctx_t prng;
int array[TEST_ARRAY_SIZE];
// disable buffering
setbuf(stderr, 0);
// start with a 1KiB buffer, TEST_ARRAY_SIZE bits
uint8_t *buf = calloc(TEST_ARRAY_SIZE, sizeof(uint8_t));
// create the sparse bitmap
sparsemap_t *map = sparsemap(buf, sizeof(uint8_t) * TEST_ARRAY_SIZE, 0);
2024-04-06 01:53:48 +00:00
#if 0
2024-04-06 01:42:46 +00:00
for (i = 0; i < 8; i++) sparsemap_set(map, i, true);
2024-04-06 01:17:14 +00:00
rank = sparsemap_rank(map, 0, 8);
__diag("rank was %lu at offset 0\n", rank);
assert(rank == 8);
for (i = 0; i < 8; i++) {
bool set = sparsemap_is_set(map, i);
2024-04-06 01:42:46 +00:00
if (set) {
2024-04-06 01:17:14 +00:00
__diag("verified %d was set, %s\n", i,
was_set(i, array) ? "but we thought it was" : "because it wasn't");
2024-04-06 01:42:46 +00:00
} else {
2024-04-06 01:17:14 +00:00
__diag("darn, %d was not really set, %s\n", i,
was_set(i, array) ? "but we thought it was" : "because it wasn't");
2024-04-06 01:42:46 +00:00
}
2024-04-06 01:17:14 +00:00
}
__diag("and %d was %s", i, sparsemap_is_set(map, i + 1) ? "set" : "not set");
rank = sparsemap_span(map, 0, 8);
__diag("span was found at %lu\n", rank);
sparsemap_clear(map);
2024-04-06 01:42:46 +00:00
for (i = 2; i < 7; i++) sparsemap_set(map, i, true);
2024-04-06 01:17:14 +00:00
rank = sparsemap_rank(map, 0, 10);
2024-04-06 01:42:46 +00:00
__diag("rank was %lu between [0, 10]\n", rank);
assert(rank == 5);
2024-04-06 01:17:14 +00:00
sparsemap_clear(map);
2024-04-06 01:53:48 +00:00
#endif
2024-04-06 01:17:14 +00:00
2024-04-06 01:42:46 +00:00
for (i = 2049; i < 2057; i++) sparsemap_set(map, i, true);
2024-04-06 01:53:48 +00:00
rank = sparsemap_rank(map, 2049, 2058);
2024-04-06 01:17:14 +00:00
__diag("rank was %lu at offset 108\n", rank);
assert(rank == 8);
2024-04-06 01:53:48 +00:00
for (i = 2049; i < 2057; i++) {
2024-04-06 01:17:14 +00:00
bool set = sparsemap_is_set(map, i);
2024-04-06 01:42:46 +00:00
if (set) {
2024-04-06 02:02:01 +00:00
__diag("verified %d was set\n", i);
2024-04-06 01:42:46 +00:00
} else {
2024-04-06 02:02:01 +00:00
__diag("darn, %d was not really set\n", i);
2024-04-06 01:42:46 +00:00
}
2024-04-06 01:17:14 +00:00
}
__diag("and %d was %s", i, sparsemap_is_set(map, i + 1) ? "set" : "not set");
rank = sparsemap_rank(map, 2048, 2060);
__diag("rank was %lu at offset 109\n", rank);
2024-04-06 02:02:01 +00:00
//rank = sparsemap_span(map, 2048, 8);
//__diag("span was found at %lu\n", rank);
2024-04-06 01:17:14 +00:00
sparsemap_clear(map);
// seed the PRNG
#ifdef SEED
__random_seed(&prng, 8675309);
#else
__random_seed(&prng, (unsigned int)time(NULL) ^ getpid());
#endif
for (i = 0; i < TEST_ARRAY_SIZE; i++) {
2024-04-06 02:02:01 +00:00
array[i] = (int)__random(&prng) % TEST_ARRAY_SIZE + 1;
2024-04-06 01:42:46 +00:00
if (array[i] < 0) {
2024-04-06 01:17:14 +00:00
i--;
2024-04-06 01:42:46 +00:00
}
2024-04-06 01:17:14 +00:00
}
// randomize setting the bits on
shuffle(&prng, array, TEST_ARRAY_SIZE);
// set all the bits on in a random order
for (i = 0; i < TEST_ARRAY_SIZE; i++) {
//__diag("set %d\n", array[i]);
sparsemap_set(map, array[i], true);
assert(sparsemap_is_set(map, array[i]) == true);
}
2024-04-06 02:02:01 +00:00
size_t len = 6;
size_t l = sparsemap_span(map, 0, len);
__diag("found span of %d at %lu starting from 0\n", len, l);
for (i = (int)l; i < l + len; i++) {
bool set = sparsemap_is_set(map, i);
2024-04-06 01:42:46 +00:00
if (set) {
2024-04-06 02:02:01 +00:00
__diag("verified %lu was set\n", i);
2024-04-06 01:42:46 +00:00
} else {
2024-04-06 02:02:01 +00:00
__diag("darn, %lu was not really set, %s\n", i,
was_set(i, array) ? "but we thought it was" : "because it wasn't");
2024-04-06 01:42:46 +00:00
}
2024-04-06 01:17:14 +00:00
}
return 0;
}