/// @file dpf/eval_full.hpp /// @brief Evaluate every input in the DPF domain. /// @details Equivalent to `eval_interval` from /// `std::numeric_limits::min()` through `max()`. /// @snippet evaluation/eval_full.cpp eval-full /// @author Ryan Henry /// @author Christopher Jiang /// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors) /// @license Released under a GNU General Public v2.0 (GPLv2) license; /// see [LICENSE.md](@ref license) for details. #ifndef LIBDPF_INCLUDE_DPF_EVAL_FULL_HPP__ #define LIBDPF_INCLUDE_DPF_EVAL_FULL_HPP__ #include #include "hedley/hedley.h" #include #include #include #include #include "dpf/dpf_key.hpp" #include "dpf/eval_common.hpp" #include "dpf/eval_target.hpp" #include "dpf/output_buffer.hpp" #include "dpf/interval_memoizer.hpp" #include "dpf/rotation_iterable.hpp" #include "dpf/subinterval_iterable.hpp" namespace dpf { namespace internal { template , bool> = false> auto eval_full(const DpfKey & dpf, OutputBuffers && outbufs, IntervalMemoizer && memoizer, std::index_sequence) { using dpf_type = DpfKey; using input_type = typename dpf_type::input_type; auto offset = dpf.offset_x(0); // N.B.: throws if dpf is not ready dpf::internal::eval_interval_impl(dpf, std::numeric_limits::min(), std::numeric_limits::max(), outbufs, memoizer, std::make_index_sequence()); return utils::make_tuple(dpf::rotation_iterable(std::begin(utils::get(outbufs)), std::end(utils::get(outbufs)), offset)...); } template , bool> = false> auto eval_full(const DpfKey & dpf, OutputBuffers && outbufs, IntervalMemoizer && memoizer, std::index_sequence) { using dpf_type = DpfKey; using input_type = typename dpf_type::input_type; dpf::internal::eval_interval_impl(dpf, std::numeric_limits::min(), std::numeric_limits::max(), outbufs, memoizer, std::make_index_sequence()); return utils::make_tuple( subinterval_iterable(std::begin(utils::get(outbufs)), utils::size(utils::get(outbufs)), std::size_t{0}, utils::get(outbufs).size() - 1, std::size_t{0}, std::size_t{0})...); } } // namespace internal template && !is_multilevel_key_v, bool> = true> HEDLEY_ALWAYS_INLINE auto eval_full(const DpfKey & dpf, OutputBuffers && outbufs, IntervalMemoizer && memoizer) { assert_not_wildcard_output(dpf); return internal::eval_full(dpf, outbufs, memoizer, std::make_index_sequence<1+sizeof...(Is)>()); } template && !is_multilevel_key_v, bool> = true, std::enable_if_t>, std::decay_t>, bool> = true> HEDLEY_ALWAYS_INLINE auto eval_full(const DpfKey & dpf, OutputBuffers & outbufs) // NOLINT(runtime/references) { using input_type = typename DpfKey::input_type; return eval_full(dpf, outbufs, dpf::make_basic_full_memoizer(dpf)); } template && !is_multilevel_key_v, bool> = true, std::enable_if_t>, std::decay_t>, bool> = true> HEDLEY_ALWAYS_INLINE auto eval_full(const DpfKey & dpf, IntervalMemoizer && memoizer) { auto outbufs = utils::make_tuple( make_output_buffer_for_full(dpf), make_output_buffer_for_full(dpf)...); // moving `outbufs` is allowed as the `outbufs` are `std::vectors` // the underlying data remains on the heap // and thus the data the iterable refers to is still valid auto iterable = eval_full(dpf, outbufs, memoizer); return std::make_pair(std::move(outbufs), std::move(iterable)); } /// Evaluate the whole domain, allocating a basic full memoizer and a buffer. template && !is_multilevel_key_v, bool> = true> HEDLEY_ALWAYS_INLINE auto eval_full(const DpfKey & dpf) { using input_type = typename DpfKey::input_type; return eval_full(dpf, dpf::make_basic_full_memoizer(dpf)); } } // namespace dpf #endif // LIBDPF_INCLUDE_DPF_EVAL_FULL_HPP__