diff options
author | David Robillard <d@drobilla.net> | 2020-12-31 15:34:15 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-12-31 15:34:15 +0100 |
commit | ed9a6e98b8e4e010117e1228333569aa31c51d9e (patch) | |
tree | 3c333f1c7ce2109222d06aa026b939e379e55b5d /src/bitset.c | |
parent | de27dcfe0bb72ef1ec937c4aaee26eef6ff7918e (diff) | |
download | zix-ed9a6e98b8e4e010117e1228333569aa31c51d9e.tar.gz zix-ed9a6e98b8e4e010117e1228333569aa31c51d9e.tar.bz2 zix-ed9a6e98b8e4e010117e1228333569aa31c51d9e.zip |
Separate source from headers
Diffstat (limited to 'src/bitset.c')
-rw-r--r-- | src/bitset.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/bitset.c b/src/bitset.c new file mode 100644 index 0000000..cf82ad0 --- /dev/null +++ b/src/bitset.c @@ -0,0 +1,124 @@ +/* + Copyright 2014-2016 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "zix/bitset.h" + +#ifdef _MSC_VER +# include <intrin.h> +#endif + +#include <string.h> + +/** Number of bits per ZixBitset element (ala CHAR_BIT). */ +#define ZIX_BITSET_ELEM_BIT (CHAR_BIT * sizeof(ZixBitset)) + +static inline size_t +zix_bitset_popcount(const ZixBitset value) +{ +#ifdef _MSC_VER + return (size_t)__popcnt(value); +#else + return (size_t)__builtin_popcountl(value); +#endif +} + +void +zix_bitset_clear(ZixBitset* b, ZixBitsetTally* t, size_t n_bits) +{ + memset(b, 0, ZIX_BITSET_ELEMS(n_bits) * sizeof(ZixBitset)); + memset(t, 0, ZIX_BITSET_ELEMS(n_bits) * sizeof(ZixBitsetTally)); +} + +void +zix_bitset_set(ZixBitset* b, ZixBitsetTally* t, size_t i) +{ + const size_t e = i / ZIX_BITSET_ELEM_BIT; + const size_t ebit = i & (ZIX_BITSET_ELEM_BIT - 1); // i % ELEM_BIT + const ZixBitset mask = (ZixBitset)1 << ebit; + + if (!(b[e] & mask)) { + ++t[e]; + } + + b[e] |= mask; +} + +void +zix_bitset_reset(ZixBitset* b, ZixBitsetTally* t, size_t i) +{ + const size_t e = i / ZIX_BITSET_ELEM_BIT; + const size_t ebit = i & (ZIX_BITSET_ELEM_BIT - 1); // i % ELEM_BIT + const ZixBitset mask = (ZixBitset)1 << ebit; + + if (b[e] & mask) { + --t[e]; + } + + b[e] &= ~mask; +} + +bool +zix_bitset_get(const ZixBitset* b, size_t i) +{ + const size_t e = i / ZIX_BITSET_ELEM_BIT; + const size_t ebit = i & (ZIX_BITSET_ELEM_BIT - 1); // i % ELEM_BIT + const ZixBitset mask = (ZixBitset)1 << ebit; + + return b[e] & mask; +} + +size_t +zix_bitset_count_up_to(const ZixBitset* b, const ZixBitsetTally* t, size_t i) +{ + const size_t full_elems = i / ZIX_BITSET_ELEM_BIT; + const size_t extra = i & (ZIX_BITSET_ELEM_BIT - 1); // i % ELEM_BIT + + size_t count = 0; + for (size_t e = 0; e < full_elems; ++e) { + count += t[e]; + } + + if (extra) { + const ZixBitset mask = ~(~(ZixBitset)0 << extra); + count += zix_bitset_popcount(b[full_elems] & mask); + } + + return count; +} + +size_t +zix_bitset_count_up_to_if(const ZixBitset* b, const ZixBitsetTally* t, size_t i) +{ + const size_t full_elems = i / ZIX_BITSET_ELEM_BIT; + const size_t extra = i & (ZIX_BITSET_ELEM_BIT - 1); // i % ELEM_BIT + + const ZixBitset get_mask = (ZixBitset)1 << extra; + if (!(b[full_elems] & get_mask)) { + return (size_t)-1; + } + + size_t count = 0; + for (size_t e = 0; e < full_elems; ++e) { + count += t[e]; + } + + if (extra) { + const ZixBitset mask = ~(~(ZixBitset)0 << extra); + count += zix_bitset_popcount(b[full_elems] & mask); + } + + return count; +} |