Annotate noexcept and constexpr with HEDLEY, and add interval containment, ChaCha, and the dyadic range tables.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ryan Henry 2026-09-24 20:44:07 -06:00
parent 875f09fec1
commit 0d8a5a8131
97 changed files with 9212 additions and 1159 deletions

View file

@ -41,6 +41,7 @@ namespace detail
{
template <typename Word>
HEDLEY_NO_THROW
constexpr void check_one_bit(Word mask) noexcept
{
#if defined(__GNUC__) || defined(__clang__)
@ -135,6 +136,7 @@ class bit_array_base
inline constexpr bit_array_base(const bit_array_base &) = default;
/// @brief default move constructor
HEDLEY_NO_THROW
inline constexpr bit_array_base(bit_array_base &&) noexcept = default;
/// @brief default destructor
@ -145,6 +147,7 @@ class bit_array_base
bit_array_base & operator=(const bit_array_base &) = default;
/// @brief defaulted move assignment
HEDLEY_NO_THROW
inline constexpr
bit_array_base & operator=(bit_array_base &&) noexcept = default;
@ -163,6 +166,7 @@ class bit_array_base
/// @note Does not perform bounds checking; behaviour is undefined if
/// `pos` is out of bounds
/// @return `data()[pos]`
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr word_type data(size_type pos) const noexcept
{
@ -187,6 +191,7 @@ class bit_array_base
return data()[pos];
}
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr size_type data_length() const noexcept { return derived_from_this()->data_length(); }
@ -261,6 +266,7 @@ class bit_array_base
/// @{
/// @returns iterator to the first element
/// @complexity `O(1)`
HEDLEY_NO_THROW
constexpr iterator begin() noexcept
{
auto *p = data();
@ -269,6 +275,7 @@ class bit_array_base
}
/// @returns iterator to the first element
/// @complexity `O(1)`
HEDLEY_NO_THROW
constexpr const_iterator begin() const noexcept
{
auto *p = data();
@ -277,6 +284,7 @@ class bit_array_base
}
/// @returns iterator to the first element
/// @complexity `O(1)`
HEDLEY_NO_THROW
constexpr const_iterator cbegin() const noexcept
{
return begin();
@ -287,6 +295,7 @@ class bit_array_base
/// @{
/// @returns iterator to the element following the last element
/// @complexity `O(1)`
HEDLEY_NO_THROW
constexpr iterator end() noexcept
{
auto *p = data();
@ -296,6 +305,7 @@ class bit_array_base
}
/// @returns iterator to the element following the last element
/// @complexity `O(1)`
HEDLEY_NO_THROW
constexpr const_iterator end() const noexcept
{
auto *p = data();
@ -305,6 +315,7 @@ class bit_array_base
}
/// @returns iterator to the element following the last element
/// @complexity `O(1)`
HEDLEY_NO_THROW
constexpr const_iterator cend() const noexcept
{
return end();
@ -326,6 +337,7 @@ class bit_array_base
/// @details checks if all bits are set to `true`
/// @return `true` if all of the bits are set to `true`, otherwise `false`
/// @complexity `O(size())`
HEDLEY_NO_THROW
bool all() const noexcept
{
if (size() == 0) return true;
@ -351,6 +363,7 @@ class bit_array_base
/// `true`, otherwise `false`
/// @complexity `O(last-first)`
template <typename Iterator>
HEDLEY_NO_THROW
bool all(Iterator first, Iterator last) const noexcept
{
bool ok = true;
@ -365,6 +378,7 @@ class bit_array_base
/// @details checks if any bits are set to `true`
/// @return `true` if any of the bits are set to `true`, otherwise `false`
/// @complexity `O(size())`
HEDLEY_NO_THROW
bool any() const noexcept
{
const size_type n = data_length();
@ -386,6 +400,7 @@ class bit_array_base
/// `true`, otherwise `false`
/// @complexity `O(last-first)`
template <typename Iterator>
HEDLEY_NO_THROW
bool any(Iterator first, Iterator last) const noexcept
{
bool found = false;
@ -400,6 +415,7 @@ class bit_array_base
/// @details checks if none of the bits are set to `true`
/// @return `true` if none of the bits are set to `true`, otherwise `false`
/// @complexity `O(size())`
HEDLEY_NO_THROW
bool none() const noexcept
{
return !any();
@ -412,6 +428,7 @@ class bit_array_base
/// `true`, otherwise `false`
/// @complexity `O(last-first)`
template <typename Iterator>
HEDLEY_NO_THROW
bool none(Iterator first, Iterator last) const noexcept
{
return !any(first, last);
@ -423,6 +440,7 @@ class bit_array_base
/// @details counts the number of bits that are set to `true`
/// @returns the number of bits set to `true`
/// @complexity `O(size())`
HEDLEY_NO_THROW
size_type count() const noexcept
{
const size_type n = data_length();
@ -443,6 +461,7 @@ class bit_array_base
/// @return the number of bits in the given range that are set to `true`
/// @complexity `O(last-first)`
template <typename Iterator>
HEDLEY_NO_THROW
size_type count(Iterator first, Iterator last) const noexcept
{
size_type sum = 0;
@ -460,6 +479,7 @@ class bit_array_base
/// @details counts the parity of all stored bits
/// @returns the parity of all stored bits
/// @complexity `O(size())`
HEDLEY_NO_THROW
size_type parity() const noexcept
{
const size_type n = data_length();
@ -481,6 +501,7 @@ class bit_array_base
/// @return the parity of all bits in the given range
/// @complexity `O(last-first)`
template <typename Iterator>
HEDLEY_NO_THROW
size_type parity(Iterator first, Iterator last) const noexcept
{
word_type x = word_type{0};
@ -496,6 +517,7 @@ class bit_array_base
/// @brief returns the number of bits
/// @returns number of bits that the `bit_array_base` holds
/// @complexity `O(1)`
HEDLEY_NO_THROW
HEDLEY_PURE
HEDLEY_ALWAYS_INLINE
constexpr size_type size() const noexcept
@ -507,6 +529,7 @@ class bit_array_base
/// @{
/// @brief sets all bits to `true`
/// @complexity `O(size())`
HEDLEY_NO_THROW
constexpr void set() noexcept
{
const size_type n = data_length();
@ -551,6 +574,7 @@ class bit_array_base
/// @{
/// @brief sets all bits to `false'
/// @complexity `O(size())`
HEDLEY_NO_THROW
constexpr void unset() noexcept
{
word_type *p = data();
@ -578,6 +602,7 @@ class bit_array_base
/// @{
/// @brief flips all bits (like `operator~`, but in-place)
/// @complexity `O(size())`
HEDLEY_NO_THROW
constexpr void flip() noexcept
{
const size_type n = data_length();
@ -711,6 +736,7 @@ class bit_array_base
return static_cast<dpf::bit>(static_cast<bool>(lhs) ^ static_cast<bool>(rhs));
}
HEDLEY_NO_THROW
friend constexpr dpf::bit operator+(bit_reference lhs, bit_reference rhs) noexcept
{
return static_cast<dpf::bit>(static_cast<bool>(lhs) ^ static_cast<bool>(rhs));
@ -820,6 +846,7 @@ class bit_array_base
/// @brief Exchange the bits named by two proxies, including temporaries
/// returned from `operator[]` and `operator*`.
HEDLEY_NO_THROW
friend constexpr void swap(bit_reference a, bit_reference b) noexcept
{
const bool tmp = static_cast<bool>(a);
@ -870,6 +897,7 @@ class bit_array_base
static constexpr word_type sentinel = ~word_type(0);
/// @brief Low `n` bits set. `n == 0` yields 0. `n >= bits_per_word` yields all ones.
HEDLEY_NO_THROW
static constexpr word_type low_bits_mask(size_type n) noexcept
{
if (n == 0) return word_type{0};
@ -878,18 +906,21 @@ class bit_array_base
static_cast<word_type>(~word_type{0}) >> (bits_per_word - n));
}
HEDLEY_NO_THROW
static constexpr size_type pop(word_type w) noexcept
{
return static_cast<size_type>(utils::popcount(w));
}
/// @brief Bits strictly below the single set bit in `mask`.
HEDLEY_NO_THROW
static constexpr word_type bits_below(word_type mask) noexcept
{
return static_cast<word_type>(mask - word_type{1});
}
/// @brief Bits at and above the single set bit in `mask`.
HEDLEY_NO_THROW
static constexpr word_type bits_at_and_above(word_type mask) noexcept
{
return static_cast<word_type>(~bits_below(mask));
@ -999,6 +1030,7 @@ class bit_iterator_base
word_type mask_;
/// @brief Singular iterator. Comparable, not dereferenceable.
HEDLEY_NO_THROW
inline constexpr bit_iterator_base() noexcept
: word_ptr_{nullptr},
mask_{lsb}
@ -1125,11 +1157,14 @@ class bit_iterator final
using word_pointer = typename bit_array_base<ConcreteBitArrayT, WordT>::word_pointer;
/// @brief Singular iterator. Comparable, not dereferenceable.
HEDLEY_NO_THROW
constexpr bit_iterator() noexcept = default;
HEDLEY_NO_THROW
inline constexpr
bit_iterator(const bit_iterator &) noexcept = default;
HEDLEY_NO_THROW
inline constexpr bit_iterator(bit_iterator &&) noexcept = default;
HEDLEY_NO_THROW
@ -1218,6 +1253,7 @@ class bit_iterator final
return tmp -= amt;
}
HEDLEY_NO_THROW
friend constexpr iterator operator+(difference_type amt, iterator it) noexcept
{
return it + amt;
@ -1257,6 +1293,7 @@ class const_bit_iterator final
using const_word_pointer = typename bit_array_base<ConcreteBitArrayT, WordT>::const_word_pointer;
/// @brief Singular iterator. Comparable, not dereferenceable.
HEDLEY_NO_THROW
constexpr const_bit_iterator() noexcept = default;
HEDLEY_ALWAYS_INLINE
HEDLEY_NO_THROW
@ -1349,6 +1386,7 @@ class const_bit_iterator final
return *this;
}
HEDLEY_NO_THROW
inline constexpr
const_iterator & operator-=(difference_type amt) noexcept
{
@ -1356,6 +1394,7 @@ class const_bit_iterator final
return *this;
}
HEDLEY_NO_THROW
inline constexpr
const_iterator operator+(difference_type amt) const noexcept
{
@ -1363,6 +1402,7 @@ class const_bit_iterator final
return tmp += amt;
}
HEDLEY_NO_THROW
inline constexpr
const_iterator operator-(difference_type amt) const noexcept
{
@ -1370,12 +1410,14 @@ class const_bit_iterator final
return tmp -= amt;
}
HEDLEY_NO_THROW
friend constexpr const_iterator operator+(difference_type amt,
const_iterator it) noexcept
{
return it + amt;
}
HEDLEY_NO_THROW
inline constexpr
const_reference operator[](difference_type i) const noexcept
{
@ -1402,10 +1444,14 @@ class alignas(utils::max_align_v) static_bit_array final
/// `size()` bits
static constexpr size_type data_length_ = utils::quotient_ceiling(Nbits, bits_per_word);
public:
HEDLEY_NO_THROW
constexpr static_bit_array(static_bit_array &&) noexcept = default;
HEDLEY_NO_THROW
constexpr static_bit_array(const static_bit_array &) noexcept = default;
~static_bit_array() = default;
HEDLEY_NO_THROW
constexpr static_bit_array & operator=(static_bit_array &&) noexcept = default;
HEDLEY_NO_THROW
constexpr static_bit_array & operator=(const static_bit_array &) noexcept = default;
/// @brief constructs a zeroed `static_bit_array` that holds `Nbits` bits
inline constexpr static_bit_array()
@ -1459,6 +1505,7 @@ class alignas(utils::max_align_v) static_bit_array final
/// @brief returns the number of bits
/// @returns number of bits that the `static_bit_array` holds
/// @complexity `O(1)`
HEDLEY_NO_THROW
HEDLEY_PURE
HEDLEY_ALWAYS_INLINE
constexpr size_type size() const noexcept
@ -1509,6 +1556,7 @@ class dynamic_bit_array
std::copy_n(other.data_.get(), data_length_ + 1, data_.get());
}
HEDLEY_NO_THROW
dynamic_bit_array(dynamic_bit_array && other) noexcept
: num_bits_{std::exchange(other.num_bits_, 0)},
data_length_{std::exchange(other.data_length_, 0)},
@ -1525,6 +1573,7 @@ class dynamic_bit_array
return *this;
}
HEDLEY_NO_THROW
dynamic_bit_array & operator=(dynamic_bit_array && other) noexcept
{
if (this != &other)
@ -1537,6 +1586,7 @@ class dynamic_bit_array
return *this;
}
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
~dynamic_bit_array() noexcept
{
@ -1595,6 +1645,7 @@ class dynamic_bit_array
/// @brief returns the number of bits
/// @returns number of bits that the `dynamic_bit_array` holds
/// @complexity `O(1)`
HEDLEY_NO_THROW
HEDLEY_PURE
HEDLEY_ALWAYS_INLINE
constexpr size_type size() const noexcept
@ -1603,6 +1654,8 @@ class dynamic_bit_array
}
private:
/// Store zeros through `volatile` so the wipe is not deleted as a dead store.
HEDLEY_NO_THROW
void wipe() noexcept
{
if (!data_) return;
@ -1620,6 +1673,7 @@ class dynamic_bit_array
/// @brief
template <typename WordT>
HEDLEY_NO_THROW
inline constexpr void swap(typename dynamic_bit_array<WordT>::reference lhs,
typename dynamic_bit_array<WordT>::reference rhs) noexcept
{
@ -1630,6 +1684,7 @@ inline constexpr void swap(typename dynamic_bit_array<WordT>::reference lhs,
template <std::size_t Nbits,
typename WordT>
HEDLEY_NO_THROW
inline constexpr void swap(typename static_bit_array<Nbits, WordT>::reference lhs,
typename static_bit_array<Nbits, WordT>::reference rhs) noexcept
{