/// @file dpf/wildcard.hpp /// @brief defines the `dpf::wildcard_value` template and associated helpers /// @details A `dpf::wildcard` is a struct template with a single parameter /// `T`, which must be a trivially copyable type (as indicated by /// `std::is_trivially_copyable`). It is used as a placeholder /// for an instance of type `T`, which can be assigned later. Its /// intended to wrap an [output type](@ref output_types) of a DPF. /// @author Ryan Henry /// @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_WILDCARD_HPP__ #define LIBDPF_INCLUDE_DPF_WILDCARD_HPP__ #include "hedley/hedley.h" #include #include #include #include #include "dpf/bit.hpp" #include "dpf/bitstring.hpp" #include "dpf/random.hpp" #include "dpf/xor_wrapper.hpp" #include "simde/simde/x86/avx2.h" // #include "simde/simde/x86/avx512.h" namespace dpf { // namespace // { /// @brief represents a placeholder value of a given type, with a concrete value to be assigned later /// @tparam T the underlying type template struct wildcard_value { static_assert(std::is_trivially_copyable_v, "T must be a trivially copyable type"); static_assert(std::numeric_limits::is_iec559 || !(std::is_same_v || std::is_same_v), "floating point types only supported for iec559"); HEDLEY_NO_THROW inline constexpr wildcard_value() noexcept : val{std::nullopt} { } HEDLEY_NO_THROW inline constexpr wildcard_value(const T & t) noexcept : val{t} { } HEDLEY_NO_THROW inline constexpr wildcard_value(T && t) noexcept : val{std::move(t)} { } HEDLEY_ALWAYS_INLINE constexpr auto operator()(const T & t) const { return wildcard_value(t); } HEDLEY_ALWAYS_INLINE constexpr auto operator()(T && t) const { return wildcard_value(std::move(t)); } HEDLEY_ALWAYS_INLINE auto operator()() const { auto t = val.value_or(dpf::uniform_sample()); return std::tuple_cat(std::make_tuple(t), dpf::additively_share(t)); } private: std::optional val; }; // } // namespace template static constexpr wildcard_value wildcard{}; /// @brief Checks whether `T` is a wildcard type. /// @details A trait class that provides the member constant `value` which is /// equal to `true`, if `T` is a specialization of the `wildcard_value` /// template and `false` otherwise. /// @see dpf::is_wildcard_v template struct is_wildcard : std::false_type { }; template struct is_wildcard> : std::true_type { }; /// @brief Checks whether `T` is a wildcard type. template constexpr bool is_wildcard_v = is_wildcard::value; template struct concrete_type { using type = T; }; template struct concrete_type> : public concrete_type { }; template using concrete_type_t = typename concrete_type::type; template struct concrete_value { HEDLEY_NO_THROW HEDLEY_ALWAYS_INLINE HEDLEY_CONST constexpr std::optional operator()(T y) const noexcept { return y; } }; template struct concrete_value> { HEDLEY_NO_THROW HEDLEY_ALWAYS_INLINE HEDLEY_CONST constexpr std::optional operator()(wildcard_value) const noexcept { return std::nullopt; } }; template constexpr auto concrete_value_v = concrete_value{}; namespace wildcards { using bit_t = wildcard_value; static constexpr auto bit = wildcard; using signed_char_t = wildcard_value; static constexpr auto signed_char = wildcard; using uchar_t = wildcard_value; static constexpr auto uchar = wildcard; using xchar_t = wildcard_value>; static constexpr auto xchar = wildcard>; using int8_t = wildcard_value; static constexpr auto int8 = wildcard; using uint8_t = wildcard_value; static constexpr auto uint8 = wildcard; using xint8_t = wildcard_value; static constexpr auto xint8 = wildcard; using int16_t = wildcard_value; static constexpr auto int16 = wildcard; using uint16_t = wildcard_value; static constexpr auto uint16 = wildcard; using xint16_t = wildcard_value; static constexpr auto xint16 = wildcard; using int32_t = wildcard_value; static constexpr auto int32 = wildcard; using uint32_t = wildcard_value; static constexpr auto uint32 = wildcard; using xint32_t = wildcard_value; static constexpr auto xint32 = wildcard; using int64_t = wildcard_value; static constexpr auto int64 = wildcard; using uint64_t = wildcard_value; static constexpr auto uint64 = wildcard; using xint64_t = wildcard_value; static constexpr auto xint64 = wildcard; HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") using __int128_t = wildcard_value; //< gcc builtin `__int128` type static constexpr auto _int128 = wildcard; using __uint128_t = wildcard_value; //< gcc builtin `unsigned __int128` type static constexpr auto _uint128 = wildcard; using uint128_t = wildcard_value<::uint128_t>; //< `uint128_t` type static constexpr auto uint128 = wildcard<::uint128_t>; using xint128_t = wildcard_value; static constexpr auto xint128 = wildcard; using uint256_t = wildcard_value<::uint256_t>; //< `uint256_t` type static constexpr auto uint256 = wildcard<::uint256_t>; using xint256_t = wildcard_value; static constexpr auto xint256 = wildcard; template using bitstring_t = wildcard_value>; template static constexpr auto bitstring = wildcard>; template using xint_t = wildcard_value>; template static constexpr auto xint = wildcard>; template using modint_t = wildcard_value>; template static constexpr auto modint = wildcard>; using m128_t = wildcard_value; static constexpr auto m128 = wildcard; using m128i_t = wildcard_value; static constexpr auto m128i = wildcard; using m128d_t = wildcard_value; static constexpr auto m128d = wildcard; using m256_t = wildcard_value; static constexpr auto m256 = wildcard; using m256i_t = wildcard_value; static constexpr auto m256i = wildcard; using m256d_t = wildcard_value; static constexpr auto m256d = wildcard; // using m512_t = wildcard_value; // static constexpr auto m512 = wildcard; // using m512i_t = wildcard_value; // static constexpr auto m512i = wildcard; // using m512d_t = wildcard_value; // static constexpr auto m512d = wildcard; HEDLEY_PRAGMA(GCC diagnostic pop) using ieee_float_t = wildcard_value; /// @brief Placeholder for a `float` whose leaf group is bitwise XOR /// (exact reconstruction), not IEEE addition. static constexpr auto ieee_float = wildcard; using ieee_double_t = wildcard_value; /// @brief Placeholder for a `double` whose leaf group is bitwise XOR. static constexpr auto ieee_double = wildcard; } // namespace wildcards template void assert_wildcard_output(const DpfKey & dpf) { if (HEDLEY_UNLIKELY(std::get(dpf.leaves).is_ready())) { throw std::runtime_error("output not an unassigned wildcard"); } } template void assert_wildcard_input(const DpfKey & dpf) { if (HEDLEY_UNLIKELY(dpf.offset_x.is_ready())) { throw std::runtime_error("input is not an unassigned wildcard"); } } template HEDLEY_ALWAYS_INLINE void assert_not_wildcard_output(const DpfKey & dpf) { if (HEDLEY_UNLIKELY(!std::get(dpf.leaf_nodes).is_ready() || ...)) { throw std::runtime_error("one or more outputs is an unassigned wildcard"); } } template HEDLEY_ALWAYS_INLINE void assert_not_wildcard_input(const DpfKey & dpf) { if (HEDLEY_UNLIKELY(!dpf.offset_x.is_ready())) { throw std::runtime_error("input is unassigned wildcard"); } } namespace utils { /// @brief specializes `dpf::utils::bitlength_of` for `dpf::wildcard_value` template struct bitlength_of> : public bitlength_of { }; /// @brief specializes `dpf::utils::bitlength_of_output` for `dpf::wildcard_value` template struct bitlength_of_output, NodeT> : public bitlength_of_output { }; template struct make_default> { static constexpr wildcard_value value = wildcard_value(); }; } // namespace dpf::utils } // namespace dpf #endif // LIBDPF_INCLUDE_DPF_WILDCARD_HPP__