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

@ -148,8 +148,18 @@ inline auto eval_sequence(const DpfKey & dpf, ForwardIterator begin, ForwardIter
}
}
/// Evaluate the sorted range `[begin, end)`, allocating a buffer.
/// @brief Evaluate the sorted range `[begin, end)`, allocating a buffer.
/// @tparam I output index
/// @tparam Is is
/// @tparam DpfKey DPF key type
/// @tparam ForwardIterator forward iterator type
/// @tparam ReturnType return type
/// @tparam DpfKey DPF key type
/// @tparam ReturnType return type
/// @param return_type `return_entire_node_tag_{}` or `return_output_only_tag_{}`.
/// @param dpf the DPF key
/// @param begin the iterator to the first query
/// @param end the iterator past the last query
/// @return Pair of buffer (or tuple of buffers) and an iterable in list order.
template <std::size_t I = 0,
std::size_t ...Is,
@ -188,8 +198,8 @@ inline auto eval_sequence_breadth_first(const DpfKey & dpf, ForwardIterator begi
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
using allocator = aligned_allocator<typename DpfKey::interior_node>;
using unique_ptr = typename allocator::unique_ptr;
HEDLEY_PRAGMA(GCC diagnostic pop)
using unique_ptr = typename allocator::unique_ptr;
allocator alloc = allocator{};
if (HEDLEY_UNLIKELY(!std::is_sorted(begin, end)))
@ -219,6 +229,8 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
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_type::depth);
// `lower` and `upper` are always adjacent elements of `splits` with `lower` < `upper`
// [lower, upper) = "block"
for (auto upper = std::begin(splits), lower = upper++; upper != std::end(splits); lower = upper++)
@ -228,16 +240,16 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
[&flip](auto a, auto b){ return static_cast<bool>(a&b) ^ flip; });
if (it == *lower) // right only since first element in "block" requires right traversal
{
memo[curhalf*nodes_in_sequence + i++] = dpf_type::traverse_interior(memo[!curhalf*nodes_in_sequence + j++], cw[1], 1);
memo[curhalf*nodes_in_sequence + i++] = dpf_type::traverse_interior(memo[!curhalf*nodes_in_sequence + j++], cw[1], 1, is_last);
}
else if (it == *upper) // left only since no element in "block" requires right traversal
{
memo[curhalf*nodes_in_sequence + i++] = dpf_type::traverse_interior(memo[!curhalf*nodes_in_sequence + j++], cw[0], 0);
memo[curhalf*nodes_in_sequence + i++] = dpf_type::traverse_interior(memo[!curhalf*nodes_in_sequence + j++], cw[0], 0, is_last);
}
else // both ways since some (non-lower) element within "block" requires right traversal
{
auto cur_node = memo[!curhalf*nodes_in_sequence + 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);
memo[curhalf*nodes_in_sequence + i++] = kids[0];
memo[curhalf*nodes_in_sequence + i++] = kids[1];
splits.insert(upper, it);
@ -259,6 +271,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
auto cw = dpf.template leaf<I>();
HEDLEY_PRAGMA(GCC diagnostic pop)
auto buf = memo.get();
constexpr auto clz = utils::countl_zero_symmetric_difference<input_type>{};
@ -278,7 +291,6 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
}
prev = curr++;
}
HEDLEY_PRAGMA(GCC diagnostic pop)
return subsequence_iterable<DpfKey, decltype(std::begin(outbuf)), ForwardIterator>(std::begin(outbuf), begin, end);
}
@ -324,6 +336,8 @@ inline auto eval_sequence_interior(const DpfKey & dpf, const sequence_recipe & r
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_type::depth);
auto prevbuf = memoizer[level_index-1];
auto currbuf = memoizer[level_index];
@ -334,12 +348,12 @@ inline auto eval_sequence_interior(const DpfKey & dpf, const sequence_recipe & r
if (memoizer.traverse_first(recipe_index) == true)
{
bool dir = memoizer.get_direction(0);
currbuf[output_index++] = dpf_type::traverse_interior(prevbuf[input_index], cw[dir], dir);
currbuf[output_index++] = dpf_type::traverse_interior(prevbuf[input_index], cw[dir], dir, is_last);
}
if (memoizer.traverse_second(recipe_index) == true)
{
bool dir = memoizer.get_direction(1);
currbuf[output_index++] = dpf_type::traverse_interior(prevbuf[input_index], cw[dir], dir);
currbuf[output_index++] = dpf_type::traverse_interior(prevbuf[input_index], cw[dir], dir, is_last);
}
}
}
@ -362,6 +376,7 @@ inline auto eval_sequence_exterior_entire_node(const DpfKey & dpf, const sequenc
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
auto buf = memoizer[dpf.depth];
HEDLEY_PRAGMA(GCC diagnostic pop)
DPF_UNROLL_LOOP
for (std::size_t j = 0; j < nodes_in_interval; ++j)
{
@ -375,7 +390,6 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
std::memcpy(&outbuf[j*dpf_type::outputs_per_leaf], &leaf, sizeof(output_type)*dpf_type::outputs_per_leaf);
}
}
HEDLEY_PRAGMA(GCC diagnostic pop)
}
template <std::size_t I,
@ -393,6 +407,7 @@ inline auto eval_sequence_exterior_output_only(const DpfKey & dpf, const sequenc
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
auto cw = dpf.template leaf<I>();
HEDLEY_PRAGMA(GCC diagnostic pop)
using node_type = typename DpfKey::exterior_node;
using leaf_node_type = std::tuple_element_t<I, typename DpfKey::leaf_tuple>;
auto buf = memoizer[dpf.depth];
@ -417,7 +432,6 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
else
outbuf[i] = v;
}
HEDLEY_PRAGMA(GCC diagnostic pop)
}
template <std::size_t ...Is,
@ -454,9 +468,21 @@ auto eval_sequence(const DpfKey & dpf, const sequence_recipe & recipe,
} // namespace internal
/// Evaluate `recipe` into a named buffer, reusing `memoizer`.
/// @brief Evaluate `recipe` into a named buffer, reusing `memoizer`.
/// @tparam I output index
/// @tparam Is is
/// @tparam DpfKey DPF key type
/// @tparam OutputBuffers tuple of output buffers
/// @tparam SequenceMemoizer sequence memoizer
/// @tparam ReturnType return type
/// @tparam SequenceMemoizer sequence memoizer
/// @tparam ReturnType return type
/// @param recipe The same object `memoizer` was constructed from.
/// @param outbufs Named buffer. The returned iterable refers into it.
/// @param dpf the DPF key
/// @param memoizer the memoizer built for this key
/// @param return_type `return_entire_node_tag_{}` or `return_output_only_tag_{}`
/// @return the evaluation result
template <std::size_t I = 0,
std::size_t ...Is,
typename DpfKey,