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

@ -1,6 +1,13 @@
/// @file dpf/path_memoizer.hpp
/// @brief
/// @details
/// @brief Workspaces that resume a root-to-leaf DPF walk.
/// @details `basic_path_memoizer` keeps one interior node per level. The next
/// `eval_point` recomputes the suffix after the common prefix with
/// the previous input. `nonmemoizing_path_memoizer` keeps a single
/// node and starts at the root on every call.
///
/// Pass a mutable lvalue to `eval_point`. The factories unwrap
/// `party_key`, so a memoizer built from either party's type
/// accepts both parties. A different root restarts the path.
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
@ -44,13 +51,21 @@ struct path_memoizer_base
using return_type = ReturnT;
using iterator_type = return_type;
HEDLEY_NO_THROW
virtual std::size_t assign_x(const dpf_type &, input_type) noexcept = 0;
HEDLEY_NO_THROW
virtual node_type & operator[](std::size_t) noexcept = 0;
HEDLEY_NO_THROW
virtual return_type begin() const noexcept = 0;
HEDLEY_NO_THROW
virtual return_type end() const noexcept = 0;
};
/// One interior node per level. `assign_x` returns the first level that the
/// next walk must recompute. `filled_to` is the deepest level already
/// written for the current input. Callers pass this object to `eval_point`;
/// they do not call `assign_x` themselves.
template <typename DpfKey>
struct alignas(alignof(typename path_memoizer_key_t<DpfKey>::interior_node))
basic_path_memoizer final
@ -69,12 +84,15 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
basic_path_memoizer()
: dpf_{std::nullopt}, x_{std::nullopt}, filled_to_{0} { }
HEDLEY_NO_THROW
basic_path_memoizer(basic_path_memoizer &&) noexcept = default;
basic_path_memoizer(const basic_path_memoizer &) = default;
HEDLEY_NO_THROW
basic_path_memoizer & operator=(basic_path_memoizer &&) noexcept = default;
basic_path_memoizer & operator=(const basic_path_memoizer &) = default;
~basic_path_memoizer() = default;
HEDLEY_NO_THROW
std::size_t assign_x(const dpf_type & dpf, input_type new_x) noexcept override
{
static constexpr auto clz_xor = utils::countl_zero_symmetric_difference<input_type>{};
@ -100,11 +118,13 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
return 1;
}
HEDLEY_NO_THROW
node_type & operator[](std::size_t i) noexcept override
{
return arr_[i];
}
HEDLEY_NO_THROW
return_type begin() const noexcept override
{
if (x_.has_value() == true)
@ -117,14 +137,17 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
}
}
HEDLEY_NO_THROW
return_type end() const noexcept override
{
return std::addressof(arr_[depth+1]);
}
/// Inclusive high-water: `arr_[0..filled_to_]` are valid for the current x.
HEDLEY_NO_THROW
std::size_t filled_to() const noexcept { return filled_to_; }
HEDLEY_NO_THROW
void note_filled(std::size_t level) noexcept
{
if (level > filled_to_)
@ -143,6 +166,7 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
HEDLEY_PRAGMA(GCC diagnostic pop)
};
/// A single interior node. Every `assign_x` restarts at the root.
template <typename DpfKey>
struct nonmemoizing_path_memoizer final
: public path_memoizer_base<path_memoizer_key_t<DpfKey>>
@ -159,8 +183,10 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
nonmemoizing_path_memoizer()
: dpf_{std::nullopt} { }
HEDLEY_NO_THROW
nonmemoizing_path_memoizer(nonmemoizing_path_memoizer &&) noexcept = default;
nonmemoizing_path_memoizer(const nonmemoizing_path_memoizer &) = default;
HEDLEY_NO_THROW
nonmemoizing_path_memoizer & operator=(nonmemoizing_path_memoizer &&) noexcept = default;
nonmemoizing_path_memoizer & operator=(const nonmemoizing_path_memoizer &) = default;
~nonmemoizing_path_memoizer() = default;
@ -186,6 +212,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
return std::addressof(v);
}
HEDLEY_NO_THROW
return_type end() const noexcept override
{
return std::addressof(v) + 1;
@ -260,6 +287,9 @@ void ensure_level(const DpfKey & dpf, typename DpfKey::input_type x,
} // namespace detail
/// Path workspace for `DpfKey`. A `party_key` argument is unwrapped, and the
/// result accepts both parties.
/// @snippet evaluation/memoizers.cpp path-memoizer
template <typename DpfKey>
auto make_basic_path_memoizer()
{
@ -272,6 +302,7 @@ auto make_basic_path_memoizer(const DpfKey &)
return make_basic_path_memoizer<DpfKey>();
}
/// Single-node path workspace. Suitable for one query.
template <typename DpfKey>
auto make_nonmemoizing_path_memoizer()
{