/// @file dpf/eval_point.hpp /// @brief Evaluate one DPF input. /// @details `eval_point(key, x)` returns a handle; `*handle` is that party's /// share of output 0. `eval_point` selects another output. /// `eval_point` returns a tuple of shares. /// Pass a `basic_path_memoizer` lvalue to resume a previous path. /// An unassigned wildcard output throws `std::runtime_error`. /// @snippet evaluation/eval_point.cpp eval-point /// @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_POINT_HPP__ #define LIBDPF_INCLUDE_DPF_EVAL_POINT_HPP__ #include #include "hedley/hedley.h" #include #include #include "dpf/dpf_key.hpp" #include "dpf/eval_common.hpp" #include "dpf/eval_target.hpp" #include "dpf/path_memoizer.hpp" namespace dpf { namespace internal { template inline auto eval_point_interior(const DpfKey & dpf, InputT && x, PathMemoizer && path) { using dpf_type = DpfKey; auto level_index = detail::path_resume_for_level(path, dpf, x, dpf.depth); DPF_UNROLL_LOOP for (auto mask = dpf.msb_mask>>(level_index-1); level_index <= dpf.depth; ++level_index, mask>>=1) { bool bit = !!(mask & x); auto cw = dpf.correction_word(level_index-1, bit); path[level_index] = dpf_type::traverse_interior(path[level_index-1], cw, bit); } detail::path_note_filled_to(path, dpf.depth); } template inline auto eval_point_exterior(const DpfKey & dpf, PathMemoizer && path) { assert_not_wildcard_output(dpf); auto interior = path[dpf.depth]; return dpf.template traverse_exterior(interior); } template HEDLEY_ALWAYS_INLINE auto eval_point(const DpfKey & dpf, InputT && x, PathMemoizer && path) { utils::flip_msb_if_signed_integral(x); internal::eval_point_interior(dpf, x, path); return internal::eval_point_exterior(dpf, path); } } // namespace internal /// Evaluate output `I` at `x`. /// @param path Mutable path memoizer. The default is a fresh /// nonmemoizing workspace for this call. /// @return Handle whose `operator*` is the party's share. template , std::enable_if_t && !is_multilevel_key_v, bool> = true> HEDLEY_ALWAYS_INLINE auto eval_point(const DpfKey & dpf, InputT && x, PathMemoizer && path = PathMemoizer{}) { assert_not_wildcard_output(dpf); using output_type = typename DpfKey::concrete_output_type; auto tx = dpf.offset_x(x); return make_eval_dpf_output( internal::eval_point(dpf, tx, path), tx); } /// Evaluate several outputs at `x`. /// @return Tuple of shares, already dereferenced. template , std::enable_if_t && !is_multilevel_key_v, bool> = true> HEDLEY_ALWAYS_INLINE auto eval_point(const DpfKey & dpf, InputT && x, PathMemoizer && path = PathMemoizer{}) { return std::make_tuple( *eval_point(dpf, x, path), *eval_point(dpf, x, path), *eval_point(dpf, x, path)...); } } // namespace dpf #endif // LIBDPF_INCLUDE_DPF_EVAL_POINT_HPP__