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/interval_memoizer.hpp
/// @brief
/// @details
/// @brief Workspaces for an inclusive interval of DPF leaves.
/// @details `basic_interval_memoizer` keeps two levels of the interval.
/// `full_tree_interval_memoizer` keeps every level. Size either one
/// for the widest interval you will evaluate; a wider interval
/// throws `std::length_error`. The same key and the same endpoints
/// leave the final interior level in place.
///
/// Factories unwrap `party_key`. Pass the memoizer as a mutable
/// lvalue to `eval_interval` or `eval_full`.
/// @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)
@ -55,10 +62,13 @@ struct interval_memoizer_base
// level 0 should access the root
// level goes up to (and including) depth
HEDLEY_NO_THROW
virtual return_type operator[](std::size_t) const noexcept = 0;
// iterators should access most recently completed level
HEDLEY_NO_THROW
virtual return_type begin() const noexcept = 0;
HEDLEY_NO_THROW
virtual return_type end() const noexcept = 0;
virtual std::size_t assign_interval(const dpf_type & dpf, integral_type new_from, integral_type new_to)
@ -151,6 +161,8 @@ struct interval_memoizer_base
std::optional<integral_type> to_;
};
/// Two-level workspace for one interval. This is what
/// `eval_interval(key, from, to)` allocates when you omit the memoizer.
template <typename DpfKey,
typename Allocator = aligned_allocator<
typename interval_memoizer_key_t<DpfKey>::interior_node>>
@ -229,6 +241,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
unique_ptr buf;
};
/// Every level of the interval. `retains_all_levels` is true.
template <typename DpfKey,
typename Allocator = aligned_allocator<
typename interval_memoizer_key_t<DpfKey>::interior_node>>
@ -392,6 +405,7 @@ struct basic_interval_memoizer_at
- utils::shift_right(from_node, offset) + 1;
}
HEDLEY_NO_THROW
return_type operator[](std::size_t level) const noexcept
{
bool b = (depth ^ level) & 1;
@ -420,9 +434,6 @@ auto make_interval_memoizer(InputT from, InputT to)
{
using dpf_type = DpfKey;
utils::flip_msb_if_signed_integral(from);
utils::flip_msb_if_signed_integral(to);
std::size_t nodes_in_interval = utils::get_leafnodes_in_output_interval<dpf_type>(from, to);
return MemoizerT(nodes_in_interval);
@ -430,6 +441,10 @@ auto make_interval_memoizer(InputT from, InputT to)
} // namespace detail
/// Two-level workspace sized for the closed interval `[from, to]`.
/// @param from Inclusive start, in the key's input domain.
/// @param to Inclusive end. `to` is at least `from` in that domain.
/// @snippet evaluation/memoizers.cpp interval-memoizer
template <typename DpfKey,
typename InputT>
inline auto make_basic_interval_memoizer(InputT from, InputT to)
@ -448,6 +463,7 @@ inline auto make_basic_interval_memoizer(const DpfKey &, InputT from, InputT to)
return make_basic_interval_memoizer<DpfKey>(from, to);
}
/// `make_basic_interval_memoizer` sized for the whole input domain.
template <typename DpfKey>
inline auto make_basic_full_memoizer()
{
@ -464,6 +480,7 @@ inline auto make_basic_full_memoizer(const DpfKey &)
return make_basic_full_memoizer<DpfKey>();
}
/// Full-tree workspace sized for the closed interval `[from, to]`.
template <typename DpfKey,
typename InputT>
inline auto make_full_tree_interval_memoizer(InputT from, InputT to)
@ -482,6 +499,7 @@ inline auto make_full_tree_interval_memoizer(const DpfKey &, InputT from, InputT
return make_full_tree_interval_memoizer<DpfKey>(from, to);
}
/// `make_full_tree_interval_memoizer` sized for the whole input domain.
template <typename DpfKey>
inline auto make_full_tree_full_memoizer()
{
@ -521,11 +539,13 @@ inline auto make_basic_interval_memoizer(InputT from, InputT to)
utils::flip_msb_if_signed_integral(from);
utils::flip_msb_if_signed_integral(to);
const integral_type from_node = utils::leaf_node_floor(
static_cast<integral_type>(to_int(from)), lg);
const integral_type to_node = utils::leaf_node_ceil_exclusive(
static_cast<integral_type>(to_int(to)), lg);
const auto segs = utils::split_leaf_nodes(from_node, to_node, stop);
const auto from_i = static_cast<integral_type>(to_int(from));
const auto to_i = static_cast<integral_type>(to_int(to));
const integral_type from_node = utils::leaf_node_floor(from_i, lg);
const integral_type to_node = utils::leaf_node_ceil_exclusive(to_i, lg);
const bool wraps = utils::interval_wraps(from_i, to_i,
utils::bitlength_of_v<InputT>);
const auto segs = utils::split_leaf_nodes(from_node, to_node, stop, wraps);
return basic_interval_memoizer_at<DpfKey, stop>(segs.total);
}