Add comments

This commit is contained in:
Patrick Pelissier committed 2020-05-31 00:15:46 +02:00
1 parent 467acfdd10
commit 294e45c7e1
1 file changed
+88 -17
+88 -17
View File
@@ -30,9 +30,9 @@
/********************************** INTERNAL ************************************/
// Define the limb of a bitset
// Define the basic limb of a bitset
typedef uint64_t bitset_limb;
// And its size
// And its size in bits
#define BITSET_LIMB_BIT (sizeof(bitset_limb) * CHAR_BIT)
// bitset grow policy. n is limb size
@@ -45,43 +45,51 @@ typedef uint64_t bitset_limb;
#define BITSETI_FROM_ALLOC(n) ((n) * BITSET_LIMB_BIT)
// Contract of a bitset
#define BITSETI_CONTRACT(t) do { \
assert (t != NULL); \
assert (t->size <= BITSETI_FROM_ALLOC (t->alloc)); \
assert (t->alloc <= ((size_t)-1) / BITSET_LIMB_BIT); \
assert (t->size < ((size_t)-1) - BITSET_LIMB_BIT); \
assert (t->size == 0 || t->ptr != NULL); \
#define BITSETI_CONTRACT(t) do { \
assert (t != NULL); \
assert (t->size <= BITSETI_FROM_ALLOC (t->alloc)); \
assert (t->alloc <= ((size_t)-1) / BITSET_LIMB_BIT); \
assert (t->size < ((size_t)-1) - BITSET_LIMB_BIT); \
assert (t->size == 0 || t->ptr != NULL); \
assert (t->alloc == 0 || t->ptr != NULL); \
} while (0)
/********************************** EXTERNAL ************************************/
/* Define a type of variable 'bits' or array of packed booleans */
typedef struct bitset_s {
size_t size; // Size is the number of bits
size_t alloc; // Alloc is the number of allocated limbs
bitset_limb *ptr; // Pointer to the allocated limbs
} bitset_t[1];
/* Pointer to a bitset_t */
typedef struct bitset_s *bitset_ptr;
/* Constant Pointer to a bitset_t */
typedef const struct bitset_s *bitset_srcptr;
/* Iterator on a bitset */
typedef struct bitset_it_s {
size_t index; // index to the array of bit
bool value; // value used for _ref & _cref to store the value
struct bitset_s *set; // the associated bitset
} bitset_it_t[1];
/* Initialize a bitset (CONSTRUCTOR) */
static inline void
bitset_init(bitset_t t)
{
assert (t != NULL);
assert (M_POWEROF2_P(BITSET_LIMB_BIT));
M_STATIC_ASSERT (M_POWEROF2_P(BITSET_LIMB_BIT), MLIB_INTERNAL, "M*LIB: BITSET LIMB shall be a power of 2.");
t->size = 0;
t->alloc = 0;
t->ptr = NULL;
BITSETI_CONTRACT(t);
}
/* Clean a bitset */
static inline void
bitset_clean(bitset_t t)
{
@@ -89,16 +97,20 @@ bitset_clean(bitset_t t)
t->size = 0;
}
/* Clear a bitset (DESTRUCTOR) */
static inline void
bitset_clear(bitset_t t)
{
bitset_clean(t);
M_MEMORY_FREE(t->ptr);
// This is not really needed, but is safer
t->alloc = 0;
// This representation is invalid and will be detected by the contract.
// A C compiler should be able to optimize out theses initializations.
t->alloc = 1;
t->ptr = NULL;
}
/* Set a bitset to another one */
static inline void
bitset_set(bitset_t d, const bitset_t s)
{
@@ -120,6 +132,7 @@ bitset_set(bitset_t d, const bitset_t s)
BITSETI_CONTRACT(d);
}
/* Initialize & set a bitset to another one (CONSTRUCTOR) */
static inline void
bitset_init_set(bitset_t d, const bitset_t s)
{
@@ -128,6 +141,7 @@ bitset_init_set(bitset_t d, const bitset_t s)
bitset_set(d, s);
}
/* Initialize & move a bitset (CONSTRUCTOR) from another one (DESTRUCTOR) */
static inline void
bitset_init_move(bitset_t d, bitset_t s)
{
@@ -140,6 +154,7 @@ bitset_init_move(bitset_t d, bitset_t s)
BITSETI_CONTRACT(d);
}
/* Move a bitset from another one (DESTRUCTOR) */
static inline void
bitset_move(bitset_t d, bitset_t s)
{
@@ -147,6 +162,7 @@ bitset_move(bitset_t d, bitset_t s)
bitset_init_move (d, s);
}
/* Set the bit 'i' in the bitset to the value 'x' */
static inline void
bitset_set_at(bitset_t v, size_t i, bool x)
{
@@ -160,6 +176,7 @@ bitset_set_at(bitset_t v, size_t i, bool x)
BITSETI_CONTRACT (v);
}
/* Flip the bit 'i' in the bitset */
static inline void
bitset_flip_at(bitset_t v, size_t i)
{
@@ -171,11 +188,13 @@ bitset_flip_at(bitset_t v, size_t i)
BITSETI_CONTRACT (v);
}
/* Push back the boolean 'x' in the bitset (increasing the bitset) */
static inline void
bitset_push_back (bitset_t v, bool x)
{
BITSETI_CONTRACT (v);
if (v->size >= BITSETI_FROM_ALLOC (v->alloc)) {
// Compute the needed allocation.
const size_t needAlloc = BITSETI_INC_ALLOC_SIZE(v->alloc);
// Check for integer overflow
if (M_UNLIKELY (needAlloc <= v->alloc)) {
@@ -201,6 +220,7 @@ bitset_push_back (bitset_t v, bool x)
bitset_set_at (v, v->size - 1, x);
}
/* Resize the bitset to have exactly 'size' bits */
static inline void
bitset_resize (bitset_t v, size_t size)
{
@@ -210,6 +230,7 @@ bitset_resize (bitset_t v, size_t size)
M_MEMORY_FULL((size_t) -1);
return;
}
// Compute the needed allocation.
size_t newAlloc = BITSETI_TO_ALLOC (size);
if (newAlloc > v->alloc) {
bitset_limb *ptr = M_MEMORY_REALLOC (bitset_limb, v->ptr, newAlloc);
@@ -220,8 +241,8 @@ bitset_resize (bitset_t v, size_t size)
v->ptr = ptr;
v->alloc = newAlloc;
}
//FIXME: Last bit are not cleared. if new size is lower than org size
//TODO: More efficient!
//FIXME: Last bit are not cleared if new size is lower than org size. Needed?
//TODO: Implement a more efficient version when needed.
size_t i = v->size;
v->size = size;
for( ; i < size; i++)
@@ -229,6 +250,7 @@ bitset_resize (bitset_t v, size_t size)
BITSETI_CONTRACT (v);
}
/* Reserve allocation in the bitset to accomodate at least 'size' bits without reallocation */
static inline void
bitset_reserve (bitset_t v, size_t size)
{
@@ -254,8 +276,10 @@ bitset_reserve (bitset_t v, size_t size)
BITSETI_CONTRACT (v);
}
// NOTE: Interface is a little bit different:
// It doesn't return a pointer to the data, but the data itself.
/* Return the value of the boolean at index 'i'.
* NOTE: Interface is a little bit different:
* It doesn't return a pointer to the data, but the data itself.
*/
static inline bool
bitset_get(const bitset_t v, size_t i)
{
@@ -265,8 +289,11 @@ bitset_get(const bitset_t v, size_t i)
size_t index = i % BITSET_LIMB_BIT;
return ( v->ptr[offset] & (((bitset_limb)1) << index) ) != 0;
}
/* bitset_cget is the exact same service than bitset_get */
#define bitset_cget bitset_get
/* Pop back the last bit in the bitset */
static inline void
bitset_pop_back(bool *dest, bitset_t v)
{
@@ -280,6 +307,7 @@ bitset_pop_back(bool *dest, bitset_t v)
BITSETI_CONTRACT (v);
}
/* Return the front bit value in the bitset */
static inline bool
bitset_front(bitset_t v)
{
@@ -288,6 +316,7 @@ bitset_front(bitset_t v)
return bitset_get(v, 0);
}
/* Return the back bit value in the bitset */
static inline bool
bitset_back(bitset_t v)
{
@@ -296,6 +325,7 @@ bitset_back(bitset_t v)
return bitset_get(v, v->size-1);
}
/* Test if the bitset is empty (no bits stored)*/
static inline bool
bitset_empty_p(bitset_t v)
{
@@ -303,6 +333,7 @@ bitset_empty_p(bitset_t v)
return v->size == 0;
}
/* Return the number of bits of the bitset */
static inline size_t
bitset_size(bitset_t v)
{
@@ -310,6 +341,7 @@ bitset_size(bitset_t v)
return v->size;
}
/* Return the capacity in limbs of the bitset */
static inline size_t
bitset_capacity(bitset_t v)
{
@@ -317,6 +349,7 @@ bitset_capacity(bitset_t v)
return BITSETI_FROM_ALLOC (v->alloc);
}
/* Swap the bit at index i and j of the bitset */
static inline void
bitset_swap_at (bitset_t v, size_t i, size_t j)
{
@@ -329,6 +362,7 @@ bitset_swap_at (bitset_t v, size_t i, size_t j)
BITSETI_CONTRACT (v);
}
/* Swap the bitsets */
static inline void
bitset_swap (bitset_t v1, bitset_t v2)
{
@@ -339,6 +373,10 @@ bitset_swap (bitset_t v1, bitset_t v2)
M_SWAP (bitset_limb *, v1->ptr, v2->ptr);
}
/* (INTERNAL) Left shift of the bitset (ptr+size) by 1 bit,
* integrating the carry in the lowest position.
* Return the new carry.
*/
static inline bitset_limb
bitseti_lshift(bitset_limb ptr[], size_t n, bitset_limb carry)
{
@@ -350,6 +388,10 @@ bitseti_lshift(bitset_limb ptr[], size_t n, bitset_limb carry)
return carry;
}
/* (INTERNAL) Right shift of the bitset (ptr+size) by 1 bit,
* integrating the carry in the lowest position.
* Return the new carry.
*/
static inline bitset_limb
bitseti_rshift(bitset_limb ptr[], size_t n, bitset_limb carry)
{
@@ -361,6 +403,7 @@ bitseti_rshift(bitset_limb ptr[], size_t n, bitset_limb carry)
return carry;
}
/* Insert a new bit at position 'key' of value 'value' in the bitset */
static inline void
bitset_push_at(bitset_t set, size_t key, bool value)
{
@@ -384,6 +427,8 @@ bitset_push_at(bitset_t set, size_t key, bool value)
BITSETI_CONTRACT (set);
}
/* Pop a new bit at position 'key' in the bitset
* and return in *dest its value if *dest exists */
static inline void
bitset_pop_at(bool *dest, bitset_t set, size_t key)
{
@@ -407,6 +452,7 @@ bitset_pop_at(bool *dest, bitset_t set, size_t key)
BITSETI_CONTRACT (set);
}
/* Test if two bitsets are equal */
static inline bool
bitset_equal_p (const bitset_t set1, const bitset_t set2)
{
@@ -430,6 +476,7 @@ bitset_equal_p (const bitset_t set1, const bitset_t set2)
return true;
}
/* Initialize an iterator to the first bit of the biset */
static inline void
bitset_it(bitset_it_t it, bitset_t set)
{
@@ -438,6 +485,7 @@ bitset_it(bitset_it_t it, bitset_t set)
it->set = set;
}
/* Initialize an iterator to reference the same bit as the given one*/
static inline void
bitset_it_set(bitset_it_t it, const bitset_it_t itorg)
{
@@ -446,6 +494,7 @@ bitset_it_set(bitset_it_t it, const bitset_it_t itorg)
it->set = itorg->set;
}
/* Initialize an iterator to reference the last bit of the bitset*/
static inline void
bitset_it_last(bitset_it_t it, bitset_t set)
{
@@ -454,6 +503,7 @@ bitset_it_last(bitset_it_t it, bitset_t set)
it->set = set;
}
/* Initialize an iterator to reference no valid bit of the bitset*/
static inline void
bitset_it_end(bitset_it_t it, bitset_t set)
{
@@ -462,6 +512,7 @@ bitset_it_end(bitset_it_t it, bitset_t set)
it->set = set;
}
/* Test if an iterator references no valid bit of the bitset anymore */
static inline bool
bitset_end_p(const bitset_it_t it)
{
@@ -469,6 +520,7 @@ bitset_end_p(const bitset_it_t it)
return (it->index) >= (it->set->size);
}
/* Test if an iterator references the last (or end) bit of the bitset anymore */
static inline bool
bitset_last_p(const bitset_it_t it)
{
@@ -476,6 +528,7 @@ bitset_last_p(const bitset_it_t it)
return (it->index) >= (it->set->size)-1;
}
/* Test if both iterators reference the same bit */
static inline bool
bitset_it_equal_p(const bitset_it_t it1, const bitset_it_t it2)
{
@@ -483,6 +536,7 @@ bitset_it_equal_p(const bitset_it_t it1, const bitset_it_t it2)
return it1->index == it2->index && it1->set == it2->set;
}
/* Move the iterator to the next bit */
static inline void
bitset_next(bitset_it_t it)
{
@@ -490,6 +544,7 @@ bitset_next(bitset_it_t it)
it->index++;
}
/* Move the iterator to the previous bit */
static inline void
bitset_previous(bitset_it_t it)
{
@@ -498,6 +553,9 @@ bitset_previous(bitset_it_t it)
}
// There is no _ref as it is not possible to modify the value using the IT interface
/* Return a pointer to the bit referenced by the iterator
* Only one reference is possible at a time per iterator */
static inline const bool *
bitset_cref(bitset_it_t it)
{
@@ -506,6 +564,7 @@ bitset_cref(bitset_it_t it)
return &it->value;
}
/* Output the bitset as a formatted text in a FILE */
static inline void
bitset_out_str(FILE *file, const bitset_t set)
{
@@ -520,6 +579,7 @@ bitset_out_str(FILE *file, const bitset_t set)
fputc (']', file);
}
/* Input the bitset from a formatted text in a FILE */
static inline bool
bitset_in_str(bitset_t set, FILE *file)
{
@@ -538,6 +598,7 @@ bitset_in_str(bitset_t set, FILE *file)
return c == ']';
}
/* Parse the bitset from a formatted text in a C string */
static inline bool
bitset_parse_str(bitset_t set, const char str[], const char **endptr)
{
@@ -561,12 +622,15 @@ bitset_parse_str(bitset_t set, const char str[], const char **endptr)
return success;
}
/* Set the bitset from a formatted text in a C string */
static inline bool
bitset_set_str(bitset_t dest, const char str[])
{
return bitset_parse_str(dest, str, NULL);
}
/* Perform an AND operation between the bitsets,
* up to the minimum size of both bitsets */
static inline void
bitset_and(bitset_t dest, const bitset_t src)
{
@@ -585,6 +649,8 @@ bitset_and(bitset_t dest, const bitset_t src)
BITSETI_CONTRACT(dest);
}
/* Perform an OR operation between the bitsets,
* up to the minimum size of both bitsets */
static inline void
bitset_or(bitset_t dest, const bitset_t src)
{
@@ -603,6 +669,8 @@ bitset_or(bitset_t dest, const bitset_t src)
BITSETI_CONTRACT(dest);
}
/* Perform an XOR operation between the bitsets,
* up to the minimum size of both bitsets */
static inline void
bitset_xor(bitset_t dest, const bitset_t src)
{
@@ -621,6 +689,7 @@ bitset_xor(bitset_t dest, const bitset_t src)
BITSETI_CONTRACT(dest);
}
/* Perform a NOT operation of the bitset */
static inline void
bitset_not(bitset_t dest)
{
@@ -638,6 +707,7 @@ bitset_not(bitset_t dest)
BITSETI_CONTRACT(dest);
}
/* Copute a hash of the bitset */
static inline size_t
bitset_hash(const bitset_t set)
{
@@ -655,6 +725,7 @@ bitset_hash(const bitset_t set)
return M_HASH_FINAL (hash);
}
/* Count the number of leading zero */
static inline size_t
bitset_clz(const bitset_t set)
{
@@ -680,6 +751,7 @@ bitset_clz(const bitset_t set)
return s;
}
/* Oplist for a bitset */
#define BITSET_OPLIST \
(INIT(bitset_init) \
,INIT_SET(bitset_init_set) \
@@ -723,10 +795,10 @@ bitset_clz(const bitset_t set)
#endif
// NOTE: Define this function only if m-string has been included
#ifndef MSTARLIB_BITSET_STRING_H
#ifdef MSTARLIB_STRING_H
#if !defined(MSTARLIB_BITSET_STRING_H) && defined(MSTARLIB_STRING_H)
#define MSTARLIB_BITSET_STRING_H
/* Output to a string_t the formatted text representation of a bitset */
static inline void
bitset_get_str(string_t str, const bitset_t set, bool append)
{
@@ -742,4 +814,3 @@ bitset_get_str(string_t str, const bitset_t set, bool append)
}
#endif
#endif