Document the new DPF surfaces in one command set, and test the field, half-tree, and multipoint edges.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ryan Henry 2026-09-24 23:18:10 -06:00
parent 0d8a5a8131
commit 0dff6df8ed
250 changed files with 12199 additions and 1981 deletions

View file

@ -67,6 +67,8 @@ inline auto eval_interval_interior(const DpfKey & dpf, IntegralT from_node,
dpf.correction_word(level_index-1, 0),
dpf.correction_word(level_index-1, 1)
};
const bool is_last = dpf_type::tree::is_last_level(level_index - 1,
dpf.depth);
auto *prev = memoizer[level_index-1];
auto *curr = memoizer[level_index];
@ -74,7 +76,7 @@ inline auto eval_interval_interior(const DpfKey & dpf, IntegralT from_node,
// process node which only requires a right traversal
if (from_offset == true)
{
curr[i++] = dpf_type::traverse_interior(prev[j++], cw[1], 1);
curr[i++] = dpf_type::traverse_interior(prev[j++], cw[1], 1, is_last);
}
// process all nodes which require both a left traversal and a right traversal
const std::size_t both_end = nodes_at_level - to_offset;
@ -88,7 +90,8 @@ inline auto eval_interval_interior(const DpfKey & dpf, IntegralT from_node,
{
parents[t] = prev[j + t];
}
dpf_type::traverse_interior01_x4(parents, cw[0], cw[1], left, right);
dpf_type::traverse_interior01_x4(parents, cw[0], cw[1], left, right,
is_last);
DPF_UNROLL_LOOP
for (std::size_t t = 0; t < 4; ++t)
{
@ -102,14 +105,15 @@ inline auto eval_interval_interior(const DpfKey & dpf, IntegralT from_node,
for (; i < both_end;)
{
auto cur_node = prev[j++];
auto kids = dpf_type::traverse_interior01(cur_node, cw[0], cw[1]);
auto kids = dpf_type::traverse_interior01(cur_node, cw[0], cw[1],
is_last);
curr[i++] = kids[0];
curr[i++] = kids[1];
}
// process node which only requires a left traversal
if (to_offset == true)
{
curr[i] = dpf_type::traverse_interior(prev[j], cw[0], 0);
curr[i] = dpf_type::traverse_interior(prev[j], cw[0], 0, is_last);
}
}
}
@ -135,6 +139,7 @@ inline auto eval_interval_exterior(const DpfKey & dpf, IntegralT from_node,
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
auto cw = std::get<I>(dpf.leaf_nodes).get();
HEDLEY_PRAGMA(GCC diagnostic pop)
auto *nodes = memoizer[dpf_type::depth];
DPF_UNROLL_LOOP
for (std::size_t j = 0, k = start; j < nodes_in_interval; ++j, ++k)
@ -151,7 +156,6 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
sizeof(output_type) * dpf_type::outputs_per_leaf);
}
}
HEDLEY_PRAGMA(GCC diagnostic pop)
}
template <std::size_t I,
@ -175,9 +179,23 @@ void store_interval_leaf(OutputBuffer && outbuf, std::size_t k, const LeafT & le
}
}
/// One pass over the leaf-level interior nodes. When the selected output
/// @brief One pass over the leaf-level interior nodes. When the selected output
/// indices occupy a contiguous PRG-position range, a single batched
/// `ExteriorPRG::eval` produces every output's leaf mask.
/// @tparam Is is
/// @tparam DpfKey DPF key type
/// @tparam OutputBuffers tuple of output buffers
/// @tparam IntervalMemoizer interval memoizer type
/// @tparam IntegralT integral type
/// @tparam IIs iis
/// @param dpf the DPF key
/// @param from_node the `from_node`
/// @param to_node the `to_node`
/// @param outbufs the named output buffers
/// @param memoizer the memoizer built for this key
/// @param IIs the `IIs`
/// @param start the start of the range
/// @throws std::runtime_error if `to_node<from_node`
template <std::size_t ...Is,
typename DpfKey,
typename OutputBuffers,
@ -194,7 +212,10 @@ inline void eval_interval_exterior_fused(const DpfKey & dpf, IntegralT from_node
using node_type = typename DpfKey::exterior_node;
using outputs_tuple = typename DpfKey::concrete_outputs_tuple;
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
using range = leaf_prg_range<node_type, outputs_tuple, Is...>;
HEDLEY_PRAGMA(GCC diagnostic pop)
std::size_t nodes_in_interval = static_cast<std::size_t>(to_node - from_node);
auto *nodes = memoizer[DpfKey::depth];
@ -312,7 +333,10 @@ void eval_interval_exterior_all(const DpfKey & dpf, IntegralT from_node,
{
using node_type = typename DpfKey::exterior_node;
using outputs_tuple = typename DpfKey::concrete_outputs_tuple;
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
using range = leaf_prg_range<node_type, outputs_tuple, Is...>;
HEDLEY_PRAGMA(GCC diagnostic pop)
if constexpr (range::is_contiguous)
{
eval_interval_exterior_fused<Is...>(dpf, from_node, to_node, outbufs,
@ -397,10 +421,26 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
} // namespace internal
/// Write outputs `I, Is...` for `[from, to]` into `outbufs`.
/// @param outbufs Named buffer, or a tuple of buffers when several outputs
/// @name Closed-interval evaluation
/// @tparam I output index
/// @tparam Is the remaining output indices
/// @tparam DpfKey DPF key type
/// @tparam InputT input domain type
/// @param dpf the DPF key
/// @param from the inclusive start of the range
/// @param to the inclusive end of the range
/// @{
/// @brief Write outputs `I, Is...` for `[from, to]` into `outbufs`.
/// @tparam OutputBuffers tuple of output buffers
/// @tparam IntervalMemoizer interval memoizer type
/// @param dpf the DPF key
/// @param from the inclusive start of the range
/// @param to the inclusive end of the range
/// @param outbufs named buffer, or a tuple of buffers when several outputs
/// are selected. Must outlive the returned iterable.
/// @param memoizer Workspace sized for at least this interval.
/// @param memoizer workspace sized for at least this interval
/// @return an iterable over the written outputs
template <std::size_t I = 0,
std::size_t ...Is,
typename DpfKey,
@ -417,7 +457,13 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
return internal::eval_interval<I, Is...>(dpf, dpf.offset_x(from), dpf.offset_x(to), outbufs, memoizer, std::make_index_sequence<1+sizeof...(Is)>());
}
/// Evaluate `[from, to]` into `outbufs`, allocating a basic interval memoizer.
/// @brief Evaluate `[from, to]` into `outbufs`, allocating a basic interval memoizer.
/// @tparam OutputBuffers tuple of output buffers
/// @param dpf the DPF key
/// @param from the inclusive start of the range
/// @param to the inclusive end of the range
/// @param outbufs the named output buffers
/// @return an iterable over the written outputs
template <std::size_t I = 0,
std::size_t ...Is,
typename DpfKey,
@ -435,7 +481,12 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
dpf::make_basic_interval_memoizer<DpfKey>(from, to));
}
/// Evaluate `[from, to]` with a caller-supplied memoizer.
/// @brief Evaluate `[from, to]` with a caller-supplied memoizer.
/// @tparam IntervalMemoizer interval memoizer type
/// @param dpf the DPF key
/// @param from the inclusive start of the range
/// @param to the inclusive end of the range
/// @param memoizer the memoizer built for this key
/// @return `std::pair` of a new buffer (or tuple of buffers) and an iterable
/// into that buffer.
template <std::size_t I = 0,
@ -462,7 +513,9 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
return std::make_pair(std::move(outbufs), std::move(iterable));
}
/// Evaluate `[from, to]`, allocating a basic interval memoizer and a buffer.
/// @brief Evaluate `[from, to]`, allocating a basic interval memoizer and a buffer.
/// @return `std::pair` of a new buffer (or tuple of buffers) and an iterable
/// into that buffer.
template <std::size_t I = 0,
std::size_t ...Is,
typename DpfKey,
@ -475,6 +528,8 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to)
dpf::make_basic_interval_memoizer<DpfKey>(from, to));
}
/// @}
} // namespace dpf
#endif // LIBDPF_INCLUDE_DPF_EVAL_INTERVAL_HPP__