From fe8c11dc9471085f6baec7c6a1770181c04dcfae Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 12 Jul 2022 11:35:52 -0700 Subject: [PATCH] ircd::util: Add a constexpr bitset. --- include/ircd/util/bitset.h | 143 +++++++++++++++++++++++++++++++++++++ include/ircd/util/util.h | 1 + 2 files changed, 144 insertions(+) create mode 100644 include/ircd/util/bitset.h diff --git a/include/ircd/util/bitset.h b/include/ircd/util/bitset.h new file mode 100644 index 000000000..019be346e --- /dev/null +++ b/include/ircd/util/bitset.h @@ -0,0 +1,143 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2022 Jason Volk +// +// 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 is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_UTIL_BITSET_H + +namespace ircd { +inline namespace util +{ + template + struct bitset; +}} + +template +struct ircd::util::bitset +{ + using word = uint8_t; + + static constexpr size_t word_bits + { + sizeof(word) * 8 + }; + + static constexpr size_t words + { + N / word_bits?: 1 + }; + + private: + word buf[words] {0}; + + public: + constexpr size_t size() const + { + return N; + } + + constexpr bool test(const size_t pos) const; + constexpr size_t count() const; + + constexpr void reset(const size_t pos); + constexpr void reset(); + constexpr void set(const size_t pos, const bool val = true); + constexpr void set(); + constexpr void flip(const size_t pos); + constexpr void flip(); + + constexpr bitset(const uint128_t val); + constexpr bitset() = default; +}; + +template +constexpr +ircd::util::bitset::bitset(const uint128_t val) +{ + const auto bits + { + std::min(sizeof(buf) * 8, sizeof(val) * 8) + }; + + size_t i{0}; + for(; i < bits; ++i) + { + const decltype(val) one{1}; + set(i, val & (one << i)); + } + + for(; i < size(); ++i) + set(i, false); +} + +template +constexpr void +ircd::util::bitset::flip() +{ + for(size_t i(0); i < words; ++i) + buf[i] =~ buf[i]; +} + +template +constexpr void +ircd::util::bitset::flip(const size_t pos) +{ + buf[pos / 8] ^= word(1) << (pos % 8); +} + +template +constexpr void +ircd::util::bitset::set() +{ + for(size_t i(0); i < words; ++i) + buf[i] = ~word{0}; +} + +template +constexpr void +ircd::util::bitset::set(const size_t pos, + const bool val) +{ + buf[pos / 8] |= word(val) << (pos % 8); +} + +template +constexpr void +ircd::util::bitset::reset() +{ + for(size_t i(0); i < words; ++i) + buf[i] = 0; +} + +template +constexpr void +ircd::util::bitset::reset(const size_t pos) +{ + buf[pos / 8] &= ~(word(1) << (pos % 8)); +} + +template +constexpr size_t +ircd::util::bitset::count() +const +{ + size_t ret(0); + for(size_t i(0); i < words; ++i) + ret += std::popcount(buf[i]); + + return ret; +} + +template +constexpr bool +ircd::util::bitset::test(const size_t pos) +const +{ + return buf[pos / 8] & (word(1) << (pos % 8)); +} diff --git a/include/ircd/util/util.h b/include/ircd/util/util.h index 7a64dab26..53d477958 100644 --- a/include/ircd/util/util.h +++ b/include/ircd/util/util.h @@ -65,6 +65,7 @@ namespace ircd #include "maybe.h" #include "all.h" #include "compare_exchange.h" +#include "bitset.h" // Unsorted section namespace ircd {