libdpf/include/dpf/eval_peel.hpp

156 lines
5.9 KiB
C++
Raw Normal View History

/// @file dpf/eval_peel.hpp
/// @brief Eval overloads that accept a wrapper and evaluate its `dpf_key`.
/// @details Include this after the eval headers. A call passes through while
/// the argument has a public `dpf_key` member and is not itself a
/// DPF key. `dpf3` / `dpf3_cmp` / `dpf3_ic` keep their key-first
/// protocol overloads; `eval_*(cmp, …)` and `eval_*(out<I>, …)` still
/// peel those wrappers down to the inner DPF key.
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
/// @license Released under a GNU General Public v2.0 (GPLv2) license.
#ifndef LIBDPF_INCLUDE_DPF_EVAL_PEEL_HPP__
#define LIBDPF_INCLUDE_DPF_EVAL_PEEL_HPP__
#include <type_traits>
#include <utility>
#include "dpf/eval_target.hpp"
namespace dpf
{
template <typename T>
inline constexpr bool peel_key_v =
has_embedded_dpf_key_v<std::decay_t<T>>
&& !owns_protocol_eval_v<std::decay_t<T>>;
template <typename T>
inline constexpr bool peel_tag_key_v =
has_embedded_dpf_key_v<std::decay_t<T>>;
#define LIBDPF_PEEL_KEY_FIRST(fn) \
template <std::size_t I = 0, \
typename KeyT, \
typename... Args, \
std::enable_if_t<peel_key_v<KeyT>, int> = 0> \
decltype(auto) fn(const KeyT & key, Args &&... args) \
{ \
return fn<I>(key.dpf_key, std::forward<Args>(args)...); \
}
#define LIBDPF_PEEL_TAG_FIRST(fn) \
template <typename Tag, \
typename KeyT, \
typename... Args, \
std::enable_if_t<peel_tag_key_v<KeyT> \
&& is_eval_channel_tag_v<std::decay_t<Tag>>, int> = 0> \
decltype(auto) fn(Tag tag, const KeyT & key, Args &&... args) \
{ \
return fn(tag, key.dpf_key, std::forward<Args>(args)...); \
}
LIBDPF_PEEL_KEY_FIRST(eval_point)
LIBDPF_PEEL_KEY_FIRST(eval_interval)
LIBDPF_PEEL_KEY_FIRST(eval_full)
LIBDPF_PEEL_KEY_FIRST(eval_sequence)
LIBDPF_PEEL_KEY_FIRST(eval_inner_product)
LIBDPF_PEEL_KEY_FIRST(eval_full_inner_product)
LIBDPF_PEEL_KEY_FIRST(eval_sequence_inner_product)
LIBDPF_PEEL_TAG_FIRST(eval_point)
LIBDPF_PEEL_TAG_FIRST(eval_interval)
LIBDPF_PEEL_TAG_FIRST(eval_full)
LIBDPF_PEEL_TAG_FIRST(eval_sequence)
LIBDPF_PEEL_TAG_FIRST(eval_sequence_breadth_first)
LIBDPF_PEEL_TAG_FIRST(eval_inner_product)
LIBDPF_PEEL_TAG_FIRST(eval_full_inner_product)
LIBDPF_PEEL_TAG_FIRST(make_output_buffer)
LIBDPF_PEEL_TAG_FIRST(make_sequence_recipe)
LIBDPF_PEEL_TAG_FIRST(eval_prefixes)
LIBDPF_PEEL_TAG_FIRST(eval_prefix_inner_product)
#undef LIBDPF_PEEL_KEY_FIRST
#undef LIBDPF_PEEL_TAG_FIRST
template <typename KeyT,
typename... Args,
std::enable_if_t<peel_key_v<KeyT>, int> = 0>
decltype(auto) eval_sequence_xor(const KeyT & key, Args &&... args)
{
return eval_sequence_xor(key.dpf_key, std::forward<Args>(args)...);
}
template <typename KeyT,
typename... Args,
std::enable_if_t<peel_key_v<KeyT>, int> = 0>
decltype(auto) prove_cmp_interval(const KeyT & key, Args &&... args)
{
return prove_cmp_interval(key.dpf_key, std::forward<Args>(args)...);
}
template <typename KeyT,
typename... Args,
std::enable_if_t<peel_key_v<KeyT>, int> = 0>
decltype(auto) prove_cmp_full(const KeyT & key, Args &&... args)
{
return prove_cmp_full(key.dpf_key, std::forward<Args>(args)...);
}
template <typename KeyT,
typename... Args,
std::enable_if_t<peel_key_v<KeyT>, int> = 0>
decltype(auto) prove_cmp_sequence(const KeyT & key, Args &&... args)
{
return prove_cmp_sequence(key.dpf_key, std::forward<Args>(args)...);
}
template <std::size_t I = 0,
typename Buffer,
typename KeyT,
typename... Args,
std::enable_if_t<peel_key_v<KeyT>, int> = 0>
void eval_full_add_into(Buffer & buf, const KeyT & key, Args &&... args)
{
eval_full_add_into<I>(buf, key.dpf_key, std::forward<Args>(args)...);
}
/// @brief Row-wise and column inner products keep the tag in front of the key.
template <typename Tag,
typename KeyT,
typename... Args,
std::enable_if_t<peel_tag_key_v<KeyT>
&& (std::is_same_v<std::decay_t<Tag>, paired_t>
|| std::is_same_v<std::decay_t<Tag>, columns_t>), int> = 0>
decltype(auto) eval_inner_product(Tag tag, const KeyT & key, Args &&... args)
{
return eval_inner_product(tag, key.dpf_key, std::forward<Args>(args)...);
}
template <typename Tag,
typename KeyT,
typename... Args,
std::enable_if_t<peel_tag_key_v<KeyT>
&& (std::is_same_v<std::decay_t<Tag>, paired_t>
|| std::is_same_v<std::decay_t<Tag>, columns_t>), int> = 0>
decltype(auto) eval_full_inner_product(Tag tag, const KeyT & key, Args &&... args)
{
return eval_full_inner_product(tag, key.dpf_key, std::forward<Args>(args)...);
}
template <typename Tag,
typename KeyT,
typename... Args,
std::enable_if_t<peel_tag_key_v<KeyT>
&& (std::is_same_v<std::decay_t<Tag>, paired_t>
|| std::is_same_v<std::decay_t<Tag>, columns_t>), int> = 0>
decltype(auto) eval_sequence_inner_product(Tag tag, const KeyT & key,
Args &&... args)
{
return eval_sequence_inner_product(tag, key.dpf_key,
std::forward<Args>(args)...);
}
} // namespace dpf
#endif // LIBDPF_INCLUDE_DPF_EVAL_PEEL_HPP__