libdpf/include/dpf/eval_target.hpp

131 lines
3.7 KiB
C++

/// @file dpf/eval_target.hpp
/// @brief Eval channel tags for the unified DPF / iDPF / DCF surface.
/// @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_TARGET_HPP__
#define LIBDPF_INCLUDE_DPF_EVAL_TARGET_HPP__
#include <cstddef>
#include <limits>
#include <type_traits>
namespace dpf
{
/// Sentinel: deduce point-slot prefix from the key (`meta[I].prefix`).
inline constexpr std::size_t prefix_deduce =
std::numeric_limits<std::size_t>::max();
/// Point-output channel: slot `I`, optional prefix check `N`.
template <std::size_t I = 0, std::size_t N = prefix_deduce>
struct out_t
{
static constexpr std::size_t index = I;
static constexpr std::size_t prefix = N;
static constexpr bool prefix_fixed = (N != prefix_deduce);
};
template <std::size_t I = 0, std::size_t N = prefix_deduce>
inline constexpr out_t<I, N> out{};
/// Comparison (DCF) channel.
struct cmp_t
{
};
inline constexpr cmp_t cmp{};
/// Prefix of an `idcf` comparison. `L` is the number of leading bits.
template <std::size_t L>
struct cmp_prefix_t
{
static constexpr std::size_t length = L;
};
template <std::size_t L>
inline constexpr cmp_prefix_t<L> cmp_prefix{};
template <typename T>
struct is_out : std::false_type
{
};
template <std::size_t I, std::size_t N>
struct is_out<out_t<I, N>> : std::true_type
{
};
template <typename T>
inline constexpr bool is_out_v = is_out<std::decay_t<T>>::value;
template <typename T>
struct is_cmp_target : std::bool_constant<std::is_same_v<std::decay_t<T>, cmp_t>>
{
};
template <typename T>
inline constexpr bool is_cmp_target_v = is_cmp_target<T>::value;
template <typename T>
struct is_cmp_prefix_target : std::false_type
{
};
template <std::size_t L>
struct is_cmp_prefix_target<cmp_prefix_t<L>> : std::true_type
{
};
template <typename T>
inline constexpr bool is_cmp_prefix_target_v =
is_cmp_prefix_target<std::decay_t<T>>::value;
/// True for channel tags that must not bind as the key in classic eval_*.
template <typename T>
inline constexpr bool is_eval_channel_tag_v =
is_out_v<T> || is_cmp_target_v<T> || is_cmp_prefix_target_v<T>;
template <typename T, typename = void>
struct looks_like_dpf_key : std::false_type
{
};
template <typename T>
struct looks_like_dpf_key<T,
std::void_t<typename T::input_type, typename T::interior_node>>
: std::true_type
{
};
template <typename T>
inline constexpr bool looks_like_dpf_key_v =
looks_like_dpf_key<std::decay_t<T>>::value;
template <typename T, typename = void>
struct is_incremental_dpf_key : std::false_type
{
};
template <typename T>
struct is_incremental_dpf_key<T,
std::void_t<decltype(T::cmp_depth), decltype(T::meta),
decltype(T::deepest_output)>> : std::true_type
{
};
template <typename T>
inline constexpr bool is_incremental_dpf_key_v =
is_incremental_dpf_key<std::decay_t<T>>::value;
/// True only for keys that must use the slot-aware (multi-level / comparison)
/// eval path. Every key now carries a `slot_meta` table (so
/// `is_incremental_dpf_key_v` is true for all keys), but classic single-level
/// equal-width keys keep using the classic `eval_*` fast paths; they set
/// `is_multilevel == false`. Multi-level (`at<N>`) and comparison keys set it
/// to true.
template <typename T, typename = void>
struct is_multilevel_key : std::false_type
{
};
template <typename T>
struct is_multilevel_key<T, std::void_t<decltype(T::is_multilevel)>>
: std::bool_constant<T::is_multilevel>
{
};
template <typename T>
inline constexpr bool is_multilevel_key_v =
is_multilevel_key<std::decay_t<T>>::value;
} // namespace dpf
#endif // LIBDPF_INCLUDE_DPF_EVAL_TARGET_HPP__