Adding bitset checkpoint
This commit is contained in:
1 parent
53f6202709
commit
7ad2462254
4 files changed
+869
No files matched your search
@@ -0,0 +1,412 @@
|
||||
/**
|
||||
* bitset.h
|
||||
*
|
||||
* Creation Date: 30/04/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* BitSet
|
||||
*
|
||||
* A BitSet is a dynamic array that stores bits. Each bit can be individually
|
||||
* handled and perform all CRUD operations.
|
||||
*/
|
||||
|
||||
#ifndef CMC_BITSET_H
|
||||
#define CMC_BITSET_H
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Core functionalities of the C Macro Collections Library
|
||||
* ------------------------------------------------------------------------- */
|
||||
#include "../cor/core.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* BitSet specific
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* Defines the underlaying data type for the bitset array */
|
||||
/* Possible values: uint64_t, uint32_t, uint16_t, uint8_t, size_t */
|
||||
typedef uint32_t cmc_bitset_word;
|
||||
|
||||
/* to_string format */
|
||||
static const char *cmc_string_fmt_bitset = "struct %s<%s> "
|
||||
"at %p { "
|
||||
"buffer:%p, "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"flag:%d, "
|
||||
"alloc:%p, "
|
||||
"callbacks:%p }";
|
||||
|
||||
#define CMC_GENERATE_BITSET(PFX, SNAME) \
|
||||
CMC_GENERATE_BITSET_HEADER(PFX, SNAME) \
|
||||
CMC_GENERATE_BITSET_SOURCE(PFX, SNAME)
|
||||
|
||||
#define CMC_WRAPGEN_BITSET_HEADER(PFX, SNAME, K, V) \
|
||||
CMC_GENERATE_BITSET_HEADER(PFX, SNAME)
|
||||
|
||||
#define CMC_WRAPGEN_BITSET_SOURCE(PFX, SNAME, K, V) \
|
||||
CMC_GENERATE_BITSET_SOURCE(PFX, SNAME)
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Header
|
||||
* ------------------------------------------------------------------------- */
|
||||
#define CMC_GENERATE_BITSET_HEADER(PFX, SNAME) \
|
||||
\
|
||||
/* BitSet Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Dynamic Array of Bits */ \
|
||||
cmc_bitset_word *buffer; \
|
||||
\
|
||||
/* Current array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks *callbacks; \
|
||||
}; \
|
||||
\
|
||||
/* BitSet Iterator */ \
|
||||
struct SNAME##_iter \
|
||||
{ \
|
||||
/* Target bitset */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
cmc_bitset_word cursor; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *PFX##_new(size_t n_bits); \
|
||||
struct SNAME *PFX##_new_custom(size_t n_bits, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks *callbacks); \
|
||||
struct SNAME PFX##_init(size_t n_bits); \
|
||||
struct SNAME PFX##_init_custom(size_t n_bits, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks *callbacks); \
|
||||
void PFX##_free(struct SNAME *_bitset_); \
|
||||
void PFX##_release(struct SNAME _bitset_); \
|
||||
void PFX##_customize(struct SNAME *_bitset_, struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks *callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool PFX##_set(struct SNAME *_bitset_, size_t bit_index); \
|
||||
bool PFX##_set_range(struct SNAME *_bitset_, size_t from, size_t to); \
|
||||
bool PFX##_clear(struct SNAME *_bitset_, size_t bit_index); \
|
||||
bool PFX##_clear_range(struct SNAME *_bitset_, size_t from, size_t to); \
|
||||
bool PFX##_flip(struct SNAME *_bitset_, size_t bit_index); \
|
||||
bool PFX##_flip_range(struct SNAME *_bitset_, size_t from, size_t to); \
|
||||
bool PFX##_put(struct SNAME *_bitset_, size_t bit_index); \
|
||||
bool PFX##_put_range(struct SNAME *_bitset_, size_t from, size_t to); \
|
||||
bool PFX##_fill(struct SNAME *_bitset_); \
|
||||
bool PFX##_empty(struct SNAME *_bitset_); \
|
||||
/* Element Access */ \
|
||||
bool PFX##_get(struct SNAME *_bitset_, size_t bit_index); \
|
||||
\
|
||||
/* Collection State */ \
|
||||
\
|
||||
/* Collection Utility */ \
|
||||
bool PFX##_resize(struct SNAME *_bitset_, size_t n_bits); \
|
||||
\
|
||||
/* Utility Methods */ \
|
||||
/* Translates a bit index to a word index */ \
|
||||
static inline cmc_bitset_word PFX##_bit_to_index(cmc_bitset_word idx) \
|
||||
{ \
|
||||
/* Calculate how many shifts based on the size of cmc_bitset_word */ \
|
||||
static const cmc_bitset_word shift = \
|
||||
((sizeof(cmc_bitset_word) * 8) >> 6) > 0 \
|
||||
? 6 \
|
||||
: ((sizeof(cmc_bitset_word) * 8) >> 5) > 0 \
|
||||
? 5 \
|
||||
: ((sizeof(cmc_bitset_word) * 8) >> 4) > 0 ? 4 : 3; \
|
||||
\
|
||||
return idx >> shift; \
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Source
|
||||
* ------------------------------------------------------------------------- */
|
||||
#define CMC_GENERATE_BITSET_SOURCE(PFX, SNAME) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
bool PFX##_impl_resize(struct SNAME *_bitset_, size_t n_bits, \
|
||||
bool do_resize); \
|
||||
\
|
||||
struct SNAME *PFX##_new(size_t n_bits) \
|
||||
{ \
|
||||
return PFX##_new_custom(n_bits, NULL, NULL); \
|
||||
} \
|
||||
\
|
||||
struct SNAME *PFX##_new_custom(size_t n_bits, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks *callbacks) \
|
||||
{ \
|
||||
if (n_bits < 1) \
|
||||
return NULL; \
|
||||
\
|
||||
if (!alloc) \
|
||||
alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
size_t capacity = PFX##_bit_to_index(n_bits - 1) + 1; \
|
||||
\
|
||||
struct SNAME *_bitset_ = alloc->malloc(sizeof(struct SNAME)); \
|
||||
\
|
||||
if (!_bitset_) \
|
||||
return NULL; \
|
||||
\
|
||||
_bitset_->buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word)); \
|
||||
\
|
||||
if (!_bitset_->buffer) \
|
||||
{ \
|
||||
alloc->free(_bitset_); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
_bitset_->capacity = capacity; \
|
||||
_bitset_->flag = cmc_flags.OK; \
|
||||
_bitset_->alloc = alloc; \
|
||||
_bitset_->callbacks = callbacks; \
|
||||
\
|
||||
return _bitset_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME PFX##_init(size_t n_bits) \
|
||||
{ \
|
||||
return PFX##_init_custom(n_bits, NULL, NULL); \
|
||||
} \
|
||||
\
|
||||
struct SNAME PFX##_init_custom(size_t n_bits, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks *callbacks) \
|
||||
{ \
|
||||
struct SNAME _bitset_ = { 0 }; \
|
||||
\
|
||||
if (n_bits < 1) \
|
||||
return _bitset_; \
|
||||
\
|
||||
if (!alloc) \
|
||||
alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
size_t capacity = PFX##_bit_to_index(n_bits - 1) + 1; \
|
||||
\
|
||||
_bitset_.buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word)); \
|
||||
\
|
||||
if (!_bitset_.buffer) \
|
||||
return _bitset_; \
|
||||
\
|
||||
_bitset_.capacity = capacity; \
|
||||
_bitset_.flag = cmc_flags.OK; \
|
||||
_bitset_.alloc = alloc; \
|
||||
_bitset_.callbacks = callbacks; \
|
||||
\
|
||||
return _bitset_; \
|
||||
} \
|
||||
\
|
||||
void PFX##_free(struct SNAME *_bitset_) \
|
||||
{ \
|
||||
free(_bitset_->buffer); \
|
||||
free(_bitset_); \
|
||||
} \
|
||||
\
|
||||
void PFX##_release(struct SNAME _bitset_) \
|
||||
{ \
|
||||
free(_bitset_.buffer); \
|
||||
} \
|
||||
\
|
||||
void PFX##_customize(struct SNAME *_bitset_, struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks *callbacks) \
|
||||
{ \
|
||||
if (!alloc) \
|
||||
_bitset_->alloc = &cmc_alloc_node_default; \
|
||||
else \
|
||||
_bitset_->alloc = alloc; \
|
||||
\
|
||||
_bitset_->callbacks = callbacks; \
|
||||
\
|
||||
_bitset_->flag = cmc_flags.OK; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_set(struct SNAME *_bitset_, size_t bit_index) \
|
||||
{ \
|
||||
if (!PFX##_impl_resize(_bitset_, bit_index + 1, false)) \
|
||||
return false; \
|
||||
\
|
||||
/* How many bits in a word */ \
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT; \
|
||||
\
|
||||
size_t i = PFX##_bit_to_index(bit_index); \
|
||||
\
|
||||
_bitset_->buffer[i] |= ((cmc_bitset_word)1) << (bit_index % bits); \
|
||||
\
|
||||
_bitset_->flag = cmc_flags.OK; \
|
||||
\
|
||||
if (_bitset_->callbacks && _bitset_->callbacks->create) \
|
||||
_bitset_->callbacks->create(); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_set_range(struct SNAME *_bitset_, size_t from, size_t to) \
|
||||
{ \
|
||||
if (to < from) \
|
||||
{ \
|
||||
_bitset_->flag = cmc_flags.INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (!PFX##_impl_resize(_bitset_, to + 1, false)) \
|
||||
return false; \
|
||||
\
|
||||
size_t start_index = PFX##_bit_to_index(from); \
|
||||
size_t end_index = PFX##_bit_to_index(to); \
|
||||
\
|
||||
/* How many bits in a word */ \
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT; \
|
||||
\
|
||||
/* 1111 ... 1111 */ \
|
||||
const cmc_bitset_word ones = ~((cmc_bitset_word)0); \
|
||||
\
|
||||
cmc_bitset_word shift_start = from % bits; \
|
||||
cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; \
|
||||
\
|
||||
cmc_bitset_word start_mask = ones << shift_start; \
|
||||
cmc_bitset_word end_mask = ones >> shift_end; \
|
||||
\
|
||||
if (start_index == end_index) \
|
||||
{ \
|
||||
_bitset_->buffer[end_index] |= (start_mask & end_mask); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_bitset_->buffer[start_index] |= start_mask; \
|
||||
\
|
||||
for (size_t i = start_index + 1; i < end_index; i++) \
|
||||
_bitset_->buffer[i] |= ~((cmc_bitset_word)0); \
|
||||
\
|
||||
_bitset_->buffer[end_index] |= end_mask; \
|
||||
} \
|
||||
\
|
||||
_bitset_->flag = cmc_flags.OK; \
|
||||
\
|
||||
if (_bitset_->callbacks && _bitset_->callbacks->create) \
|
||||
_bitset_->callbacks->create(); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_clear(struct SNAME *_bitset_, size_t bit_index) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_clear_range(struct SNAME *_bitset_, size_t from, size_t to) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_flip(struct SNAME *_bitset_, size_t bit_index) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_flip_range(struct SNAME *_bitset_, size_t from, size_t to) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_put(struct SNAME *_bitset_, size_t bit_index) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_put_range(struct SNAME *_bitset_, size_t from, size_t to) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_fill(struct SNAME *_bitset_) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_empty(struct SNAME *_bitset_) \
|
||||
{ \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool PFX##_get(struct SNAME *_bitset_, size_t bit_index) \
|
||||
{ \
|
||||
/* How many bits in a word */ \
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT; \
|
||||
\
|
||||
cmc_bitset_word w = _bitset_->buffer[PFX##_bit_to_index(bit_index)]; \
|
||||
\
|
||||
return w & ((cmc_bitset_word)1 << (bit_index % bits)); \
|
||||
} \
|
||||
\
|
||||
bool PFX##_resize(struct SNAME *_bitset_, size_t n_bits) \
|
||||
{ \
|
||||
return PFX##_impl_resize(_bitset_, n_bits, true); \
|
||||
} \
|
||||
\
|
||||
/* When do_resize is false, then we just want to assure that the bitset */ \
|
||||
/* can accommodate n_bits */ \
|
||||
bool PFX##_impl_resize(struct SNAME *_bitset_, size_t n_bits, \
|
||||
bool do_resize) \
|
||||
{ \
|
||||
if (n_bits == 0) \
|
||||
{ \
|
||||
_bitset_->flag = cmc_flags.INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
/* -1 because n_bits is 1-based and we need to pass a 0-based index */ \
|
||||
/* +1 to have a 1-based result */ \
|
||||
size_t words = PFX##_bit_to_index(n_bits - 1) + 1; \
|
||||
\
|
||||
/* Be sure we are not always shrinking when we just want to make */ \
|
||||
/* sure that we have enough size for n_bits */ \
|
||||
if (!do_resize && words <= _bitset_->capacity) \
|
||||
return true; \
|
||||
\
|
||||
cmc_bitset_word *new_buffer = \
|
||||
realloc(_bitset_->buffer, words * sizeof(cmc_bitset_word)); \
|
||||
\
|
||||
if (!new_buffer) \
|
||||
{ \
|
||||
_bitset_->flag = cmc_flags.ALLOC; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
_bitset_->buffer = new_buffer; \
|
||||
\
|
||||
/* Make new bits be all zeroes */ \
|
||||
if (_bitset_->capacity < words) \
|
||||
memset(_bitset_->buffer + _bitset_->capacity, 0, \
|
||||
(words - _bitset_->capacity) * sizeof(cmc_bitset_word)); \
|
||||
\
|
||||
_bitset_->capacity = words; \
|
||||
\
|
||||
if (_bitset_->callbacks && _bitset_->callbacks->resize) \
|
||||
_bitset_->callbacks->resize(); \
|
||||
\
|
||||
_bitset_->flag = cmc_flags.OK; \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_BITSET_H */
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "utl/timer.h"
|
||||
|
||||
#include "unt/bidimap.c"
|
||||
#include "unt/bitset.c"
|
||||
#include "unt/deque.c"
|
||||
#include "unt/hashmap.c"
|
||||
#include "unt/hashset.c"
|
||||
@@ -47,6 +48,8 @@ int main(void)
|
||||
uintmax_t tests = 0, units = 0;
|
||||
|
||||
cmc_run(BidiMap, units, tests);
|
||||
cmc_run(BitSet, units, tests);
|
||||
cmc_run(BitSetIter, units, tests);
|
||||
cmc_run(Deque, units, tests);
|
||||
cmc_run(DequeIter, units, tests);
|
||||
cmc_run(HashMap, units, tests);
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
#include "cmc/bitset.h"
|
||||
|
||||
struct bitset
|
||||
{
|
||||
cmc_bitset_word *buffer;
|
||||
size_t capacity;
|
||||
int flag;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct bitset_iter
|
||||
{
|
||||
struct bitset *target;
|
||||
cmc_bitset_word cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct bitset *bs_new(size_t n_bits);
|
||||
struct bitset *bs_new_custom(size_t n_bits, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
struct bitset bs_init(size_t n_bits);
|
||||
struct bitset bs_init_custom(size_t n_bits, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void bs_free(struct bitset *_bitset_);
|
||||
void bs_release(struct bitset _bitset_);
|
||||
void bs_customize(struct bitset *_bitset_, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
_Bool bs_set(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_set_range(struct bitset *_bitset_, size_t from, size_t to);
|
||||
_Bool bs_clear(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_clear_range(struct bitset *_bitset_, size_t from, size_t to);
|
||||
_Bool bs_flip(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_flip_range(struct bitset *_bitset_, size_t from, size_t to);
|
||||
_Bool bs_put(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_put_range(struct bitset *_bitset_, size_t from, size_t to);
|
||||
_Bool bs_fill(struct bitset *_bitset_);
|
||||
_Bool bs_empty(struct bitset *_bitset_);
|
||||
_Bool bs_get(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_resize(struct bitset *_bitset_, size_t n_bits);
|
||||
static inline cmc_bitset_word bs_bit_to_index(cmc_bitset_word idx)
|
||||
{
|
||||
static const cmc_bitset_word shift =
|
||||
((sizeof(cmc_bitset_word) * 8) >> 6) > 0
|
||||
? 6
|
||||
: ((sizeof(cmc_bitset_word) * 8) >> 5) > 0
|
||||
? 5
|
||||
: ((sizeof(cmc_bitset_word) * 8) >> 4) > 0 ? 4 : 3;
|
||||
return idx >> shift;
|
||||
}
|
||||
_Bool bs_impl_resize(struct bitset *_bitset_, size_t n_bits, _Bool do_resize);
|
||||
struct bitset *bs_new(size_t n_bits)
|
||||
{
|
||||
return bs_new_custom(n_bits, ((void *)0), ((void *)0));
|
||||
}
|
||||
struct bitset *bs_new_custom(size_t n_bits, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks)
|
||||
{
|
||||
if (n_bits < 1)
|
||||
return ((void *)0);
|
||||
if (!alloc)
|
||||
alloc = &cmc_alloc_node_default;
|
||||
size_t capacity = bs_bit_to_index(n_bits - 1) + 1;
|
||||
struct bitset *_bitset_ = alloc->malloc(sizeof(struct bitset));
|
||||
if (!_bitset_)
|
||||
return ((void *)0);
|
||||
_bitset_->buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word));
|
||||
if (!_bitset_->buffer)
|
||||
{
|
||||
alloc->free(_bitset_);
|
||||
return ((void *)0);
|
||||
}
|
||||
_bitset_->capacity = capacity;
|
||||
_bitset_->flag = cmc_flags.OK;
|
||||
_bitset_->alloc = alloc;
|
||||
_bitset_->callbacks = callbacks;
|
||||
return _bitset_;
|
||||
}
|
||||
struct bitset bs_init(size_t n_bits)
|
||||
{
|
||||
return bs_init_custom(n_bits, ((void *)0), ((void *)0));
|
||||
}
|
||||
struct bitset bs_init_custom(size_t n_bits, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks)
|
||||
{
|
||||
struct bitset _bitset_ = { 0 };
|
||||
if (n_bits < 1)
|
||||
return _bitset_;
|
||||
if (!alloc)
|
||||
alloc = &cmc_alloc_node_default;
|
||||
size_t capacity = bs_bit_to_index(n_bits - 1) + 1;
|
||||
_bitset_.buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word));
|
||||
if (!_bitset_.buffer)
|
||||
return _bitset_;
|
||||
_bitset_.capacity = capacity;
|
||||
_bitset_.flag = cmc_flags.OK;
|
||||
_bitset_.alloc = alloc;
|
||||
_bitset_.callbacks = callbacks;
|
||||
return _bitset_;
|
||||
}
|
||||
void bs_free(struct bitset *_bitset_)
|
||||
{
|
||||
free(_bitset_->buffer);
|
||||
free(_bitset_);
|
||||
}
|
||||
void bs_release(struct bitset _bitset_)
|
||||
{
|
||||
free(_bitset_.buffer);
|
||||
}
|
||||
void bs_customize(struct bitset *_bitset_, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks)
|
||||
{
|
||||
if (!alloc)
|
||||
_bitset_->alloc = &cmc_alloc_node_default;
|
||||
else
|
||||
_bitset_->alloc = alloc;
|
||||
_bitset_->callbacks = callbacks;
|
||||
_bitset_->flag = cmc_flags.OK;
|
||||
}
|
||||
_Bool bs_set(struct bitset *_bitset_, size_t bit_index)
|
||||
{
|
||||
if (!bs_impl_resize(_bitset_, bit_index + 1, 0))
|
||||
return 0;
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8;
|
||||
size_t i = bs_bit_to_index(bit_index);
|
||||
_bitset_->buffer[i] |= ((cmc_bitset_word)1) << (bit_index % bits);
|
||||
_bitset_->flag = cmc_flags.OK;
|
||||
if (_bitset_->callbacks && _bitset_->callbacks->create)
|
||||
_bitset_->callbacks->create();
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_set_range(struct bitset *_bitset_, size_t from, size_t to)
|
||||
{
|
||||
if (to < from)
|
||||
{
|
||||
_bitset_->flag = cmc_flags.INVALID;
|
||||
return 0;
|
||||
}
|
||||
if (!bs_impl_resize(_bitset_, to + 1, 0))
|
||||
return 0;
|
||||
size_t start_index = bs_bit_to_index(from);
|
||||
size_t end_index = bs_bit_to_index(to);
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8;
|
||||
const cmc_bitset_word ones = ~((cmc_bitset_word)0);
|
||||
cmc_bitset_word shift_start = from % bits;
|
||||
cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits;
|
||||
cmc_bitset_word start_mask = ones << shift_start;
|
||||
cmc_bitset_word end_mask = ones >> shift_end;
|
||||
if (start_index == end_index)
|
||||
{
|
||||
_bitset_->buffer[end_index] |= (start_mask & end_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
_bitset_->buffer[start_index] |= start_mask;
|
||||
for (size_t i = start_index + 1; i < end_index; i++)
|
||||
_bitset_->buffer[i] |= ~((cmc_bitset_word)0);
|
||||
_bitset_->buffer[end_index] |= end_mask;
|
||||
}
|
||||
_bitset_->flag = cmc_flags.OK;
|
||||
if (_bitset_->callbacks && _bitset_->callbacks->create)
|
||||
_bitset_->callbacks->create();
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_clear(struct bitset *_bitset_, size_t bit_index)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_clear_range(struct bitset *_bitset_, size_t from, size_t to)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_flip(struct bitset *_bitset_, size_t bit_index)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_flip_range(struct bitset *_bitset_, size_t from, size_t to)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_put(struct bitset *_bitset_, size_t bit_index)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_put_range(struct bitset *_bitset_, size_t from, size_t to)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_fill(struct bitset *_bitset_)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_empty(struct bitset *_bitset_)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
_Bool bs_get(struct bitset *_bitset_, size_t bit_index)
|
||||
{
|
||||
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8;
|
||||
cmc_bitset_word w = _bitset_->buffer[bs_bit_to_index(bit_index)];
|
||||
return w & ((cmc_bitset_word)1 << (bit_index % bits));
|
||||
}
|
||||
_Bool bs_resize(struct bitset *_bitset_, size_t n_bits)
|
||||
{
|
||||
return bs_impl_resize(_bitset_, n_bits, 1);
|
||||
}
|
||||
_Bool bs_impl_resize(struct bitset *_bitset_, size_t n_bits, _Bool do_resize)
|
||||
{
|
||||
if (n_bits == 0)
|
||||
{
|
||||
_bitset_->flag = cmc_flags.INVALID;
|
||||
return 0;
|
||||
}
|
||||
size_t words = bs_bit_to_index(n_bits - 1) + 1;
|
||||
if (!do_resize && words <= _bitset_->capacity)
|
||||
return 1;
|
||||
cmc_bitset_word *new_buffer =
|
||||
realloc(_bitset_->buffer, words * sizeof(cmc_bitset_word));
|
||||
if (!new_buffer)
|
||||
{
|
||||
_bitset_->flag = cmc_flags.ALLOC;
|
||||
return 0;
|
||||
}
|
||||
_bitset_->buffer = new_buffer;
|
||||
if (_bitset_->capacity < words)
|
||||
memset(_bitset_->buffer + _bitset_->capacity, 0,
|
||||
(words - _bitset_->capacity) * sizeof(cmc_bitset_word));
|
||||
_bitset_->capacity = words;
|
||||
if (_bitset_->callbacks && _bitset_->callbacks->resize)
|
||||
_bitset_->callbacks->resize();
|
||||
_bitset_->flag = cmc_flags.OK;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
#include "utl.c"
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
|
||||
#include "../src/bitset.c"
|
||||
|
||||
struct cmc_alloc_node *bs_alloc_node = &(struct cmc_alloc_node){
|
||||
.malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free
|
||||
};
|
||||
|
||||
CMC_CREATE_UNIT(BitSet, true, {
|
||||
const size_t word_bytes = sizeof(cmc_bitset_word);
|
||||
const size_t word_bits = sizeof(cmc_bitset_word) * CHAR_BIT;
|
||||
|
||||
CMC_CREATE_TEST(PFX##_new(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_not_equals(ptr, NULL, bs->buffer);
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(63) + 1, bs->capacity);
|
||||
cmc_assert_equals(ptr, &cmc_alloc_node_default, bs->alloc);
|
||||
cmc_assert_equals(ptr, NULL, bs->callbacks);
|
||||
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new(129);
|
||||
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(128) + 1, bs->capacity);
|
||||
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_new_custom(), {
|
||||
struct bitset *bs = bs_new_custom(64, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert_not_equals(ptr, NULL, bs->buffer);
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(63) + 1, bs->capacity);
|
||||
cmc_assert_equals(ptr, bs_alloc_node, bs->alloc);
|
||||
cmc_assert_equals(ptr, callbacks, bs->callbacks);
|
||||
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new_custom(129, NULL, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(128) + 1, bs->capacity);
|
||||
bs_free(bs);
|
||||
|
||||
bs = bs_new_custom(0, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_init(), {
|
||||
struct bitset bs = bs_init(64);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs.buffer);
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(63) + 1, bs.capacity);
|
||||
cmc_assert_equals(ptr, &cmc_alloc_node_default, bs.alloc);
|
||||
cmc_assert_equals(ptr, NULL, bs.callbacks);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init(129);
|
||||
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(128) + 1, bs.capacity);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs.buffer);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_init_custom(), {
|
||||
struct bitset bs = bs_init_custom(64, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs.buffer);
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(63) + 1, bs.capacity);
|
||||
cmc_assert_equals(ptr, bs_alloc_node, bs.alloc);
|
||||
cmc_assert_equals(ptr, callbacks, bs.callbacks);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init_custom(129, NULL, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, bs_bit_to_index(128) + 1, bs.capacity);
|
||||
|
||||
bs_release(bs);
|
||||
|
||||
bs = bs_init_custom(0, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, bs.buffer);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_customize(), {
|
||||
struct bitset *bs = bs_new(word_bits);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
|
||||
bs->flag = cmc_flags.ERROR;
|
||||
bs_customize(bs, bs_alloc_node, callbacks);
|
||||
|
||||
cmc_assert_equals(ptr, bs_alloc_node, bs->alloc);
|
||||
cmc_assert_equals(ptr, callbacks, bs->callbacks);
|
||||
cmc_assert_equals(int32_t, cmc_flags.OK, bs->flag);
|
||||
|
||||
bs->flag = cmc_flags.ERROR;
|
||||
bs_customize(bs, NULL, NULL);
|
||||
|
||||
cmc_assert_equals(ptr, &cmc_alloc_node_default, bs->alloc);
|
||||
cmc_assert_equals(ptr, NULL, bs->callbacks);
|
||||
cmc_assert_equals(int32_t, cmc_flags.OK, bs->flag);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_set(), {
|
||||
struct bitset *bs = bs_new(word_bits);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert(0 == bs->buffer[0]);
|
||||
|
||||
bs->flag = cmc_flags.ERROR;
|
||||
cmc_assert(bs_set(bs, 0));
|
||||
cmc_assert(1 == bs->buffer[0]);
|
||||
cmc_assert_equals(int32_t, cmc_flags.OK, bs->flag);
|
||||
|
||||
bs->buffer[0] = 0;
|
||||
|
||||
cmc_assert(bs_set(bs, word_bits - 1));
|
||||
cmc_assert(((cmc_bitset_word)1 << (word_bits - 1)) == bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_set(bs, word_bits * 8 - 1));
|
||||
cmc_assert(((cmc_bitset_word)1 << (word_bits - 1)) ==
|
||||
bs->buffer[bs_bit_to_index(word_bits * 8 - 1)]);
|
||||
|
||||
cmc_assert(bs_set(bs, word_bits * 18 - 2));
|
||||
cmc_assert(((cmc_bitset_word)1 << (word_bits - 2)) ==
|
||||
bs->buffer[bs_bit_to_index(word_bits * 18 - 2)]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_set_range(), {
|
||||
struct bitset *bs = bs_new(word_bits);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
cmc_assert(0 == bs->buffer[0]);
|
||||
|
||||
bs->flag = cmc_flags.ERROR;
|
||||
cmc_assert(bs_set_range(bs, 0, 0));
|
||||
cmc_assert_equals(uint8_t, 1, bs->buffer[0]);
|
||||
cmc_assert_equals(int32_t, cmc_flags.OK, bs->flag);
|
||||
|
||||
bs->buffer[0] = 0;
|
||||
|
||||
cmc_assert(bs_set_range(bs, 4, 7)); /* 1111 0000 */
|
||||
cmc_assert_equals(uint8_t, 240, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_set_range(bs, 2, 2)); /* 1111 0100 */
|
||||
cmc_assert_equals(uint8_t, 244, bs->buffer[0]);
|
||||
|
||||
cmc_assert(bs_set_range(bs, word_bits * 6 - 2, word_bits * 6 - 2));
|
||||
cmc_assert(((cmc_bitset_word)1 << (word_bits - 2)) ==
|
||||
bs->buffer[bs_bit_to_index(word_bits * 6 - 2)]);
|
||||
|
||||
// Make sure we have at leats word_bits * 40 slots
|
||||
bs_set(bs, word_bits * 40);
|
||||
|
||||
cmc_assert(bs_set_range(bs, word_bits * 20, word_bits * 21 - 1));
|
||||
cmc_assert((~(cmc_bitset_word)0) ==
|
||||
bs->buffer[bs_bit_to_index(word_bits * 20)]);
|
||||
|
||||
cmc_assert(0 == bs->buffer[bs_bit_to_index(word_bits * 20 - 1)]);
|
||||
cmc_assert(0 == bs->buffer[bs_bit_to_index(word_bits * 21 + 1)]);
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_clear(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
// WIP
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_get(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, bs);
|
||||
|
||||
cmc_assert(bs_set(bs, 1));
|
||||
|
||||
cmc_assert(bs_get(bs, 1));
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_resize(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
// WIP
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
});
|
||||
|
||||
CMC_CREATE_UNIT(BitSetIter, true, {
|
||||
CMC_CREATE_TEST(PFX##_iter_start(), {
|
||||
struct bitset *bs = bs_new(64);
|
||||
|
||||
// WIP
|
||||
|
||||
bs_free(bs);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user