Annotate noexcept and constexpr with HEDLEY, and add interval containment, ChaCha, and the dyadic range tables.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
875f09fec1
commit
0d8a5a8131
97 changed files with 9212 additions and 1159 deletions
|
|
@ -143,6 +143,7 @@ class advice_bit_iterable_const_iterator
|
|||
using difference_type = std::ptrdiff_t;
|
||||
using node_type = typename iterator_traits::value_type;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr
|
||||
explicit advice_bit_iterable_const_iterator(const wrapped_type & it) noexcept
|
||||
|
|
@ -213,28 +214,33 @@ class advice_bit_iterable_const_iterator
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
advice_bit_iterable_const_iterator operator+(std::size_t n) const noexcept
|
||||
{
|
||||
return advice_bit_iterable_const_iterator(it_ + n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
advice_bit_iterable_const_iterator & operator-=(std::size_t n) noexcept
|
||||
{
|
||||
it_ -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
advice_bit_iterable_const_iterator operator-(std::size_t n) const noexcept
|
||||
{
|
||||
return advice_bit_iterable_const_iterator(it_ - n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
difference_type
|
||||
operator-(advice_bit_iterable_const_iterator rhs) const noexcept
|
||||
{
|
||||
return it_ - rhs.it_;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
reference operator[](std::size_t i) const noexcept
|
||||
{
|
||||
return bit(it_ + i);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class aligned_allocator
|
|||
template <typename Pointer>
|
||||
struct deleter
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
constexpr void operator()(Pointer p) const noexcept { free(p); }
|
||||
};
|
||||
public:
|
||||
|
|
@ -125,6 +126,7 @@ class aligned_allocator
|
|||
/// @note This function returns the maximum number of elements that can
|
||||
/// be allocated, not the maximum allocation size in bytes
|
||||
/// @return The maximum supported allocation size.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr size_type max_size() const noexcept
|
||||
{
|
||||
return std::numeric_limits<size_type>::max() / sizeof(value_type);
|
||||
|
|
|
|||
|
|
@ -166,17 +166,22 @@ class wire
|
|||
friend class session<Ring>;
|
||||
|
||||
public:
|
||||
HEDLEY_NO_THROW
|
||||
constexpr wire() noexcept = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
constexpr std::uint32_t id() const noexcept { return id_; }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
constexpr session<Ring> * owner() const noexcept { return sess_; }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator==(wire a, wire b) noexcept
|
||||
{
|
||||
return a.sess_ == b.sess_ && a.id_ == b.id_;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator!=(wire a, wire b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
|
|
@ -240,13 +245,16 @@ public:
|
|||
static constexpr std::uint32_t mono_role_base = 0x40000000u;
|
||||
static constexpr std::uint32_t dot_role_base = 0x80000000u;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr std::uint32_t wire_role(std::uint32_t id) noexcept { return id; }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr std::uint32_t mono_role(std::uint32_t i) noexcept
|
||||
{
|
||||
return mono_role_base + i;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr std::uint32_t dot_role(std::uint32_t gate) noexcept
|
||||
{
|
||||
return dot_role_base + gate;
|
||||
|
|
@ -255,6 +263,7 @@ public:
|
|||
/// Fused within-polynomial λ combinations (Appendix E groupings).
|
||||
static constexpr std::uint32_t bundle_role_base = 0xC0000000u;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr std::uint32_t bundle_role(std::uint32_t i) noexcept
|
||||
{
|
||||
return bundle_role_base + i;
|
||||
|
|
@ -268,6 +277,7 @@ public:
|
|||
: lanes_(std::move(seed), window)
|
||||
{ }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const seed_type & seed() const noexcept { return lanes_.seed(); }
|
||||
|
||||
Ring blind(std::uint32_t role, std::uint64_t index) const
|
||||
|
|
@ -822,11 +832,13 @@ public:
|
|||
return wires_[check(w)].ready_round;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t wire_count() const noexcept { return wires_.size(); }
|
||||
|
||||
/// Product shares beyond the per-wire blinds: subset monomials from
|
||||
/// `product` gates, plus one fused bundle per public-δ class in a
|
||||
/// polynomial (Appendix E). A lone mask is not counted.
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t monomial_count() const noexcept
|
||||
{
|
||||
return monos_.size() + bundles_.size();
|
||||
|
|
|
|||
|
|
@ -183,12 +183,14 @@ operator>>(std::basic_istream<CharT, Traits> & is, dpf::bit & value)
|
|||
|
||||
/// @}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr dpf::bit operator+(dpf::bit lhs, dpf::bit rhs) noexcept
|
||||
{
|
||||
return static_cast<dpf::bit>(static_cast<bool>(lhs) ^ static_cast<bool>(rhs));
|
||||
}
|
||||
|
||||
/// @brief GF(2) subtraction. Identical to `operator+`.
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr dpf::bit operator-(dpf::bit lhs, dpf::bit rhs) noexcept
|
||||
{
|
||||
return lhs + rhs;
|
||||
|
|
@ -216,6 +218,7 @@ struct packed_lane_bits<dpf::bit>
|
|||
template <>
|
||||
struct make_from_integral_value<dpf::bit>
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
constexpr dpf::bit operator()(bool val) const noexcept
|
||||
{
|
||||
return val ? dpf::bit::one : dpf::bit::zero;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace detail
|
|||
{
|
||||
|
||||
template <typename Word>
|
||||
HEDLEY_NO_THROW
|
||||
constexpr void check_one_bit(Word mask) noexcept
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
|
|
@ -135,6 +136,7 @@ class bit_array_base
|
|||
inline constexpr bit_array_base(const bit_array_base &) = default;
|
||||
|
||||
/// @brief default move constructor
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr bit_array_base(bit_array_base &&) noexcept = default;
|
||||
|
||||
/// @brief default destructor
|
||||
|
|
@ -145,6 +147,7 @@ class bit_array_base
|
|||
bit_array_base & operator=(const bit_array_base &) = default;
|
||||
|
||||
/// @brief defaulted move assignment
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr
|
||||
bit_array_base & operator=(bit_array_base &&) noexcept = default;
|
||||
|
||||
|
|
@ -163,6 +166,7 @@ class bit_array_base
|
|||
/// @note Does not perform bounds checking; behaviour is undefined if
|
||||
/// `pos` is out of bounds
|
||||
/// @return `data()[pos]`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr word_type data(size_type pos) const noexcept
|
||||
{
|
||||
|
|
@ -187,6 +191,7 @@ class bit_array_base
|
|||
return data()[pos];
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr size_type data_length() const noexcept { return derived_from_this()->data_length(); }
|
||||
|
||||
|
|
@ -261,6 +266,7 @@ class bit_array_base
|
|||
/// @{
|
||||
/// @returns iterator to the first element
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr iterator begin() noexcept
|
||||
{
|
||||
auto *p = data();
|
||||
|
|
@ -269,6 +275,7 @@ class bit_array_base
|
|||
}
|
||||
/// @returns iterator to the first element
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const_iterator begin() const noexcept
|
||||
{
|
||||
auto *p = data();
|
||||
|
|
@ -277,6 +284,7 @@ class bit_array_base
|
|||
}
|
||||
/// @returns iterator to the first element
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const_iterator cbegin() const noexcept
|
||||
{
|
||||
return begin();
|
||||
|
|
@ -287,6 +295,7 @@ class bit_array_base
|
|||
/// @{
|
||||
/// @returns iterator to the element following the last element
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr iterator end() noexcept
|
||||
{
|
||||
auto *p = data();
|
||||
|
|
@ -296,6 +305,7 @@ class bit_array_base
|
|||
}
|
||||
/// @returns iterator to the element following the last element
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const_iterator end() const noexcept
|
||||
{
|
||||
auto *p = data();
|
||||
|
|
@ -305,6 +315,7 @@ class bit_array_base
|
|||
}
|
||||
/// @returns iterator to the element following the last element
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const_iterator cend() const noexcept
|
||||
{
|
||||
return end();
|
||||
|
|
@ -326,6 +337,7 @@ class bit_array_base
|
|||
/// @details checks if all bits are set to `true`
|
||||
/// @return `true` if all of the bits are set to `true`, otherwise `false`
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
bool all() const noexcept
|
||||
{
|
||||
if (size() == 0) return true;
|
||||
|
|
@ -351,6 +363,7 @@ class bit_array_base
|
|||
/// `true`, otherwise `false`
|
||||
/// @complexity `O(last-first)`
|
||||
template <typename Iterator>
|
||||
HEDLEY_NO_THROW
|
||||
bool all(Iterator first, Iterator last) const noexcept
|
||||
{
|
||||
bool ok = true;
|
||||
|
|
@ -365,6 +378,7 @@ class bit_array_base
|
|||
/// @details checks if any bits are set to `true`
|
||||
/// @return `true` if any of the bits are set to `true`, otherwise `false`
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
bool any() const noexcept
|
||||
{
|
||||
const size_type n = data_length();
|
||||
|
|
@ -386,6 +400,7 @@ class bit_array_base
|
|||
/// `true`, otherwise `false`
|
||||
/// @complexity `O(last-first)`
|
||||
template <typename Iterator>
|
||||
HEDLEY_NO_THROW
|
||||
bool any(Iterator first, Iterator last) const noexcept
|
||||
{
|
||||
bool found = false;
|
||||
|
|
@ -400,6 +415,7 @@ class bit_array_base
|
|||
/// @details checks if none of the bits are set to `true`
|
||||
/// @return `true` if none of the bits are set to `true`, otherwise `false`
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
bool none() const noexcept
|
||||
{
|
||||
return !any();
|
||||
|
|
@ -412,6 +428,7 @@ class bit_array_base
|
|||
/// `true`, otherwise `false`
|
||||
/// @complexity `O(last-first)`
|
||||
template <typename Iterator>
|
||||
HEDLEY_NO_THROW
|
||||
bool none(Iterator first, Iterator last) const noexcept
|
||||
{
|
||||
return !any(first, last);
|
||||
|
|
@ -423,6 +440,7 @@ class bit_array_base
|
|||
/// @details counts the number of bits that are set to `true`
|
||||
/// @returns the number of bits set to `true`
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
size_type count() const noexcept
|
||||
{
|
||||
const size_type n = data_length();
|
||||
|
|
@ -443,6 +461,7 @@ class bit_array_base
|
|||
/// @return the number of bits in the given range that are set to `true`
|
||||
/// @complexity `O(last-first)`
|
||||
template <typename Iterator>
|
||||
HEDLEY_NO_THROW
|
||||
size_type count(Iterator first, Iterator last) const noexcept
|
||||
{
|
||||
size_type sum = 0;
|
||||
|
|
@ -460,6 +479,7 @@ class bit_array_base
|
|||
/// @details counts the parity of all stored bits
|
||||
/// @returns the parity of all stored bits
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
size_type parity() const noexcept
|
||||
{
|
||||
const size_type n = data_length();
|
||||
|
|
@ -481,6 +501,7 @@ class bit_array_base
|
|||
/// @return the parity of all bits in the given range
|
||||
/// @complexity `O(last-first)`
|
||||
template <typename Iterator>
|
||||
HEDLEY_NO_THROW
|
||||
size_type parity(Iterator first, Iterator last) const noexcept
|
||||
{
|
||||
word_type x = word_type{0};
|
||||
|
|
@ -496,6 +517,7 @@ class bit_array_base
|
|||
/// @brief returns the number of bits
|
||||
/// @returns number of bits that the `bit_array_base` holds
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr size_type size() const noexcept
|
||||
|
|
@ -507,6 +529,7 @@ class bit_array_base
|
|||
/// @{
|
||||
/// @brief sets all bits to `true`
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr void set() noexcept
|
||||
{
|
||||
const size_type n = data_length();
|
||||
|
|
@ -551,6 +574,7 @@ class bit_array_base
|
|||
/// @{
|
||||
/// @brief sets all bits to `false'
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr void unset() noexcept
|
||||
{
|
||||
word_type *p = data();
|
||||
|
|
@ -578,6 +602,7 @@ class bit_array_base
|
|||
/// @{
|
||||
/// @brief flips all bits (like `operator~`, but in-place)
|
||||
/// @complexity `O(size())`
|
||||
HEDLEY_NO_THROW
|
||||
constexpr void flip() noexcept
|
||||
{
|
||||
const size_type n = data_length();
|
||||
|
|
@ -711,6 +736,7 @@ class bit_array_base
|
|||
return static_cast<dpf::bit>(static_cast<bool>(lhs) ^ static_cast<bool>(rhs));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend constexpr dpf::bit operator+(bit_reference lhs, bit_reference rhs) noexcept
|
||||
{
|
||||
return static_cast<dpf::bit>(static_cast<bool>(lhs) ^ static_cast<bool>(rhs));
|
||||
|
|
@ -820,6 +846,7 @@ class bit_array_base
|
|||
|
||||
/// @brief Exchange the bits named by two proxies, including temporaries
|
||||
/// returned from `operator[]` and `operator*`.
|
||||
HEDLEY_NO_THROW
|
||||
friend constexpr void swap(bit_reference a, bit_reference b) noexcept
|
||||
{
|
||||
const bool tmp = static_cast<bool>(a);
|
||||
|
|
@ -870,6 +897,7 @@ class bit_array_base
|
|||
static constexpr word_type sentinel = ~word_type(0);
|
||||
|
||||
/// @brief Low `n` bits set. `n == 0` yields 0. `n >= bits_per_word` yields all ones.
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr word_type low_bits_mask(size_type n) noexcept
|
||||
{
|
||||
if (n == 0) return word_type{0};
|
||||
|
|
@ -878,18 +906,21 @@ class bit_array_base
|
|||
static_cast<word_type>(~word_type{0}) >> (bits_per_word - n));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr size_type pop(word_type w) noexcept
|
||||
{
|
||||
return static_cast<size_type>(utils::popcount(w));
|
||||
}
|
||||
|
||||
/// @brief Bits strictly below the single set bit in `mask`.
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr word_type bits_below(word_type mask) noexcept
|
||||
{
|
||||
return static_cast<word_type>(mask - word_type{1});
|
||||
}
|
||||
|
||||
/// @brief Bits at and above the single set bit in `mask`.
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr word_type bits_at_and_above(word_type mask) noexcept
|
||||
{
|
||||
return static_cast<word_type>(~bits_below(mask));
|
||||
|
|
@ -999,6 +1030,7 @@ class bit_iterator_base
|
|||
word_type mask_;
|
||||
|
||||
/// @brief Singular iterator. Comparable, not dereferenceable.
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr bit_iterator_base() noexcept
|
||||
: word_ptr_{nullptr},
|
||||
mask_{lsb}
|
||||
|
|
@ -1125,11 +1157,14 @@ class bit_iterator final
|
|||
using word_pointer = typename bit_array_base<ConcreteBitArrayT, WordT>::word_pointer;
|
||||
|
||||
/// @brief Singular iterator. Comparable, not dereferenceable.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bit_iterator() noexcept = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr
|
||||
bit_iterator(const bit_iterator &) noexcept = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr bit_iterator(bit_iterator &&) noexcept = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
|
|
@ -1218,6 +1253,7 @@ class bit_iterator final
|
|||
return tmp -= amt;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend constexpr iterator operator+(difference_type amt, iterator it) noexcept
|
||||
{
|
||||
return it + amt;
|
||||
|
|
@ -1257,6 +1293,7 @@ class const_bit_iterator final
|
|||
using const_word_pointer = typename bit_array_base<ConcreteBitArrayT, WordT>::const_word_pointer;
|
||||
|
||||
/// @brief Singular iterator. Comparable, not dereferenceable.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const_bit_iterator() noexcept = default;
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
|
|
@ -1349,6 +1386,7 @@ class const_bit_iterator final
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr
|
||||
const_iterator & operator-=(difference_type amt) noexcept
|
||||
{
|
||||
|
|
@ -1356,6 +1394,7 @@ class const_bit_iterator final
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr
|
||||
const_iterator operator+(difference_type amt) const noexcept
|
||||
{
|
||||
|
|
@ -1363,6 +1402,7 @@ class const_bit_iterator final
|
|||
return tmp += amt;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr
|
||||
const_iterator operator-(difference_type amt) const noexcept
|
||||
{
|
||||
|
|
@ -1370,12 +1410,14 @@ class const_bit_iterator final
|
|||
return tmp -= amt;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend constexpr const_iterator operator+(difference_type amt,
|
||||
const_iterator it) noexcept
|
||||
{
|
||||
return it + amt;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr
|
||||
const_reference operator[](difference_type i) const noexcept
|
||||
{
|
||||
|
|
@ -1402,10 +1444,14 @@ class alignas(utils::max_align_v) static_bit_array final
|
|||
/// `size()` bits
|
||||
static constexpr size_type data_length_ = utils::quotient_ceiling(Nbits, bits_per_word);
|
||||
public:
|
||||
HEDLEY_NO_THROW
|
||||
constexpr static_bit_array(static_bit_array &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr static_bit_array(const static_bit_array &) noexcept = default;
|
||||
~static_bit_array() = default;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr static_bit_array & operator=(static_bit_array &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr static_bit_array & operator=(const static_bit_array &) noexcept = default;
|
||||
/// @brief constructs a zeroed `static_bit_array` that holds `Nbits` bits
|
||||
inline constexpr static_bit_array()
|
||||
|
|
@ -1459,6 +1505,7 @@ class alignas(utils::max_align_v) static_bit_array final
|
|||
/// @brief returns the number of bits
|
||||
/// @returns number of bits that the `static_bit_array` holds
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr size_type size() const noexcept
|
||||
|
|
@ -1509,6 +1556,7 @@ class dynamic_bit_array
|
|||
std::copy_n(other.data_.get(), data_length_ + 1, data_.get());
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
dynamic_bit_array(dynamic_bit_array && other) noexcept
|
||||
: num_bits_{std::exchange(other.num_bits_, 0)},
|
||||
data_length_{std::exchange(other.data_length_, 0)},
|
||||
|
|
@ -1525,6 +1573,7 @@ class dynamic_bit_array
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
dynamic_bit_array & operator=(dynamic_bit_array && other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
|
|
@ -1537,6 +1586,7 @@ class dynamic_bit_array
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
~dynamic_bit_array() noexcept
|
||||
{
|
||||
|
|
@ -1595,6 +1645,7 @@ class dynamic_bit_array
|
|||
/// @brief returns the number of bits
|
||||
/// @returns number of bits that the `dynamic_bit_array` holds
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr size_type size() const noexcept
|
||||
|
|
@ -1603,6 +1654,8 @@ class dynamic_bit_array
|
|||
}
|
||||
|
||||
private:
|
||||
/// Store zeros through `volatile` so the wipe is not deleted as a dead store.
|
||||
HEDLEY_NO_THROW
|
||||
void wipe() noexcept
|
||||
{
|
||||
if (!data_) return;
|
||||
|
|
@ -1620,6 +1673,7 @@ class dynamic_bit_array
|
|||
|
||||
/// @brief
|
||||
template <typename WordT>
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr void swap(typename dynamic_bit_array<WordT>::reference lhs,
|
||||
typename dynamic_bit_array<WordT>::reference rhs) noexcept
|
||||
{
|
||||
|
|
@ -1630,6 +1684,7 @@ inline constexpr void swap(typename dynamic_bit_array<WordT>::reference lhs,
|
|||
|
||||
template <std::size_t Nbits,
|
||||
typename WordT>
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr void swap(typename static_bit_array<Nbits, WordT>::reference lhs,
|
||||
typename static_bit_array<Nbits, WordT>::reference rhs) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -187,7 +187,9 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
|
||||
/// @}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
bitstring & operator=(const bitstring &) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
bitstring & operator=(bitstring &&) noexcept = default;
|
||||
~bitstring() = default;
|
||||
|
||||
|
|
@ -387,6 +389,7 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
using base::flip;
|
||||
|
||||
/// @brief Flips every defined bit and clears bits above `Nbits`.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr void flip() noexcept
|
||||
{
|
||||
base::flip();
|
||||
|
|
@ -468,6 +471,7 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
/// @note Does not perform bounds checking; behaviour is undefined if
|
||||
/// `pos` is out of bounds
|
||||
/// @return `data()[pos]`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr word_type data(size_type pos) const noexcept
|
||||
{
|
||||
|
|
@ -480,6 +484,7 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
/// @note Does not perform bounds checking; behaviour is undefined if
|
||||
/// `pos` is out of bounds
|
||||
/// @return `data()[pos]`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr word_type & data(size_type pos) noexcept
|
||||
{
|
||||
|
|
@ -488,6 +493,7 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
|
||||
/// @brief length of the underlying data array
|
||||
/// @return the number of elements in the underlying array
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr size_type data_length() const noexcept
|
||||
{
|
||||
|
|
@ -497,6 +503,7 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
/// @brief returns the number of bits
|
||||
/// @returns number of bits that the `bitstring` holds
|
||||
/// @complexity `O(1)`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr size_type size() const noexcept
|
||||
|
|
@ -510,6 +517,7 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
std::array<word_type, data_length_> data_{};
|
||||
|
||||
/// @brief Mask of the bits that belong to this string in the high word.
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr word_type defined_high_mask() noexcept
|
||||
{
|
||||
constexpr auto rem = Nbits % bits_per_word;
|
||||
|
|
@ -519,6 +527,7 @@ class bitstring : public bit_array_base<bitstring<Nbits, WordT>, WordT>
|
|||
return static_cast<word_type>((word_type{1} << rem) - word_type{1});
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
constexpr void clear_unused() noexcept
|
||||
{
|
||||
if constexpr (Nbits % bits_per_word != 0)
|
||||
|
|
@ -630,6 +639,7 @@ struct countl_zero_symmetric_difference<dpf::bitstring<Nbits, WordT>>
|
|||
{
|
||||
using T = dpf::bitstring<Nbits, WordT>;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr
|
||||
|
|
@ -706,6 +716,7 @@ struct make_from_integral_value<dpf::bitstring<Nbits, WordT>>
|
|||
using integral_type = std::conditional_t<std::is_void_v<T_integral_type>, simde_uint128, T_integral_type>;
|
||||
static constexpr auto mod = utils::mod_pow_2<integral_type>{};
|
||||
static constexpr auto bits_per_last_word = Nbits % T::bits_per_word;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr dpf::bitstring<Nbits, WordT> operator()(integral_type val) const noexcept
|
||||
{
|
||||
dpf::bitstring<Nbits, WordT> ret;
|
||||
|
|
@ -731,6 +742,7 @@ struct mod_pow_2<dpf::bitstring<Nbits, WordT>>
|
|||
using T = dpf::bitstring<Nbits, WordT>;
|
||||
static constexpr auto to_int = to_integral_type<T>{};
|
||||
static constexpr auto mod = mod_pow_2<typename T::integral_type>{};
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t operator()(T val, std::size_t n) const noexcept
|
||||
{
|
||||
return mod(to_int(val), n);
|
||||
|
|
@ -1141,14 +1153,23 @@ class numeric_limits<dpf::bitstring<Nbits, WordT>>
|
|||
= std::numeric_limits<typename dpf::bitstring<Nbits, WordT>::integral_type>::traps;
|
||||
static constexpr bool tinyness_before = false;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> min() noexcept { return dpf::bitstring<Nbits, WordT>{}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> lowest() noexcept { return dpf::bitstring<Nbits, WordT>{}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> max() noexcept { return ~dpf::bitstring<Nbits, WordT>{}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> epsilon() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> round_error() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> infinity() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> quiet_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> signaling_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::bitstring<Nbits, WordT> denorm_min() noexcept { return 0; }
|
||||
};
|
||||
|
||||
|
|
|
|||
475
include/dpf/blocked_dcf.hpp
Normal file
475
include/dpf/blocked_dcf.hpp
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
/// @file dpf/blocked_dcf.hpp
|
||||
/// @brief Blocked-checkpoint comparison: one ring word per block of levels.
|
||||
/// @details The seed spine stays dense. Ring words are published only at a
|
||||
/// public checkpoint schedule. Point eval expands parked siblings
|
||||
/// up to the next checkpoint; a full-domain memoizer already holds
|
||||
/// those nodes. `q` tail bits, when the comparison sets the key
|
||||
/// depth, are a residual table on the node at height `h`.
|
||||
/// @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_BLOCKED_DCF_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_BLOCKED_DCF_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
|
||||
#include "dpf/dcf.hpp"
|
||||
#include "dpf/path_memoizer.hpp"
|
||||
#include "dpf/twiddle.hpp"
|
||||
#include "dpf/utils.hpp"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace blocked
|
||||
{
|
||||
|
||||
template <std::size_t H, std::size_t B>
|
||||
struct schedule
|
||||
{
|
||||
static constexpr std::size_t count =
|
||||
(B == 0 || H == 0) ? 0 : (H + B - 1) / B;
|
||||
|
||||
static constexpr auto depths = [] {
|
||||
std::array<std::size_t, count == 0 ? 1 : count> cs{};
|
||||
if constexpr (count == 0)
|
||||
return cs;
|
||||
const std::size_t base = H / count;
|
||||
const std::size_t extra = H % count;
|
||||
std::size_t acc = 0;
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
acc += base + (i < extra ? 1 : 0);
|
||||
cs[i] = acc;
|
||||
}
|
||||
return cs;
|
||||
}();
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr bool contains(std::size_t depth) noexcept
|
||||
{
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (depths[i] == depth)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr std::size_t index(std::size_t depth) noexcept
|
||||
{
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (depths[i] == depth)
|
||||
return i;
|
||||
}
|
||||
return static_cast<std::size_t>(-1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename PRG, typename Node>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t rho_of(const Node & node, uint64_t mask) noexcept
|
||||
{
|
||||
auto kids = PRG::eval01(dpf::unset_lo_2bits(node));
|
||||
return dcf_impl::convert_node(kids[0], mask);
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr int control_sign(uint8_t t0, uint8_t t1) noexcept
|
||||
{
|
||||
return static_cast<int>(t0) - static_cast<int>(t1);
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t mul_sgn(int sgn, uint64_t v, uint64_t mask) noexcept
|
||||
{
|
||||
if (sgn > 0)
|
||||
return v & mask;
|
||||
if (sgn < 0)
|
||||
return dcf_impl::neg_m(v, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Group element `sgn` (`+1`, `-1`, or `0`) used as an `assign_cmp` coefficient.
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t sgn_coeff(int sgn, uint64_t mask) noexcept
|
||||
{
|
||||
if (sgn > 0)
|
||||
return 1ULL & mask;
|
||||
if (sgn < 0)
|
||||
return dcf_impl::neg_m(1ULL, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename PRG, typename Node>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t checkpoint_word(const Node & n0, const Node & n1, uint64_t beta,
|
||||
uint64_t mask) noexcept
|
||||
{
|
||||
const int sgn = control_sign(
|
||||
static_cast<uint8_t>(dpf::get_lo_bit(n0)),
|
||||
static_cast<uint8_t>(dpf::get_lo_bit(n1)));
|
||||
const uint64_t r0 = rho_of<PRG>(n0, mask);
|
||||
const uint64_t r1 = rho_of<PRG>(n1, mask);
|
||||
const uint64_t inner =
|
||||
(beta + dcf_impl::neg_m(r0, mask) + r1) & mask;
|
||||
return mul_sgn(sgn, inner, mask);
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t checkpoint_coeff(const Node & n0, const Node & n1,
|
||||
uint64_t mask) noexcept
|
||||
{
|
||||
return sgn_coeff(control_sign(
|
||||
static_cast<uint8_t>(dpf::get_lo_bit(n0)),
|
||||
static_cast<uint8_t>(dpf::get_lo_bit(n1))), mask);
|
||||
}
|
||||
|
||||
template <typename PRG, typename Node>
|
||||
HEDLEY_NON_NULL(4)
|
||||
HEDLEY_NO_THROW
|
||||
void suffix_masks(const Node & seed, std::size_t q, uint64_t mask,
|
||||
uint64_t * out) noexcept
|
||||
{
|
||||
Node cur[4]{};
|
||||
Node nxt[8]{};
|
||||
cur[0] = seed;
|
||||
std::size_t n = 1;
|
||||
for (std::size_t lvl = 0; lvl < q; ++lvl)
|
||||
{
|
||||
std::size_t m = 0;
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
auto kids = PRG::eval01(dpf::unset_lo_2bits(cur[i]));
|
||||
nxt[m++] = kids[0];
|
||||
nxt[m++] = kids[1];
|
||||
}
|
||||
for (std::size_t i = 0; i < m; ++i)
|
||||
cur[i] = nxt[i];
|
||||
n = m;
|
||||
}
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
out[i] = dcf_impl::convert_node(cur[i], mask);
|
||||
}
|
||||
|
||||
template <typename PRG, typename Node>
|
||||
HEDLEY_NON_NULL(8)
|
||||
HEDLEY_NO_THROW
|
||||
void tail_words(const Node & n0, const Node & n1, uint64_t beta, uint64_t mask,
|
||||
bool include_eq, uint64_t suffix, std::size_t q, uint64_t * words,
|
||||
uint64_t * coeffs) noexcept
|
||||
{
|
||||
uint64_t u0[4]{};
|
||||
uint64_t u1[4]{};
|
||||
suffix_masks<PRG>(n0, q, mask, u0);
|
||||
suffix_masks<PRG>(n1, q, mask, u1);
|
||||
const int sgn = control_sign(
|
||||
static_cast<uint8_t>(dpf::get_lo_bit(n0)),
|
||||
static_cast<uint8_t>(dpf::get_lo_bit(n1)));
|
||||
const uint64_t coeff = sgn_coeff(sgn, mask);
|
||||
const std::size_t n = std::size_t{1} << q;
|
||||
for (std::size_t z = 0; z < n; ++z)
|
||||
{
|
||||
const bool pred = include_eq
|
||||
? (z <= suffix)
|
||||
: (z < suffix);
|
||||
const uint64_t inner =
|
||||
((pred ? beta : 0ULL) + dcf_impl::neg_m(u0[z], mask) + u1[z]) & mask;
|
||||
words[z] = mul_sgn(sgn, inner, mask);
|
||||
if (coeffs != nullptr)
|
||||
coeffs[z] = pred ? coeff : 0ULL;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename KeyT>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t add_membership(uint64_t acc, const typename KeyT::interior_node & node,
|
||||
uint64_t word, uint64_t mask, int party) noexcept
|
||||
{
|
||||
using prg = typename KeyT::interior_prg;
|
||||
const uint8_t t = static_cast<uint8_t>(dpf::get_lo_bit(node));
|
||||
const uint64_t y =
|
||||
(rho_of<prg>(node, mask) + (t ? word : 0ULL)) & mask;
|
||||
return (acc + (party ? dcf_impl::neg_m(y, mask) : y)) & mask;
|
||||
}
|
||||
|
||||
template <typename KeyT>
|
||||
uint64_t add_frontier(uint64_t acc, const typename KeyT::interior_node & seed,
|
||||
std::size_t from_depth, std::size_t to_depth, const KeyT & dpf, uint64_t word,
|
||||
uint64_t mask, int party)
|
||||
{
|
||||
using node = typename KeyT::interior_node;
|
||||
std::vector<node> cur;
|
||||
std::vector<node> nxt;
|
||||
cur.push_back(seed);
|
||||
for (std::size_t lvl = from_depth; lvl < to_depth; ++lvl)
|
||||
{
|
||||
nxt.clear();
|
||||
nxt.reserve(cur.size() * 2);
|
||||
const node cw0 = dpf.correction_word(lvl, false);
|
||||
const node cw1 = dpf.correction_word(lvl, true);
|
||||
for (const node & fs : cur)
|
||||
{
|
||||
auto kids = KeyT::traverse_interior01(fs, cw0, cw1);
|
||||
nxt.push_back(kids[0]);
|
||||
nxt.push_back(kids[1]);
|
||||
}
|
||||
cur.swap(nxt);
|
||||
}
|
||||
for (const node & fs : cur)
|
||||
acc = add_membership<KeyT>(acc, fs, word, mask, party);
|
||||
return acc;
|
||||
}
|
||||
|
||||
template <typename KeyT, typename InputT>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t query_suffix(InputT tx, std::size_t nbits, std::size_t q) noexcept
|
||||
{
|
||||
if (q == 0)
|
||||
return 0;
|
||||
uint64_t z = 0;
|
||||
auto bit_mask = KeyT::msb_mask >> (nbits - q);
|
||||
for (std::size_t j = 0; j < q; ++j, bit_mask >>= 1)
|
||||
z = (z << 1) | static_cast<uint64_t>(!!(bit_mask & tx));
|
||||
return z;
|
||||
}
|
||||
|
||||
template <typename KeyT>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t finish_share(const KeyT & dpf, uint64_t suffix, uint64_t acc,
|
||||
const typename KeyT::interior_node & at_h, int party) noexcept
|
||||
{
|
||||
using namespace dcf_impl;
|
||||
using prg = typename KeyT::interior_prg;
|
||||
const auto & ch = dpf.cmp();
|
||||
const uint64_t mask = ch.mask;
|
||||
constexpr std::size_t q = KeyT::cmp_q;
|
||||
constexpr std::size_t h = KeyT::cmp_h;
|
||||
if constexpr (q == 0)
|
||||
{
|
||||
if (ch.include_eq)
|
||||
{
|
||||
constexpr auto wi = schedule<h, KeyT::cmp_block>::index(h);
|
||||
acc = add_membership<KeyT>(acc, at_h, dpf.value_cw(wi), mask, party);
|
||||
}
|
||||
(void)suffix;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint64_t z = suffix;
|
||||
uint64_t u[4]{};
|
||||
suffix_masks<prg>(at_h, q, mask, u);
|
||||
const uint8_t t = static_cast<uint8_t>(dpf::get_lo_bit(at_h));
|
||||
const uint64_t y = (u[z] + (t ? dpf.tail_cw(z) : 0ULL)) & mask;
|
||||
acc = (acc + (party ? neg_m(y, mask) : y)) & mask;
|
||||
}
|
||||
if (ch.eval_as_ge)
|
||||
acc = neg_m(acc, mask);
|
||||
const uint64_t add = [&]() -> uint64_t {
|
||||
if constexpr (is_party_key_v<KeyT>)
|
||||
return dpf.cmp_addend().raw();
|
||||
else
|
||||
return dpf.cmp_addend();
|
||||
}();
|
||||
return (acc + add) & mask;
|
||||
}
|
||||
|
||||
template <typename KeyT, typename InputT, typename PathMemoizer>
|
||||
uint64_t eval_share(const KeyT & dpf, InputT tx, PathMemoizer & path)
|
||||
{
|
||||
using node = typename KeyT::interior_node;
|
||||
const auto & ch = dpf.cmp();
|
||||
const uint64_t mask = ch.mask;
|
||||
const uint64_t add = [&]() -> uint64_t {
|
||||
if constexpr (is_party_key_v<KeyT>)
|
||||
return dpf.cmp_addend().raw();
|
||||
else
|
||||
return dpf.cmp_addend();
|
||||
}();
|
||||
if (ch.trivial == cmp_trivial::always_true
|
||||
|| ch.trivial == cmp_trivial::always_false)
|
||||
return add & mask;
|
||||
|
||||
constexpr std::size_t h = KeyT::cmp_h;
|
||||
using sched = schedule<h, KeyT::cmp_block>;
|
||||
const std::size_t nbits = static_cast<std::size_t>(ch.nbits);
|
||||
const int party = dpf::get_lo_bit(dpf.root()) ? 1 : 0;
|
||||
|
||||
dpf::detail::ensure_level(dpf, tx, path, h);
|
||||
|
||||
struct parked
|
||||
{
|
||||
node seed;
|
||||
std::size_t depth;
|
||||
};
|
||||
parked pend[128];
|
||||
std::size_t npend = 0;
|
||||
|
||||
uint64_t acc = 0;
|
||||
auto bit_mask = KeyT::msb_mask;
|
||||
for (std::size_t level = 0; level < h; ++level, bit_mask >>= 1)
|
||||
{
|
||||
const bool xi = !!(bit_mask & tx);
|
||||
const node & parent = path[level];
|
||||
const node right = KeyT::traverse_interior(parent,
|
||||
dpf.correction_word(level, true), true);
|
||||
if (!xi)
|
||||
{
|
||||
pend[npend].seed = right;
|
||||
pend[npend].depth = level + 1;
|
||||
++npend;
|
||||
}
|
||||
const std::size_t c = level + 1;
|
||||
if (sched::contains(c))
|
||||
{
|
||||
const uint64_t word = dpf.value_cw(sched::index(c));
|
||||
for (std::size_t p = 0; p < npend; ++p)
|
||||
{
|
||||
acc = add_frontier<KeyT>(acc, pend[p].seed, pend[p].depth, c,
|
||||
dpf, word, mask, party);
|
||||
}
|
||||
npend = 0;
|
||||
}
|
||||
}
|
||||
const uint64_t suffix = query_suffix<KeyT>(tx, nbits, KeyT::cmp_q);
|
||||
return finish_share(dpf, suffix, acc, path[h], party);
|
||||
}
|
||||
|
||||
template <typename KeyT, typename Integral, typename Memo>
|
||||
HEDLEY_NO_THROW
|
||||
bool memo_has(const Memo & memo, Integral prefix, std::size_t depth,
|
||||
Integral from_lane, Integral to_excl) noexcept
|
||||
{
|
||||
const auto shift = KeyT::cmp_depth - depth;
|
||||
const auto from_p = from_lane >> shift;
|
||||
if (prefix < from_p)
|
||||
return false;
|
||||
const auto idx = static_cast<std::size_t>(prefix - from_p);
|
||||
const auto count = memo.get_nodes_at_level(depth, from_lane, to_excl);
|
||||
return idx < count;
|
||||
}
|
||||
|
||||
template <typename KeyT, typename Integral, typename Memo>
|
||||
const typename KeyT::interior_node & memo_node(const Memo & memo, Integral prefix,
|
||||
std::size_t depth, Integral from_lane)
|
||||
{
|
||||
const auto shift = KeyT::cmp_depth - depth;
|
||||
const auto from_p = from_lane >> shift;
|
||||
const auto idx = static_cast<std::size_t>(prefix - from_p);
|
||||
return memo[depth][idx];
|
||||
}
|
||||
|
||||
template <typename KeyT, typename Integral, typename Memo>
|
||||
uint64_t eval_share_memo(const KeyT & dpf, Integral lane,
|
||||
Integral from_lane, Integral to_excl, const Memo & memo)
|
||||
{
|
||||
using node = typename KeyT::interior_node;
|
||||
const auto & ch = dpf.cmp();
|
||||
const uint64_t mask = ch.mask;
|
||||
const uint64_t add = [&]() -> uint64_t {
|
||||
if constexpr (is_party_key_v<KeyT>)
|
||||
return dpf.cmp_addend().raw();
|
||||
else
|
||||
return dpf.cmp_addend();
|
||||
}();
|
||||
if (ch.trivial == cmp_trivial::always_true
|
||||
|| ch.trivial == cmp_trivial::always_false)
|
||||
return add & mask;
|
||||
|
||||
constexpr std::size_t h = KeyT::cmp_h;
|
||||
using sched = schedule<h, KeyT::cmp_block>;
|
||||
const int party = dpf::get_lo_bit(dpf.root()) ? 1 : 0;
|
||||
|
||||
struct parked
|
||||
{
|
||||
node seed;
|
||||
Integral prefix;
|
||||
std::size_t depth;
|
||||
};
|
||||
parked pend[128];
|
||||
std::size_t npend = 0;
|
||||
|
||||
uint64_t acc = 0;
|
||||
Integral path_pref = 0;
|
||||
const std::size_t nbits = static_cast<std::size_t>(ch.nbits);
|
||||
for (std::size_t level = 0; level < h; ++level)
|
||||
{
|
||||
const bool xi = ((lane >> (nbits - 1 - level)) & Integral{1}) != 0;
|
||||
const node & parent = memo_node<KeyT>(memo, path_pref, level, from_lane);
|
||||
const Integral sib = static_cast<Integral>((path_pref << 1) | Integral{1});
|
||||
if (!xi)
|
||||
{
|
||||
const node right = KeyT::traverse_interior(parent,
|
||||
dpf.correction_word(level, true), true);
|
||||
pend[npend].seed = right;
|
||||
pend[npend].prefix = sib;
|
||||
pend[npend].depth = level + 1;
|
||||
++npend;
|
||||
}
|
||||
path_pref = static_cast<Integral>((path_pref << 1) | Integral{xi ? 1 : 0});
|
||||
const std::size_t c = level + 1;
|
||||
if (!sched::contains(c))
|
||||
continue;
|
||||
const uint64_t word = dpf.value_cw(sched::index(c));
|
||||
for (std::size_t p = 0; p < npend; ++p)
|
||||
{
|
||||
const std::size_t extra = c - pend[p].depth;
|
||||
const Integral leftmost =
|
||||
static_cast<Integral>(pend[p].prefix << extra);
|
||||
const Integral rightmost = static_cast<Integral>(
|
||||
leftmost + static_cast<Integral>((Integral{1} << extra) - 1));
|
||||
const bool covered =
|
||||
memo_has<KeyT>(memo, leftmost, c, from_lane, to_excl)
|
||||
&& memo_has<KeyT>(memo, rightmost, c, from_lane, to_excl);
|
||||
if (covered && extra < 16)
|
||||
{
|
||||
const Integral nleaf = static_cast<Integral>(Integral{1} << extra);
|
||||
for (Integral k = 0; k < nleaf; ++k)
|
||||
{
|
||||
const auto pref = static_cast<Integral>(leftmost + k);
|
||||
acc = add_membership<KeyT>(acc,
|
||||
memo_node<KeyT>(memo, pref, c, from_lane), word, mask,
|
||||
party);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
acc = add_frontier<KeyT>(acc, pend[p].seed, pend[p].depth, c,
|
||||
dpf, word, mask, party);
|
||||
}
|
||||
}
|
||||
npend = 0;
|
||||
}
|
||||
const node & at_h = memo_node<KeyT>(memo, path_pref, h, from_lane);
|
||||
const uint64_t suffix = static_cast<uint64_t>(lane)
|
||||
& (KeyT::cmp_q == 0 ? 0ULL : ((1ULL << KeyT::cmp_q) - 1ULL));
|
||||
return finish_share(dpf, suffix, acc, at_h, party);
|
||||
}
|
||||
|
||||
} // namespace blocked
|
||||
} // namespace detail
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_BLOCKED_DCF_HPP__
|
||||
|
|
@ -39,6 +39,7 @@ namespace detail
|
|||
{
|
||||
|
||||
template <typename PRG>
|
||||
HEDLEY_NO_THROW
|
||||
typename PRG::block_type mask_master(typename PRG::block_type master) noexcept
|
||||
{
|
||||
unsigned char raw[sizeof(master)];
|
||||
|
|
@ -140,6 +141,7 @@ struct buffered_slot
|
|||
return lane_codec<PRG, T>::at(seed_, index);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
std::uint64_t sampled() const noexcept { return absolute_pos_; }
|
||||
|
||||
private:
|
||||
|
|
@ -165,7 +167,13 @@ typename PRG::block_type sample_master_seed()
|
|||
return dpf::uniform_sample<typename PRG::block_type>();
|
||||
}
|
||||
|
||||
/// Fixed lanes. Lane `I` is `PRG::eval(master, I)`.
|
||||
/// Forward cursor over one PRG stream per value type.
|
||||
///
|
||||
/// `get<I>()` and `fill<I>()` consume the cursor. `at<I>(index)` reads an
|
||||
/// absolute index and leaves the cursor where it is. `sampled<I>()` reports
|
||||
/// how far `get` and `fill` have advanced. `per_stream_buffer_elems` is at
|
||||
/// least 1.
|
||||
/// @snippet evaluation/buffered_prg.cpp buffered-prg
|
||||
template <typename PRG, typename... Ts>
|
||||
class buffered_prg
|
||||
{
|
||||
|
|
@ -184,6 +192,7 @@ public:
|
|||
buffers_(make_buffers(per_stream_buffer_elems))
|
||||
{ }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const seed_type & seed() const noexcept { return seed_; }
|
||||
|
||||
template <std::size_t I>
|
||||
|
|
@ -208,6 +217,7 @@ public:
|
|||
}
|
||||
|
||||
template <std::size_t I>
|
||||
HEDLEY_NO_THROW
|
||||
std::uint64_t sampled() const noexcept
|
||||
{
|
||||
static_assert(I < stream_count, "stream index out of range");
|
||||
|
|
@ -238,9 +248,12 @@ private:
|
|||
template <typename... Ts>
|
||||
using aes_buffered_prg = buffered_prg<dpf::prg::aes128, Ts...>;
|
||||
|
||||
/// Dynamic lanes of one value type. `value_at(role, index)` and
|
||||
/// `mask_at(role, index)` are independent of call order. A window cache
|
||||
/// refills from the requested index.
|
||||
/// Seekable value and mask streams for a runtime set of roles.
|
||||
///
|
||||
/// `value_at(role, index)` and `mask_at(role, index)` are independent of
|
||||
/// call order. A repeated index returns the same element. `window` is at
|
||||
/// least 1.
|
||||
/// @snippet evaluation/buffered_prg.cpp lane-table
|
||||
template <typename T, typename PRG = dpf::prg::aes128>
|
||||
class lane_table
|
||||
{
|
||||
|
|
@ -267,6 +280,7 @@ public:
|
|||
lane_table(lane_table &&) = default;
|
||||
lane_table & operator=(lane_table &&) = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const seed_type & seed() const noexcept { return seed_; }
|
||||
|
||||
T value_at(std::uint32_t role, std::uint64_t index) const
|
||||
|
|
|
|||
|
|
@ -26,15 +26,61 @@
|
|||
namespace dpf
|
||||
{
|
||||
|
||||
template <typename Beta>
|
||||
struct ic_pack;
|
||||
|
||||
template <typename T>
|
||||
struct is_ic_pack : std::false_type {};
|
||||
|
||||
template <typename Beta>
|
||||
struct is_ic_pack<ic_pack<Beta>> : std::true_type {};
|
||||
|
||||
template <typename ...Ts>
|
||||
inline constexpr bool no_ic_pack_v =
|
||||
(!is_ic_pack<std::decay_t<Ts>>::value && ...);
|
||||
|
||||
/// Comparison kind for the optional DCF channel on a key.
|
||||
/// `lt`/`leq`/`gt`/`geq` are the comparison predicates. The later kinds are
|
||||
/// path paints: one constant on each sibling subtree of the secret point,
|
||||
/// evaluated by the same value-correction walk.
|
||||
enum class cmp_kind : uint8_t
|
||||
{
|
||||
lt = 0,
|
||||
leq = 1,
|
||||
gt = 2,
|
||||
geq = 3
|
||||
geq = 3,
|
||||
lcp = 4, // common-prefix length
|
||||
prefix = 5, // matched prefix, in the lane's high bits
|
||||
mask = 6, // high-bit mask of that length
|
||||
one_hot = 7, // 2^{length} (0 when the bit does not fit)
|
||||
break_bit = 8, // secret bit at the first difference
|
||||
prefix_with_length = 9, // (low-aligned prefix << length_bits) | length
|
||||
paint = 10 // caller-supplied unit plant
|
||||
};
|
||||
|
||||
/// True for the path-paint kinds. Comparisons stay `lt`/`leq`/`gt`/`geq`.
|
||||
HEDLEY_NO_THROW
|
||||
inline constexpr bool is_paint_kind(cmp_kind kind) noexcept
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case cmp_kind::lcp:
|
||||
case cmp_kind::prefix:
|
||||
case cmp_kind::mask:
|
||||
case cmp_kind::one_hot:
|
||||
case cmp_kind::break_bit:
|
||||
case cmp_kind::prefix_with_length:
|
||||
case cmp_kind::paint:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Unit plant for `path_paint`. `prefix` is the in-lane matched prefix.
|
||||
using paint_callback = uint64_t (*)(std::size_t matched, uint64_t prefix,
|
||||
bool leaf, const void * ctx);
|
||||
|
||||
enum class cmp_trivial : uint8_t
|
||||
{
|
||||
none = 0,
|
||||
|
|
@ -48,6 +94,7 @@ namespace dcf_impl
|
|||
{
|
||||
|
||||
template <typename Beta>
|
||||
HEDLEY_NO_THROW
|
||||
Beta default_false() noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<Beta, dpf::bit>)
|
||||
|
|
@ -57,6 +104,7 @@ Beta default_false() noexcept
|
|||
}
|
||||
|
||||
template <typename Beta>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t beta_delta_u64(const Beta & if_true, const Beta & if_false,
|
||||
uint64_t mask) noexcept
|
||||
{
|
||||
|
|
@ -79,6 +127,7 @@ uint64_t beta_delta_u64(const Beta & if_true, const Beta & if_false,
|
|||
}
|
||||
|
||||
template <typename Beta>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t beta_to_u64_simple(const Beta & beta, uint64_t mask) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<Beta, dpf::bit>)
|
||||
|
|
@ -88,6 +137,7 @@ uint64_t beta_to_u64_simple(const Beta & beta, uint64_t mask) noexcept
|
|||
}
|
||||
|
||||
template <typename Beta>
|
||||
HEDLEY_NO_THROW
|
||||
Beta sub_beta(const Beta & a, const Beta & b) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<Beta, dpf::bit>)
|
||||
|
|
@ -99,6 +149,7 @@ Beta sub_beta(const Beta & a, const Beta & b) noexcept
|
|||
}
|
||||
|
||||
template <typename Beta>
|
||||
HEDLEY_NO_THROW
|
||||
Beta u64_to_beta(uint64_t v) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<Beta, dpf::bit>)
|
||||
|
|
@ -107,7 +158,10 @@ Beta u64_to_beta(uint64_t v) noexcept
|
|||
return static_cast<Beta>(v);
|
||||
}
|
||||
|
||||
inline uint64_t default_mask_for_bits(std::size_t out_bits) noexcept
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t default_mask_for_bits(std::size_t out_bits) noexcept
|
||||
{
|
||||
if (out_bits >= 64)
|
||||
return ~0ULL;
|
||||
|
|
@ -116,14 +170,18 @@ inline uint64_t default_mask_for_bits(std::size_t out_bits) noexcept
|
|||
return (1ULL << out_bits) - 1ULL;
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
uint64_t neg_m(uint64_t x, uint64_t mask) noexcept
|
||||
constexpr uint64_t neg_m(uint64_t x, uint64_t mask) noexcept
|
||||
{
|
||||
return (0ULL - x) & mask;
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
uint64_t sgn_m(uint8_t t1, uint64_t x, uint64_t mask) noexcept
|
||||
constexpr uint64_t sgn_m(uint8_t t1, uint64_t x, uint64_t mask) noexcept
|
||||
{
|
||||
return t1 ? neg_m(x, mask) : x;
|
||||
}
|
||||
|
|
@ -143,6 +201,7 @@ uint64_t convert_node(simde__m128i n, uint64_t mask) noexcept
|
|||
/// same block source so their keys stay byte-identical (matched tapes).
|
||||
template <typename BlockSampler>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t sample_addend_blind(uint64_t mask, BlockSampler && sample) noexcept
|
||||
{
|
||||
return convert_node(dpf::unset_lo_2bits(sample()), mask);
|
||||
|
|
@ -150,6 +209,7 @@ uint64_t sample_addend_blind(uint64_t mask, BlockSampler && sample) noexcept
|
|||
|
||||
/// One level of value CW on GGM children. Updates running `Va`.
|
||||
/// `ai` is the keep-path bit of the (effective) threshold.
|
||||
HEDLEY_NO_THROW
|
||||
inline uint64_t make_value_cw(simde__m128i c0L, simde__m128i c0R,
|
||||
simde__m128i c1L, simde__m128i c1R, uint8_t t0, uint8_t t1, int ai,
|
||||
uint64_t & Va, uint64_t beta, uint64_t mask) noexcept
|
||||
|
|
@ -179,8 +239,127 @@ inline uint64_t make_value_cw(simde__m128i c0L, simde__m128i c0R,
|
|||
return vcw;
|
||||
}
|
||||
|
||||
/// Same recurrence as `make_value_cw`, planting `plant` on the lose child
|
||||
/// in both directions. `plant == 0` leaves the correction unchanged.
|
||||
HEDLEY_NO_THROW
|
||||
inline uint64_t make_value_cw_planted(simde__m128i c0L, simde__m128i c0R,
|
||||
simde__m128i c1L, simde__m128i c1R, uint8_t t0, uint8_t t1, int ai,
|
||||
uint64_t & Va, uint64_t plant, uint64_t mask) noexcept
|
||||
{
|
||||
(void)t0;
|
||||
uint64_t v0K, v1K, v0Lo, v1Lo;
|
||||
if (ai == 0)
|
||||
{
|
||||
v0K = convert_node(c0L, mask);
|
||||
v1K = convert_node(c1L, mask);
|
||||
v0Lo = convert_node(c0R, mask);
|
||||
v1Lo = convert_node(c1R, mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
v0K = convert_node(c0R, mask);
|
||||
v1K = convert_node(c1R, mask);
|
||||
v0Lo = convert_node(c0L, mask);
|
||||
v1Lo = convert_node(c1L, mask);
|
||||
}
|
||||
uint64_t vcw = sgn_m(t1,
|
||||
(v1Lo + neg_m(v0Lo, mask) + neg_m(Va, mask)) & mask, mask);
|
||||
vcw = (vcw + sgn_m(t1, plant, mask)) & mask;
|
||||
Va = (Va + neg_m(v1K, mask) + v0K + sgn_m(t1, vcw, mask)) & mask;
|
||||
return vcw;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline unsigned __int128 paint_lane_mask(std::size_t nbits) noexcept
|
||||
{
|
||||
using u128 = unsigned __int128;
|
||||
if (nbits == 0)
|
||||
return 0;
|
||||
if (nbits >= 128)
|
||||
return ~u128{0};
|
||||
return (u128{1} << nbits) - 1;
|
||||
}
|
||||
|
||||
/// High `d` bits of an `nbits`-wide lane, in that lane's own positions.
|
||||
HEDLEY_NO_THROW
|
||||
inline unsigned __int128 paint_high_bits(unsigned __int128 alpha,
|
||||
std::size_t nbits, std::size_t d) noexcept
|
||||
{
|
||||
alpha &= paint_lane_mask(nbits);
|
||||
if (d == 0 || nbits == 0)
|
||||
return 0;
|
||||
if (d >= nbits)
|
||||
return alpha;
|
||||
const std::size_t drop = nbits - d;
|
||||
return (alpha >> drop) << drop;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline unsigned __int128 paint_low_aligned(unsigned __int128 alpha,
|
||||
std::size_t nbits, std::size_t d) noexcept
|
||||
{
|
||||
alpha &= paint_lane_mask(nbits);
|
||||
if (d == 0 || nbits == 0)
|
||||
return 0;
|
||||
if (d >= nbits)
|
||||
return alpha;
|
||||
return alpha >> (nbits - d);
|
||||
}
|
||||
|
||||
/// Unit (β = 1) lose-subtree or leaf plant. The caller scales by δ.
|
||||
/// `matched` is the number of leading bits already shared with α. A lose
|
||||
/// subtree at that depth reconstructs to this value; `leaf` is the full match.
|
||||
inline uint64_t paint_unit(cmp_kind kind, std::size_t matched,
|
||||
unsigned __int128 alpha, std::size_t nbits, std::size_t length_bits,
|
||||
bool leaf, paint_callback fn, const void * ctx)
|
||||
{
|
||||
if (nbits == 0)
|
||||
return 0;
|
||||
const std::size_t d = leaf ? nbits : matched;
|
||||
switch (kind)
|
||||
{
|
||||
case cmp_kind::lcp:
|
||||
return static_cast<uint64_t>(d);
|
||||
case cmp_kind::prefix:
|
||||
return static_cast<uint64_t>(paint_high_bits(alpha, nbits, d));
|
||||
case cmp_kind::mask:
|
||||
return static_cast<uint64_t>(
|
||||
paint_high_bits(paint_lane_mask(nbits), nbits, d));
|
||||
case cmp_kind::one_hot:
|
||||
return d >= 64 ? 0ULL : (1ULL << d);
|
||||
case cmp_kind::break_bit:
|
||||
if (leaf || matched >= nbits)
|
||||
return 0;
|
||||
return static_cast<uint64_t>(
|
||||
(alpha >> (nbits - 1 - matched)) & 1);
|
||||
case cmp_kind::prefix_with_length:
|
||||
{
|
||||
if (length_bits >= 128)
|
||||
return static_cast<uint64_t>(d);
|
||||
unsigned __int128 packed =
|
||||
paint_low_aligned(alpha, nbits, d) << length_bits;
|
||||
packed |= static_cast<unsigned __int128>(d);
|
||||
return static_cast<uint64_t>(packed);
|
||||
}
|
||||
case cmp_kind::paint:
|
||||
if (fn == nullptr)
|
||||
return 0;
|
||||
return fn(d, static_cast<uint64_t>(paint_high_bits(alpha, nbits, d)),
|
||||
leaf, ctx);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline uint64_t scale_plant(uint64_t unit, uint64_t scale, uint64_t mask) noexcept
|
||||
{
|
||||
return (unit * scale) & mask;
|
||||
}
|
||||
|
||||
/// Final leaf value CW. `on_path` is the payload reconstructed when the query
|
||||
/// stays on α's path through all levels (0 for strict lt/geq; β for leq/gt).
|
||||
HEDLEY_NO_THROW
|
||||
inline uint64_t make_final_cw(simde__m128i s0, simde__m128i s1, uint8_t t1,
|
||||
uint64_t Va, uint64_t mask, uint64_t on_path = 0) noexcept
|
||||
{
|
||||
|
|
@ -206,7 +385,11 @@ struct cmp_meta
|
|||
bool eval_as_ge = false; // invert path-sum (geq / gt)
|
||||
bool include_eq = false; // plant δ on the α-path leaf (leq / gt)
|
||||
bool active = false;
|
||||
bool incremental = false; // final correction saved at every depth
|
||||
int block_width = 0; // 0 = per-level path-sum
|
||||
int tail_bits = 0; // residual q; 0 when the tree covers every bit
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
bool empty() const noexcept { return !active; }
|
||||
};
|
||||
|
||||
|
|
@ -225,6 +408,7 @@ struct cmp_pack
|
|||
static constexpr bool is_cmp = true;
|
||||
static constexpr cmp_kind kind = Kind;
|
||||
static constexpr std::size_t prefix = 0;
|
||||
static constexpr std::size_t block_width = 0;
|
||||
using beta_type = Beta;
|
||||
Beta if_true;
|
||||
Beta if_false;
|
||||
|
|
@ -239,6 +423,7 @@ struct cmp_at_pack
|
|||
static constexpr bool is_cmp = true;
|
||||
static constexpr cmp_kind kind = Kind;
|
||||
static constexpr std::size_t prefix = N;
|
||||
static constexpr std::size_t block_width = 0;
|
||||
using beta_type = Beta;
|
||||
Beta if_true;
|
||||
Beta if_false;
|
||||
|
|
@ -289,6 +474,228 @@ inline auto geq_at(Beta t, Beta f = detail::dcf_impl::default_false<std::decay_t
|
|||
return cmp_at_pack<N, cmp_kind::geq, std::decay_t<Beta>>(std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Path paints. Same channel and same (if_true, if_false) scale as a comparison:
|
||||
// the reconstructed value is if_false + (if_true − if_false) · unit(x).
|
||||
// `unit` is the common-prefix length, the matched prefix, a mask, and so on.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct spec_is_incremental : std::false_type {};
|
||||
template <typename T>
|
||||
struct spec_is_incremental<T, std::void_t<decltype(T::incremental)>>
|
||||
: std::bool_constant<T::incremental> {};
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct spec_length_bits : std::integral_constant<std::size_t, 0> {};
|
||||
template <typename T>
|
||||
struct spec_length_bits<T, std::void_t<decltype(T::length_bits)>>
|
||||
: std::integral_constant<std::size_t, T::length_bits> {};
|
||||
|
||||
template <cmp_kind Kind, typename Beta, std::size_t LengthBits = 0>
|
||||
struct paint_pack
|
||||
{
|
||||
static constexpr bool is_cmp = true;
|
||||
static constexpr cmp_kind kind = Kind;
|
||||
static constexpr std::size_t prefix = 0;
|
||||
static constexpr std::size_t block_width = 0;
|
||||
static constexpr std::size_t length_bits = LengthBits;
|
||||
static constexpr bool incremental = false;
|
||||
using beta_type = Beta;
|
||||
Beta if_true;
|
||||
Beta if_false;
|
||||
|
||||
explicit paint_pack(Beta t, Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
: if_true{std::move(t)}, if_false{std::move(f)} { }
|
||||
};
|
||||
|
||||
template <std::size_t N, cmp_kind Kind, typename Beta, std::size_t LengthBits = 0>
|
||||
struct paint_at_pack
|
||||
{
|
||||
static constexpr bool is_cmp = true;
|
||||
static constexpr cmp_kind kind = Kind;
|
||||
static constexpr std::size_t prefix = N;
|
||||
static constexpr std::size_t block_width = 0;
|
||||
static constexpr std::size_t length_bits = LengthBits;
|
||||
static constexpr bool incremental = false;
|
||||
using beta_type = Beta;
|
||||
Beta if_true;
|
||||
Beta if_false;
|
||||
|
||||
explicit paint_at_pack(Beta t, Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
: if_true{std::move(t)}, if_false{std::move(f)} { }
|
||||
};
|
||||
|
||||
template <typename Beta = uint64_t>
|
||||
inline auto lcp(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_pack<cmp_kind::lcp, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
template <std::size_t N, typename Beta = uint64_t>
|
||||
inline auto lcp_at(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_at_pack<N, cmp_kind::lcp, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
template <typename Beta = uint64_t>
|
||||
inline auto common_prefix(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_pack<cmp_kind::prefix, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
template <std::size_t N, typename Beta = uint64_t>
|
||||
inline auto common_prefix_at(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_at_pack<N, cmp_kind::prefix, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
template <typename Beta = uint64_t>
|
||||
inline auto prefix_mask(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_pack<cmp_kind::mask, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
template <std::size_t N, typename Beta = uint64_t>
|
||||
inline auto prefix_mask_at(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_at_pack<N, cmp_kind::mask, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
template <typename Beta = uint64_t>
|
||||
inline auto diverge_one_hot(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_pack<cmp_kind::one_hot, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
template <std::size_t N, typename Beta = uint64_t>
|
||||
inline auto diverge_one_hot_at(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_at_pack<N, cmp_kind::one_hot, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
template <typename Beta = uint64_t>
|
||||
inline auto break_bit(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_pack<cmp_kind::break_bit, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
template <std::size_t N, typename Beta = uint64_t>
|
||||
inline auto break_bit_at(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_at_pack<N, cmp_kind::break_bit, Beta>(std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
/// Low `LengthBits` hold the common-prefix length. Above them sits the
|
||||
/// matched prefix packed into the low bits of the lane (`α >> (N − d)`).
|
||||
template <std::size_t LengthBits = 8, typename Beta = uint64_t>
|
||||
inline auto prefix_with_length(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_pack<cmp_kind::prefix_with_length, Beta, LengthBits>(
|
||||
std::move(t), std::move(f));
|
||||
}
|
||||
template <std::size_t N, std::size_t LengthBits = 8, typename Beta = uint64_t>
|
||||
inline auto prefix_with_length_at(Beta t = Beta{1},
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_at_pack<N, cmp_kind::prefix_with_length, Beta, LengthBits>(
|
||||
std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
/// Arbitrary unit plant. `fn(matched, in_lane_prefix, leaf)` returns the β = 1
|
||||
/// value of that sibling subtree (`leaf` is the full match, `matched == N`).
|
||||
/// The result is scaled by `if_true − if_false` like the canned recipes.
|
||||
template <typename Beta, typename Fn>
|
||||
struct paint_fn_pack
|
||||
{
|
||||
static constexpr bool is_cmp = true;
|
||||
static constexpr cmp_kind kind = cmp_kind::paint;
|
||||
static constexpr std::size_t prefix = 0;
|
||||
static constexpr std::size_t block_width = 0;
|
||||
static constexpr std::size_t length_bits = 0;
|
||||
static constexpr bool incremental = false;
|
||||
using beta_type = Beta;
|
||||
Beta if_true;
|
||||
Beta if_false;
|
||||
Fn fn;
|
||||
|
||||
paint_fn_pack(Beta t, Beta f, Fn g)
|
||||
: if_true{std::move(t)}, if_false{std::move(f)}, fn{std::move(g)} { }
|
||||
};
|
||||
|
||||
template <std::size_t N, typename Beta, typename Fn>
|
||||
struct paint_fn_at_pack
|
||||
{
|
||||
static constexpr bool is_cmp = true;
|
||||
static constexpr cmp_kind kind = cmp_kind::paint;
|
||||
static constexpr std::size_t prefix = N;
|
||||
static constexpr std::size_t block_width = 0;
|
||||
static constexpr std::size_t length_bits = 0;
|
||||
static constexpr bool incremental = false;
|
||||
using beta_type = Beta;
|
||||
Beta if_true;
|
||||
Beta if_false;
|
||||
Fn fn;
|
||||
|
||||
paint_fn_at_pack(Beta t, Beta f, Fn g)
|
||||
: if_true{std::move(t)}, if_false{std::move(f)}, fn{std::move(g)} { }
|
||||
};
|
||||
|
||||
template <typename Fn, typename Beta>
|
||||
inline auto path_paint(Fn fn, Beta t,
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_fn_pack<std::decay_t<Beta>, std::decay_t<Fn>>(
|
||||
std::move(t), std::move(f), std::move(fn));
|
||||
}
|
||||
template <typename Fn>
|
||||
inline auto path_paint(Fn fn)
|
||||
{
|
||||
return path_paint(std::move(fn), uint64_t{1});
|
||||
}
|
||||
template <std::size_t N, typename Fn, typename Beta>
|
||||
inline auto path_paint_at(Fn fn, Beta t,
|
||||
Beta f = detail::dcf_impl::default_false<Beta>())
|
||||
{
|
||||
return paint_fn_at_pack<N, std::decay_t<Beta>, std::decay_t<Fn>>(
|
||||
std::move(t), std::move(f), std::move(fn));
|
||||
}
|
||||
|
||||
/// Incremental comparison: the same predicate, correct at every prefix length.
|
||||
/// Evaluate the full point with `cmp`, and a prefix with `cmp_prefix<L>`.
|
||||
template <typename Spec>
|
||||
struct idcf_pack
|
||||
{
|
||||
static constexpr bool is_cmp = true;
|
||||
static constexpr bool incremental = true;
|
||||
static constexpr cmp_kind kind = Spec::kind;
|
||||
static constexpr std::size_t prefix = Spec::prefix;
|
||||
static constexpr std::size_t block_width = Spec::block_width;
|
||||
static constexpr std::size_t length_bits = spec_length_bits<Spec>::value;
|
||||
using beta_type = typename Spec::beta_type;
|
||||
beta_type if_true;
|
||||
beta_type if_false;
|
||||
|
||||
explicit idcf_pack(Spec spec)
|
||||
: if_true{std::move(spec.if_true)}, if_false{std::move(spec.if_false)} { }
|
||||
};
|
||||
|
||||
template <typename Spec>
|
||||
inline auto idcf(Spec spec)
|
||||
{
|
||||
static_assert(is_paint_kind(Spec::kind) == false,
|
||||
"idcf wraps lt/leq/gt/geq; path paints are already one full-domain value");
|
||||
static_assert(Spec::block_width == 0,
|
||||
"idcf uses the per-level path, not blocked checkpoints");
|
||||
return idcf_pack<Spec>{std::move(spec)};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Equality specs: eq / eq_at
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -330,10 +737,54 @@ inline auto eq_at(Beta t, Beta f = detail::dcf_impl::default_false<std::decay_t<
|
|||
return eq_at_pack<N, std::decay_t<Beta>>(std::move(t), std::move(f));
|
||||
}
|
||||
|
||||
template <std::size_t BlockWidth, typename Spec>
|
||||
struct block_width_pack
|
||||
{
|
||||
static_assert(BlockWidth >= 1, "block_width<B> needs B >= 1");
|
||||
static_assert(Spec::block_width == 0, "comparison is already block_width");
|
||||
static constexpr bool is_cmp = true;
|
||||
static constexpr std::size_t block_width = BlockWidth;
|
||||
static constexpr cmp_kind kind = Spec::kind;
|
||||
static constexpr std::size_t prefix = Spec::prefix;
|
||||
static constexpr bool incremental = spec_is_incremental<Spec>::value;
|
||||
static constexpr std::size_t length_bits = spec_length_bits<Spec>::value;
|
||||
using beta_type = typename Spec::beta_type;
|
||||
beta_type if_true;
|
||||
beta_type if_false;
|
||||
|
||||
explicit block_width_pack(Spec spec)
|
||||
: if_true{std::move(spec.if_true)}, if_false{std::move(spec.if_false)} { }
|
||||
};
|
||||
|
||||
template <std::size_t BlockWidth>
|
||||
struct block_width_fn
|
||||
{
|
||||
template <typename Spec>
|
||||
constexpr auto operator()(Spec spec) const
|
||||
{
|
||||
return block_width_pack<BlockWidth, Spec>{std::move(spec)};
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t BlockWidth>
|
||||
inline constexpr block_width_fn<BlockWidth> block_width{};
|
||||
|
||||
template <typename T> struct is_cmp_spec : std::false_type {};
|
||||
template <cmp_kind K, typename B> struct is_cmp_spec<cmp_pack<K, B>> : std::true_type {};
|
||||
template <std::size_t N, cmp_kind K, typename B>
|
||||
struct is_cmp_spec<cmp_at_pack<N, K, B>> : std::true_type {};
|
||||
template <cmp_kind K, typename B, std::size_t L>
|
||||
struct is_cmp_spec<paint_pack<K, B, L>> : std::true_type {};
|
||||
template <std::size_t N, cmp_kind K, typename B, std::size_t L>
|
||||
struct is_cmp_spec<paint_at_pack<N, K, B, L>> : std::true_type {};
|
||||
template <typename B, typename Fn>
|
||||
struct is_cmp_spec<paint_fn_pack<B, Fn>> : std::true_type {};
|
||||
template <std::size_t N, typename B, typename Fn>
|
||||
struct is_cmp_spec<paint_fn_at_pack<N, B, Fn>> : std::true_type {};
|
||||
template <typename Spec>
|
||||
struct is_cmp_spec<idcf_pack<Spec>> : std::true_type {};
|
||||
template <std::size_t B, typename Spec>
|
||||
struct is_cmp_spec<block_width_pack<B, Spec>> : std::true_type {};
|
||||
template <typename T>
|
||||
inline constexpr bool is_cmp_spec_v = is_cmp_spec<T>::value;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
/// @file dpf/doerner_shelat.hpp
|
||||
/// @brief Doerner–Shelat generation of a dealer DPF key.
|
||||
/// @details Two XOR shares of the point are walked level by level. Correction
|
||||
/// words, advice bits, seeds, and leaves are the ones `make_dpf`
|
||||
/// would emit for the XOR of those shares, the same roots, and the
|
||||
/// same beaver coins. Beaver pads used to hide the path bit cancel
|
||||
/// and are not part of the key. Pad randomness must not come from
|
||||
/// `uniform_fill` if the beaver tape is being matched.
|
||||
/// @details Two shares of the point are walked level by level — XOR shares by
|
||||
/// default, or additive shares when tagged with `arith_input`.
|
||||
/// Correction words, advice bits, seeds, and leaves are the ones
|
||||
/// `make_dpf` would emit for the reconstructed point, the same roots,
|
||||
/// and the same beaver coins. Beaver pads used to hide the path bit
|
||||
/// cancel and are not part of the key. Pad randomness must not come
|
||||
/// from `uniform_fill` if the beaver tape is being matched.
|
||||
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
|
||||
/// @license Released under a GNU General Public v2.0 (GPLv2) license;
|
||||
/// see [LICENSE.md](@ref license) for details.
|
||||
|
|
@ -28,6 +29,14 @@
|
|||
namespace dpf
|
||||
{
|
||||
|
||||
/// Tag: Doerner–Shelat / geneval takes additive shares of the point
|
||||
/// (`x0 + x1` in the input ring). Default calls take XOR shares.
|
||||
struct arith_input_t
|
||||
{
|
||||
};
|
||||
|
||||
inline constexpr arith_input_t arith_input{};
|
||||
|
||||
/// Roots and the Beaver-pad stream for one Doerner–Shelat generation.
|
||||
/// `root` is called twice, same as `make_dpf`: party 0 clears the low bit of
|
||||
/// the first sample, party 1 sets the low bit of the second.
|
||||
|
|
@ -86,12 +95,14 @@ struct ds_and_shares
|
|||
simde__m128i z1;
|
||||
};
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
simde__m128i ds_xor(simde__m128i a, simde__m128i b) noexcept
|
||||
{
|
||||
return simde_mm_xor_si128(a, b);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
simde__m128i ds_gate(uint8_t bit, simde__m128i block) noexcept
|
||||
{
|
||||
|
|
@ -128,6 +139,7 @@ ds_and_pads ds_sample_and(PadRng & pad)
|
|||
return p;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
simde__m128i ds_cw_share(simde__m128i L, simde__m128i R, uint8_t my_bit,
|
||||
const ds_cw_party & mine, const ds_blind & their) noexcept
|
||||
|
|
@ -144,6 +156,7 @@ simde__m128i ds_cw_share(simde__m128i L, simde__m128i R, uint8_t my_bit,
|
|||
return out;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline void ds_cw_blinds(const ds_cw_pads & p,
|
||||
simde__m128i L0, simde__m128i R0, uint8_t bit0,
|
||||
simde__m128i L1, simde__m128i R1, uint8_t bit1,
|
||||
|
|
@ -155,6 +168,7 @@ inline void ds_cw_blinds(const ds_cw_pads & p,
|
|||
b1.msg = ds_xor(ds_xor(L1, R1), p.p1.rand);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m128i ds_cw_outs(const ds_cw_pads & p,
|
||||
simde__m128i L0, simde__m128i R0, uint8_t bit0,
|
||||
simde__m128i L1, simde__m128i R1, uint8_t bit1,
|
||||
|
|
@ -165,6 +179,7 @@ inline simde__m128i ds_cw_outs(const ds_cw_pads & p,
|
|||
ds_cw_share(L1, R1, bit1, p.p1, b0));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline uint8_t ds_open_advice(simde__m128i L0, simde__m128i R0, uint8_t bit0,
|
||||
simde__m128i L1, simde__m128i R1, uint8_t bit1) noexcept
|
||||
{
|
||||
|
|
@ -177,6 +192,7 @@ inline uint8_t ds_open_advice(simde__m128i L0, simde__m128i R0, uint8_t bit0,
|
|||
return static_cast<uint8_t>((t1 << 1) | (t0 & 1u));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline void ds_next_terms(simde__m128i L, simde__m128i R, uint8_t advice,
|
||||
simde__m128i cw, uint8_t tpack, simde__m128i & M, simde__m128i & base) noexcept
|
||||
{
|
||||
|
|
@ -190,6 +206,7 @@ inline void ds_next_terms(simde__m128i L, simde__m128i R, uint8_t advice,
|
|||
base = (advice & 1u) ? ds_xor(L, cw_base) : L;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline ds_and_shares ds_and_open(const ds_and_pads & p, simde__m128i M,
|
||||
uint8_t b_recv) noexcept
|
||||
{
|
||||
|
|
@ -202,6 +219,7 @@ inline ds_and_shares ds_and_open(const ds_and_pads & p, simde__m128i M,
|
|||
return z;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m128i ds_deliver(uint8_t b_exp, simde__m128i base, simde__m128i M,
|
||||
const ds_and_shares & z) noexcept
|
||||
{
|
||||
|
|
@ -249,6 +267,11 @@ struct ds_cmp_gen_state
|
|||
bool track_coeff = false;
|
||||
uint64_t Va1 = 0;
|
||||
uint64_t last_vcw_coeff = 0;
|
||||
cmp_kind kind = cmp_kind::lt;
|
||||
bool paint = false;
|
||||
std::size_t length_bits = 0;
|
||||
paint_callback paint_cb = nullptr;
|
||||
const void * paint_ctx = nullptr;
|
||||
};
|
||||
|
||||
/// Local joint simulation: today's `ds_cw_outs` / `ds_open_advice` / `ds_and_open`.
|
||||
|
|
@ -288,6 +311,7 @@ struct local_cw_protocol
|
|||
}
|
||||
|
||||
/// Open CW + advice only (AND pads stay in `blinds` for a later open).
|
||||
HEDLEY_NO_THROW
|
||||
std::pair<simde__m128i, uint8_t> open_cw(const ds_level_blinds & b) noexcept
|
||||
{
|
||||
return {ds_cw_outs(b.cwp, b.L0, b.R0, b.bit0, b.L1, b.R1, b.bit1,
|
||||
|
|
@ -297,6 +321,7 @@ struct local_cw_protocol
|
|||
|
||||
/// Open the public value CW for this level (local: clear convert+make_value_cw).
|
||||
/// MPC backends open additive shares of the same word.
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t open_value_cw(const ds_level_blinds & b, uint8_t adv0, uint8_t adv1,
|
||||
int ai, uint64_t & Va, uint64_t beta, uint64_t mask) noexcept
|
||||
{
|
||||
|
|
@ -304,6 +329,16 @@ struct local_cw_protocol
|
|||
adv1, ai, Va, beta, mask);
|
||||
}
|
||||
|
||||
/// Open a path-paint value CW. `plant` is the scaled lose-subtree constant.
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t open_planted_cw(const ds_level_blinds & b, uint8_t adv0, uint8_t adv1,
|
||||
int ai, uint64_t & Va, uint64_t plant, uint64_t mask) noexcept
|
||||
{
|
||||
return dcf_impl::make_value_cw_planted(b.L0, b.R0, b.L1, b.R1, adv0,
|
||||
adv1, ai, Va, plant, mask);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
ds_and_shares open_and(const ds_and_pads & p, simde__m128i M,
|
||||
uint8_t b_recv) noexcept
|
||||
{
|
||||
|
|
@ -313,6 +348,7 @@ struct local_cw_protocol
|
|||
/// Open the final comparison leaf CW. Wraps `make_final_cw` so the
|
||||
/// Doerner–Shelat gen does not call it directly on reconstructed seeds;
|
||||
/// an MPC backend would open additive shares of the same word.
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t open_final_cw(simde__m128i s0, simde__m128i s1, uint8_t t1,
|
||||
uint64_t Va, uint64_t mask, uint64_t on_path) noexcept
|
||||
{
|
||||
|
|
@ -323,18 +359,81 @@ struct local_cw_protocol
|
|||
/// the shared root sampler so the blind matches the dealer's; an MPC
|
||||
/// backend would instead pull a group-width element from the pad stream.
|
||||
template <typename BlockSampler>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t sample_addend_blind(uint64_t mask, BlockSampler && sample) noexcept
|
||||
{
|
||||
return dcf_impl::sample_addend_blind(mask,
|
||||
std::forward<BlockSampler>(sample));
|
||||
}
|
||||
|
||||
/// Majority of three bits (next carry of a full adder).
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint8_t majority(uint8_t a, uint8_t b, uint8_t c) noexcept
|
||||
{
|
||||
return static_cast<uint8_t>((a & b) | (a & c) | (b & c));
|
||||
}
|
||||
|
||||
/// One additive digit: sum bit `a XOR b XOR cin`, carry out = majority.
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint8_t open_sum_bit(uint8_t a, uint8_t b, uint8_t cin,
|
||||
uint8_t & cout) noexcept
|
||||
{
|
||||
cout = majority(a, b, cin);
|
||||
return static_cast<uint8_t>(a ^ b ^ cin);
|
||||
}
|
||||
|
||||
/// Reconstruct `a0 + a1` via a LSB→MSB carry chain, then flip the MSB
|
||||
/// when the domain is signed — matching `make_dpf` on the sum. The call
|
||||
/// site never forms the sum; an MPC backend would open the same bits.
|
||||
template <typename InputT>
|
||||
InputT open_arith_point(InputT a0, InputT a1) const
|
||||
{
|
||||
constexpr auto to_int = utils::to_integral_type<InputT>{};
|
||||
using FromI = typename utils::make_from_integral_value<InputT>::integral_type;
|
||||
using U = std::make_unsigned_t<FromI>;
|
||||
const U u0 = static_cast<U>(to_int(a0));
|
||||
const U u1 = static_cast<U>(to_int(a1));
|
||||
U sum = 0;
|
||||
uint8_t carry = 0;
|
||||
constexpr std::size_t nbits = utils::bitlength_of_v<InputT>;
|
||||
for (std::size_t i = 0; i < nbits; ++i)
|
||||
{
|
||||
const uint8_t b0 = static_cast<uint8_t>((u0 >> i) & U{1});
|
||||
const uint8_t b1 = static_cast<uint8_t>((u1 >> i) & U{1});
|
||||
const uint8_t s = open_sum_bit(b0, b1, carry, carry);
|
||||
sum = static_cast<U>(sum | (static_cast<U>(s) << i));
|
||||
}
|
||||
InputT out = utils::make_from_integral_value<InputT>{}(
|
||||
static_cast<FromI>(sum));
|
||||
utils::flip_msb_if_signed_integral(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Encode shares for the XOR-style CW walk. XOR mode flips party 0's MSB
|
||||
/// (linear over XOR). Arithmetic mode opens the sum (carry + signed MSB)
|
||||
/// and returns `(alpha, 0)` so the walk matches `make_dpf(alpha)`.
|
||||
template <typename InputT>
|
||||
void encode_walk_shares(InputT & x0, InputT & x1, bool arith) const
|
||||
{
|
||||
if (arith)
|
||||
{
|
||||
const InputT alpha = open_arith_point(x0, x1);
|
||||
x0 = alpha;
|
||||
x1 = InputT{};
|
||||
}
|
||||
else
|
||||
{
|
||||
utils::flip_msb_if_signed_integral(x0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Open a group of leaf correction words for one prefix group. In this
|
||||
/// local joint simulation both XOR shares of the point are present, so the
|
||||
/// point is reconstructed *inside* the protocol and handed to `leaf_fn`
|
||||
/// (which runs `make_leaves` for the group). The Doerner–Shelat gen never
|
||||
/// forms `x = x0 ^ x1` at its own call site; an MPC backend would instead
|
||||
/// run a per-group leaf CW exchange that never reveals `x`.
|
||||
/// run a per-group leaf CW exchange that never reveals `x`. After
|
||||
/// `encode_walk_shares`, arithmetic inputs are already `(alpha, 0)`.
|
||||
template <typename InputT, typename LeafFn>
|
||||
void open_leaf_group(InputT x0, InputT x1, LeafFn && leaf_fn)
|
||||
{
|
||||
|
|
@ -351,6 +450,7 @@ struct ds_gen_state
|
|||
NodeT root0;
|
||||
NodeT root1;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
void init(NodeT r0, NodeT r1) noexcept
|
||||
{
|
||||
root0 = r0;
|
||||
|
|
@ -361,9 +461,13 @@ struct ds_gen_state
|
|||
home[1] = 1;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
NodeT & seed0() noexcept { return inbox[home[0]]; }
|
||||
HEDLEY_NO_THROW
|
||||
NodeT & seed1() noexcept { return inbox[home[1]]; }
|
||||
HEDLEY_NO_THROW
|
||||
const NodeT & seed0() const noexcept { return inbox[home[0]]; }
|
||||
HEDLEY_NO_THROW
|
||||
const NodeT & seed1() const noexcept { return inbox[home[1]]; }
|
||||
};
|
||||
|
||||
|
|
@ -403,15 +507,37 @@ void ds_advance_level(ds_gen_state<NodeT> & st, InputT x0, InputT x1,
|
|||
{
|
||||
const int ai = static_cast<int>(
|
||||
(cmp->thresh >> (cmp->nbits - 1 - level)) & 1);
|
||||
*value_cw_out = proto.open_value_cw(blinds, adv0, adv1, ai, cmp->Va,
|
||||
cmp->beta, cmp->mask);
|
||||
if (cmp->track_coeff)
|
||||
if (cmp->paint)
|
||||
{
|
||||
// Affine coefficient: same level with β = 1 on a parallel Va.
|
||||
const uint64_t v1 = proto.open_value_cw(blinds, adv0, adv1, ai,
|
||||
cmp->Va1, 1ULL, cmp->mask);
|
||||
cmp->last_vcw_coeff =
|
||||
(v1 + dcf_impl::neg_m(*value_cw_out, cmp->mask)) & cmp->mask;
|
||||
const uint64_t unit = dcf_impl::paint_unit(cmp->kind, level,
|
||||
cmp->thresh, cmp->nbits, cmp->length_bits, false,
|
||||
cmp->paint_cb, cmp->paint_ctx);
|
||||
const uint64_t plant = dcf_impl::scale_plant(unit, cmp->beta,
|
||||
cmp->mask);
|
||||
*value_cw_out = proto.open_planted_cw(blinds, adv0, adv1, ai,
|
||||
cmp->Va, plant, cmp->mask);
|
||||
if (cmp->track_coeff)
|
||||
{
|
||||
const uint64_t plant1 = dcf_impl::scale_plant(unit, 1ULL,
|
||||
cmp->mask);
|
||||
const uint64_t v1 = proto.open_planted_cw(blinds, adv0, adv1,
|
||||
ai, cmp->Va1, plant1, cmp->mask);
|
||||
cmp->last_vcw_coeff =
|
||||
(v1 + dcf_impl::neg_m(*value_cw_out, cmp->mask)) & cmp->mask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*value_cw_out = proto.open_value_cw(blinds, adv0, adv1, ai, cmp->Va,
|
||||
cmp->beta, cmp->mask);
|
||||
if (cmp->track_coeff)
|
||||
{
|
||||
// Affine coefficient: same level with β = 1 on a parallel Va.
|
||||
const uint64_t v1 = proto.open_value_cw(blinds, adv0, adv1, ai,
|
||||
cmp->Va1, 1ULL, cmp->mask);
|
||||
cmp->last_vcw_coeff =
|
||||
(v1 + dcf_impl::neg_m(*value_cw_out, cmp->mask)) & cmp->mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -475,14 +601,14 @@ template <typename InteriorPRG,
|
|||
typename ...OutputTs,
|
||||
typename RootSampler,
|
||||
typename CwProtocol>
|
||||
auto make_dpf_doerner_shelat_impl(InputT x0, InputT x1,
|
||||
auto make_dpf_doerner_shelat_impl(bool arith, InputT x0, InputT x1,
|
||||
RootSampler & root_sampler, CwProtocol & proto, OutputT && y,
|
||||
OutputTs && ...ys)
|
||||
{
|
||||
static_assert(!dpf::is_wildcard_v<InputT>,
|
||||
"Doerner–Shelat gen takes XOR shares of a concrete point");
|
||||
"Doerner–Shelat gen takes shares of a concrete point");
|
||||
static_assert(!dpf::is_secret_share_v<InputT>,
|
||||
"Doerner–Shelat: pass additive_share of xor_wrapper, or raw XOR shares");
|
||||
"Doerner–Shelat: pass additive_share of xor_wrapper, or raw shares");
|
||||
static_assert(sizeof(typename InteriorPRG::block_type) == sizeof(simde__m128i),
|
||||
"Doerner–Shelat gen uses the AES-block interior node");
|
||||
|
||||
|
|
@ -492,7 +618,7 @@ auto make_dpf_doerner_shelat_impl(InputT x0, InputT x1,
|
|||
using input_type = typename dpf_type::input_type;
|
||||
constexpr auto depth = dpf_type::depth;
|
||||
|
||||
utils::flip_msb_if_signed_integral(x0);
|
||||
proto.encode_walk_shares(x0, x1, arith);
|
||||
|
||||
const node root0 = dpf::unset_lo_bit(static_cast<node>(root_sampler()));
|
||||
const node root1 = dpf::set_lo_bit(static_cast<node>(root_sampler()));
|
||||
|
|
|
|||
|
|
@ -150,6 +150,12 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
static constexpr std::size_t num_outputs = 1 + sizeof...(OutputTs);
|
||||
static constexpr std::size_t cmp_depth = 0;
|
||||
static constexpr std::size_t cmp_out_bits = 0;
|
||||
static constexpr std::size_t cmp_block = 0;
|
||||
static constexpr bool cmp_idcf = false;
|
||||
static constexpr std::size_t cmp_q = 0;
|
||||
static constexpr std::size_t cmp_h = 0;
|
||||
static constexpr std::size_t cmp_checkpoints = 0;
|
||||
static constexpr std::size_t cmp_tail = 0;
|
||||
/// Classic keys are single-level; the unified eval surface keeps routing
|
||||
/// them through the classic `eval_*` fast paths (see `is_multilevel_key`).
|
||||
static constexpr bool is_multilevel = false;
|
||||
|
|
@ -286,6 +292,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
return std::get<I>(leaf_nodes).beaver();
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
constexpr bool is_wildcard(std::size_t i) const noexcept
|
||||
|
|
@ -442,41 +449,68 @@ namespace incr
|
|||
/// / `cw_last` are affine in the payload δ, so after keygen with δ = 0 the
|
||||
/// concrete values are `base[i] + coeff[i]·δ`; `assign_cmp` patches them in
|
||||
/// place with no tree re-walk / re-PRG.
|
||||
template <std::size_t Depth, typename ValueCwWord, bool Wild>
|
||||
template <std::size_t Depth, typename ValueCwWord, bool Wild,
|
||||
std::size_t TailLen = 0, bool Idcf = false>
|
||||
struct cmp_wild_state { };
|
||||
template <std::size_t Depth, typename ValueCwWord>
|
||||
struct cmp_wild_state<Depth, ValueCwWord, true>
|
||||
template <std::size_t Depth, typename ValueCwWord, std::size_t TailLen, bool Idcf>
|
||||
struct cmp_wild_state<Depth, ValueCwWord, true, TailLen, Idcf>
|
||||
{
|
||||
std::array<ValueCwWord, Depth> value_cw_coeff{};
|
||||
ValueCwWord cw_last_coeff{0};
|
||||
std::array<ValueCwWord, TailLen> tail_coeff{};
|
||||
std::array<ValueCwWord, Idcf ? Depth + 1 : 0> prefix_cw_coeff{};
|
||||
bool assigned{false};
|
||||
};
|
||||
|
||||
template <std::size_t Depth, typename ValueCwWord, bool Wild = false>
|
||||
template <std::size_t Depth, typename ValueCwWord, bool Wild = false,
|
||||
std::size_t TailLen = 0, bool Blocked = false, bool Idcf = false>
|
||||
struct cmp_storage
|
||||
{
|
||||
using value_cw_word = ValueCwWord;
|
||||
using value_cw_array = std::array<value_cw_word, Depth>;
|
||||
using tail_array = std::array<value_cw_word, TailLen>;
|
||||
static constexpr std::size_t prefix_cw_len = Idcf ? Depth + 1 : 0;
|
||||
using prefix_cw_array = std::array<value_cw_word, prefix_cw_len>;
|
||||
cmp_storage() = default;
|
||||
cmp_storage(detail::cmp_meta cmp, value_cw_array value_cws,
|
||||
value_cw_word cw_last_in, value_cw_word cmp_addend_in)
|
||||
value_cw_word cw_last_in, value_cw_word cmp_addend_in,
|
||||
tail_array tail = {}, tail_array tail_coeff = {},
|
||||
prefix_cw_array prefix = {}, prefix_cw_array prefix_coeff = {})
|
||||
: cmp_{cmp}, value_cw_{value_cws}, cw_last_{cw_last_in},
|
||||
cmp_addend_{cmp_addend_in} { }
|
||||
cmp_addend_{cmp_addend_in}, tail_{tail}, prefix_cw_{prefix}
|
||||
{
|
||||
if constexpr (Wild && Blocked)
|
||||
wild_.tail_coeff = tail_coeff;
|
||||
else
|
||||
(void)tail_coeff;
|
||||
if constexpr (Wild && Idcf)
|
||||
wild_.prefix_cw_coeff = prefix_coeff;
|
||||
else
|
||||
(void)prefix_coeff;
|
||||
}
|
||||
cmp_storage(detail::cmp_meta cmp, value_cw_array value_cws,
|
||||
value_cw_word cw_last_in, value_cw_word cmp_addend_in,
|
||||
value_cw_array coeff, value_cw_word cw_last_coeff)
|
||||
value_cw_array coeff, value_cw_word cw_last_coeff,
|
||||
tail_array tail = {}, tail_array tail_coeff = {},
|
||||
prefix_cw_array prefix = {}, prefix_cw_array prefix_coeff = {})
|
||||
: cmp_{cmp}, value_cw_{value_cws}, cw_last_{cw_last_in},
|
||||
cmp_addend_{cmp_addend_in}
|
||||
cmp_addend_{cmp_addend_in}, tail_{tail}, prefix_cw_{prefix}
|
||||
{
|
||||
if constexpr (Wild)
|
||||
{
|
||||
wild_.value_cw_coeff = coeff;
|
||||
wild_.cw_last_coeff = cw_last_coeff;
|
||||
if constexpr (Blocked)
|
||||
wild_.tail_coeff = tail_coeff;
|
||||
if constexpr (Idcf)
|
||||
wild_.prefix_cw_coeff = prefix_coeff;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)coeff;
|
||||
(void)cw_last_coeff;
|
||||
(void)tail_coeff;
|
||||
(void)prefix_coeff;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,15 +519,32 @@ struct cmp_storage
|
|||
{
|
||||
return static_cast<uint64_t>(value_cw_[level]);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t cw_last() const noexcept { return static_cast<uint64_t>(cw_last_); }
|
||||
HEDLEY_NO_THROW
|
||||
const tail_array & tail_cw() const noexcept { return tail_; }
|
||||
uint64_t tail_cw(std::size_t i) const
|
||||
{
|
||||
return static_cast<uint64_t>(tail_[i]);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t cmp_addend() const noexcept
|
||||
{
|
||||
return static_cast<uint64_t>(cmp_addend_);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
const detail::cmp_meta & cmp() const noexcept { return cmp_; }
|
||||
HEDLEY_NO_THROW
|
||||
bool has_cmp() const noexcept { return cmp_.active; }
|
||||
HEDLEY_NO_THROW
|
||||
const prefix_cw_array & prefix_cws() const noexcept { return prefix_cw_; }
|
||||
uint64_t prefix_cw(std::size_t i) const
|
||||
{
|
||||
return static_cast<uint64_t>(prefix_cw_[i]);
|
||||
}
|
||||
|
||||
static constexpr bool is_wildcard = Wild;
|
||||
HEDLEY_NO_THROW
|
||||
bool cmp_assigned() const noexcept
|
||||
{
|
||||
if constexpr (Wild)
|
||||
|
|
@ -518,9 +569,27 @@ struct cmp_storage
|
|||
const uint64_t c = static_cast<uint64_t>(wild_.value_cw_coeff[i]);
|
||||
value_cw_[i] = static_cast<value_cw_word>((base + c * delta) & mask);
|
||||
}
|
||||
if constexpr (Blocked)
|
||||
{
|
||||
for (std::size_t i = 0; i < TailLen; ++i)
|
||||
{
|
||||
const uint64_t base = static_cast<uint64_t>(tail_[i]);
|
||||
const uint64_t c = static_cast<uint64_t>(wild_.tail_coeff[i]);
|
||||
tail_[i] = static_cast<value_cw_word>((base + c * delta) & mask);
|
||||
}
|
||||
}
|
||||
const uint64_t lbase = static_cast<uint64_t>(cw_last_);
|
||||
const uint64_t lc = static_cast<uint64_t>(wild_.cw_last_coeff);
|
||||
cw_last_ = static_cast<value_cw_word>((lbase + lc * delta) & mask);
|
||||
if constexpr (Idcf)
|
||||
{
|
||||
for (std::size_t i = 0; i < prefix_cw_len; ++i)
|
||||
{
|
||||
const uint64_t base = static_cast<uint64_t>(prefix_cw_[i]);
|
||||
const uint64_t c = static_cast<uint64_t>(wild_.prefix_cw_coeff[i]);
|
||||
prefix_cw_[i] = static_cast<value_cw_word>((base + c * delta) & mask);
|
||||
}
|
||||
}
|
||||
cmp_addend_ = static_cast<value_cw_word>(addend_share & mask);
|
||||
wild_.assigned = true;
|
||||
}
|
||||
|
|
@ -531,14 +600,17 @@ struct cmp_storage
|
|||
value_cw_array value_cw_{};
|
||||
value_cw_word cw_last_{0};
|
||||
value_cw_word cmp_addend_{0};
|
||||
cmp_wild_state<Depth, value_cw_word, Wild> wild_{};
|
||||
tail_array tail_{};
|
||||
prefix_cw_array prefix_cw_{};
|
||||
cmp_wild_state<Depth, value_cw_word, Wild, TailLen, Idcf> wild_{};
|
||||
};
|
||||
|
||||
/// Multi-level / comparison DPF key body. `PlacedTuple` is a tuple of
|
||||
/// `placed<N, T>` slots; `CmpDepth > 0` activates the comparison channel.
|
||||
template <typename InteriorPRG, typename ExteriorPRG, typename InputT,
|
||||
typename PlacedTuple, std::size_t CmpDepth = 0,
|
||||
std::size_t CmpOutBits = 0, bool CmpWild = false>
|
||||
std::size_t CmpOutBits = 0, bool CmpWild = false,
|
||||
std::size_t CmpBlock = 0, bool CmpIdcf = false>
|
||||
struct incr_key_base
|
||||
{
|
||||
public:
|
||||
|
|
@ -554,6 +626,26 @@ struct incr_key_base
|
|||
static constexpr std::size_t cmp_out_bits = CmpOutBits;
|
||||
/// True when the comparison payload is an unassigned wildcard.
|
||||
static constexpr bool cmp_is_wildcard = CmpWild;
|
||||
/// 0 = per-level path-sum. `B >= 1` = blocked checkpoints of width `B`.
|
||||
static constexpr std::size_t cmp_block = CmpBlock;
|
||||
static constexpr bool cmp_idcf = CmpIdcf;
|
||||
static constexpr std::size_t max_output_level =
|
||||
detail::incr::max_tree_level_v<node_type, PlacedTuple>;
|
||||
/// Residual tail width. 2 only when dropping those levels does not cut an
|
||||
/// output and the comparison itself is what sets the tree height.
|
||||
static constexpr std::size_t cmp_q = [] {
|
||||
if (CmpBlock == 0 || CmpDepth <= 2)
|
||||
return std::size_t{0};
|
||||
if (max_output_level > CmpDepth - 2)
|
||||
return std::size_t{0};
|
||||
return std::size_t{2};
|
||||
}();
|
||||
static constexpr std::size_t cmp_h =
|
||||
(CmpBlock == 0) ? CmpDepth : (CmpDepth - cmp_q);
|
||||
static constexpr std::size_t cmp_checkpoints =
|
||||
(CmpBlock == 0 || cmp_h == 0) ? 0 : (cmp_h + CmpBlock - 1) / CmpBlock;
|
||||
static constexpr std::size_t cmp_tail =
|
||||
(CmpBlock == 0 || cmp_q == 0) ? 0 : (std::size_t{1} << cmp_q);
|
||||
/// Multi-level / comparison keys route through the slot-aware eval path.
|
||||
static constexpr bool is_multilevel = true;
|
||||
/// Narrowest unsigned word that holds `cmp_out_bits` bits (1 byte for a
|
||||
|
|
@ -564,8 +656,11 @@ struct incr_key_base
|
|||
|
||||
static constexpr std::size_t num_outputs = std::tuple_size_v<PlacedTuple>;
|
||||
static constexpr std::size_t input_bits = utils::bitlength_of_v<input_type>;
|
||||
static constexpr std::size_t depth = std::max(
|
||||
detail::incr::max_tree_level_v<node_type, PlacedTuple>, CmpDepth);
|
||||
static constexpr std::size_t depth = std::max(max_output_level,
|
||||
(CmpBlock == 0) ? CmpDepth : cmp_h);
|
||||
static constexpr std::size_t value_cw_len =
|
||||
(CmpBlock == 0) ? depth
|
||||
: (cmp_checkpoints == 0 ? std::size_t{1} : cmp_checkpoints);
|
||||
static constexpr auto msb_mask = utils::msb_of_v<input_type>;
|
||||
using integral_type = utils::integral_type_from_bitlength_t<
|
||||
input_bits, utils::bitlength_of_v<std::size_t>>;
|
||||
|
|
@ -577,7 +672,10 @@ struct incr_key_base
|
|||
|
||||
using correction_words_array = std::array<interior_node, depth>;
|
||||
using correction_advice_array = std::array<psnip_uint8_t, depth>;
|
||||
using value_cw_array = std::array<value_cw_word, depth>;
|
||||
using value_cw_array = std::array<value_cw_word, value_cw_len>;
|
||||
using tail_array = std::array<value_cw_word, cmp_tail>;
|
||||
static constexpr std::size_t prefix_cw_len = CmpIdcf ? depth + 1 : 0;
|
||||
using prefix_cw_array = std::array<value_cw_word, prefix_cw_len>;
|
||||
using meta_array = std::array<detail::incr::slot_meta, num_outputs>;
|
||||
static constexpr meta_array meta =
|
||||
detail::incr::build_meta<node_type, PlacedTuple>();
|
||||
|
|
@ -675,14 +773,17 @@ struct incr_key_base
|
|||
detail::cmp_meta cmp = {}, value_cw_array value_cws = {},
|
||||
uint64_t cw_last_in = 0, uint64_t cmp_addend_in = 0,
|
||||
addend_tuple addends = {}, value_cw_array value_cw_coeff = {},
|
||||
uint64_t cw_last_coeff_in = 0)
|
||||
uint64_t cw_last_coeff_in = 0, tail_array tail_in = {},
|
||||
tail_array tail_coeff_in = {}, prefix_cw_array prefix_in = {},
|
||||
prefix_cw_array prefix_coeff_in = {})
|
||||
: leaf_nodes{std::move(leaves)},
|
||||
offset_x{offset_share},
|
||||
cmp_store_{cmp, value_cws,
|
||||
static_cast<value_cw_word>(cw_last_in),
|
||||
static_cast<value_cw_word>(cmp_addend_in),
|
||||
value_cw_coeff,
|
||||
static_cast<value_cw_word>(cw_last_coeff_in)},
|
||||
static_cast<value_cw_word>(cw_last_coeff_in),
|
||||
tail_in, tail_coeff_in, prefix_in, prefix_coeff_in},
|
||||
public_addends{std::move(addends)},
|
||||
root_{root},
|
||||
correction_words_{correction_words},
|
||||
|
|
@ -706,10 +807,19 @@ struct incr_key_base
|
|||
return correction_advice_;
|
||||
}
|
||||
const value_cw_array & value_cw() const { return cmp_store_.value_cw(); }
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t cw_last() const noexcept { return cmp_store_.cw_last(); }
|
||||
HEDLEY_NO_THROW
|
||||
const prefix_cw_array & prefix_cws() const noexcept
|
||||
{
|
||||
return cmp_store_.prefix_cws();
|
||||
}
|
||||
uint64_t prefix_cw(std::size_t i) const { return cmp_store_.prefix_cw(i); }
|
||||
/// Party-local share of the constant absorb (`if_false`, or
|
||||
/// `δ + if_false` when `eval_as_ge`). Reconstructs with the peer share.
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t cmp_addend() const noexcept { return cmp_store_.cmp_addend(); }
|
||||
HEDLEY_NO_THROW
|
||||
const detail::cmp_meta & cmp() const noexcept { return cmp_store_.cmp(); }
|
||||
const digest_type & common_part_hash() const { return common_part_hash_; }
|
||||
const leaf_wrapper_tuple & leaves() const { return leaf_nodes; }
|
||||
|
|
@ -728,6 +838,8 @@ struct incr_key_base
|
|||
(correction_advice_[level] >> direction) & 1);
|
||||
}
|
||||
uint64_t value_cw(std::size_t level) const { return cmp_store_.value_cw(level); }
|
||||
const tail_array & tail_cw() const { return cmp_store_.tail_cw(); }
|
||||
uint64_t tail_cw(std::size_t i) const { return cmp_store_.tail_cw(i); }
|
||||
|
||||
template <std::size_t I = 0>
|
||||
const auto & leaf() const
|
||||
|
|
@ -812,6 +924,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
}
|
||||
|
||||
template <std::size_t I = 0>
|
||||
HEDLEY_NO_THROW
|
||||
auto traverse_exterior(const interior_node & node) const noexcept
|
||||
{
|
||||
static_assert(num_outputs > 0, "cmp-only key has no exterior outputs");
|
||||
|
|
@ -836,9 +949,11 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
/// Public `if_false` addends for `eq` / `eq_at` slots.
|
||||
addend_tuple public_addends{};
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
bool has_cmp() const noexcept { return cmp_store_.has_cmp(); }
|
||||
/// True once a wildcard comparison payload has been assigned (always true
|
||||
/// for concrete cmp keys and for keys without a comparison channel).
|
||||
HEDLEY_NO_THROW
|
||||
bool cmp_assigned() const noexcept { return cmp_store_.cmp_assigned(); }
|
||||
|
||||
/// Patch the value CWs / `cw_last` for a resolved payload δ and install
|
||||
|
|
@ -850,7 +965,9 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
}
|
||||
|
||||
private:
|
||||
cmp_storage<depth, value_cw_word, CmpWild> cmp_store_{};
|
||||
cmp_storage<value_cw_len, value_cw_word, CmpWild, cmp_tail, (CmpBlock > 0),
|
||||
CmpIdcf>
|
||||
cmp_store_{};
|
||||
interior_node root_;
|
||||
correction_words_array correction_words_;
|
||||
correction_advice_array correction_advice_;
|
||||
|
|
@ -890,7 +1007,13 @@ using dpf_key_base_t = std::conditional_t<
|
|||
OutputT, OutputTs...>::cmp_out_bits,
|
||||
dpf::detail::incr::normalize_pack<
|
||||
utils::bitlength_of_v<dpf::concrete_type_t<InputT>>,
|
||||
OutputT, OutputTs...>::cmp_wild>>;
|
||||
OutputT, OutputTs...>::cmp_wild,
|
||||
dpf::detail::incr::normalize_pack<
|
||||
utils::bitlength_of_v<dpf::concrete_type_t<InputT>>,
|
||||
OutputT, OutputTs...>::cmp_block,
|
||||
dpf::detail::incr::normalize_pack<
|
||||
utils::bitlength_of_v<dpf::concrete_type_t<InputT>>,
|
||||
OutputT, OutputTs...>::cmp_idcf>>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
|
@ -919,39 +1042,40 @@ namespace incr
|
|||
// expanding the placed slots into the output pack and appending the phantom
|
||||
// cmp tag when a comparison channel is present.
|
||||
template <std::size_t CmpDepth, std::size_t CmpOutBits, bool CmpWild,
|
||||
typename InteriorPRG,
|
||||
std::size_t CmpBlock, bool CmpIdcf, typename InteriorPRG,
|
||||
typename ExteriorPRG, typename InputT, typename ...Ps>
|
||||
struct assemble_key
|
||||
{
|
||||
using type = dpf::dpf_key<InteriorPRG, ExteriorPRG, InputT, Ps...,
|
||||
dpf::cmp_channel_tag<CmpDepth, CmpOutBits, CmpWild>>;
|
||||
dpf::cmp_channel_tag<CmpDepth, CmpOutBits, CmpWild, CmpBlock, CmpIdcf>>;
|
||||
};
|
||||
template <std::size_t CmpOutBits, bool CmpWild, typename InteriorPRG,
|
||||
template <std::size_t CmpOutBits, bool CmpWild, std::size_t CmpBlock,
|
||||
bool CmpIdcf, typename InteriorPRG,
|
||||
typename ExteriorPRG, typename InputT, typename ...Ps>
|
||||
struct assemble_key<0, CmpOutBits, CmpWild, InteriorPRG, ExteriorPRG, InputT,
|
||||
Ps...>
|
||||
struct assemble_key<0, CmpOutBits, CmpWild, CmpBlock, CmpIdcf, InteriorPRG,
|
||||
ExteriorPRG, InputT, Ps...>
|
||||
{
|
||||
using type = dpf::dpf_key<InteriorPRG, ExteriorPRG, InputT, Ps...>;
|
||||
};
|
||||
|
||||
template <typename InteriorPRG, typename ExteriorPRG, typename InputT,
|
||||
typename PlacedTuple, std::size_t CmpDepth, std::size_t CmpOutBits = 0,
|
||||
bool CmpWild = false>
|
||||
bool CmpWild = false, std::size_t CmpBlock = 0, bool CmpIdcf = false>
|
||||
struct incr_dpf_key_of;
|
||||
template <typename InteriorPRG, typename ExteriorPRG, typename InputT,
|
||||
typename ...Ps, std::size_t CmpDepth, std::size_t CmpOutBits,
|
||||
bool CmpWild>
|
||||
bool CmpWild, std::size_t CmpBlock, bool CmpIdcf>
|
||||
struct incr_dpf_key_of<InteriorPRG, ExteriorPRG, InputT, std::tuple<Ps...>,
|
||||
CmpDepth, CmpOutBits, CmpWild>
|
||||
CmpDepth, CmpOutBits, CmpWild, CmpBlock, CmpIdcf>
|
||||
{
|
||||
using type = typename assemble_key<CmpDepth, CmpOutBits, CmpWild,
|
||||
InteriorPRG, ExteriorPRG, InputT, Ps...>::type;
|
||||
using type = typename assemble_key<CmpDepth, CmpOutBits, CmpWild, CmpBlock,
|
||||
CmpIdcf, InteriorPRG, ExteriorPRG, InputT, Ps...>::type;
|
||||
};
|
||||
template <typename InteriorPRG, typename ExteriorPRG, typename InputT,
|
||||
typename PlacedTuple, std::size_t CmpDepth, std::size_t CmpOutBits = 0,
|
||||
bool CmpWild = false>
|
||||
bool CmpWild = false, std::size_t CmpBlock = 0, bool CmpIdcf = false>
|
||||
using incr_dpf_key_of_t = typename incr_dpf_key_of<InteriorPRG, ExteriorPRG,
|
||||
InputT, PlacedTuple, CmpDepth, CmpOutBits, CmpWild>::type;
|
||||
InputT, PlacedTuple, CmpDepth, CmpOutBits, CmpWild, CmpBlock, CmpIdcf>::type;
|
||||
|
||||
} // namespace incr
|
||||
} // namespace detail
|
||||
|
|
|
|||
|
|
@ -67,8 +67,10 @@ struct alignas(utils::max_align_v) dpf_output
|
|||
subtractive_share<OutputT, Party>>;
|
||||
|
||||
dpf_output(const dpf_output &) = default;
|
||||
HEDLEY_NO_THROW
|
||||
dpf_output(dpf_output &&) noexcept = default;
|
||||
dpf_output & operator=(const dpf_output &) = default;
|
||||
HEDLEY_NO_THROW
|
||||
dpf_output & operator=(dpf_output &&) noexcept = default;
|
||||
~dpf_output() = default;
|
||||
|
||||
|
|
@ -156,6 +158,7 @@ auto make_eval_dpf_output(const Node & node, Input x)
|
|||
/// Wrap a raw comparison `Beta` value as an additive share when `KeyT` is a
|
||||
/// `party_key`.
|
||||
template <typename KeyT, typename Beta>
|
||||
HEDLEY_NO_THROW
|
||||
auto make_eval_cmp_result(Beta raw) noexcept
|
||||
{
|
||||
if constexpr (is_party_key_v<KeyT>)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/// @file dpf/eval_full.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Evaluate every input in the DPF domain.
|
||||
/// @details Equivalent to `eval_interval` from
|
||||
/// `std::numeric_limits<input_type>::min()` through `max()`.
|
||||
/// @snippet evaluation/eval_full.cpp eval-full
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -135,6 +137,7 @@ auto eval_full(const DpfKey & dpf,
|
|||
return std::make_pair(std::move(outbufs), std::move(iterable));
|
||||
}
|
||||
|
||||
/// Evaluate the whole domain, allocating a basic full memoizer and a buffer.
|
||||
template <std::size_t I = 0,
|
||||
std::size_t ...Is,
|
||||
typename DpfKey,
|
||||
|
|
|
|||
|
|
@ -331,7 +331,12 @@ void eval_prepare_nodes(const DpfKey & dpf, InputT from, InputT to,
|
|||
|
||||
integral_type from_node = utils::get_from_node<dpf_type>(from);
|
||||
integral_type to_node = utils::get_to_node<dpf_type>(to);
|
||||
auto segs = utils::split_leaf_nodes(from_node, to_node, dpf.depth);
|
||||
constexpr auto to_int = utils::to_integral_type<InputT>{};
|
||||
const bool wraps = utils::interval_wraps(
|
||||
static_cast<integral_type>(to_int(from)),
|
||||
static_cast<integral_type>(to_int(to)),
|
||||
utils::bitlength_of_v<InputT>);
|
||||
auto segs = utils::split_leaf_nodes(from_node, to_node, dpf.depth, wraps);
|
||||
// The memoizer keeps one interval. A wrap is two intervals, and walking
|
||||
// the first clobbers the second, so only a single segment can be cached.
|
||||
if (segs.n == 1)
|
||||
|
|
@ -359,7 +364,12 @@ auto eval_inner_product_impl(const DpfKey & dpf, InputT from, InputT to,
|
|||
|
||||
integral_type from_node = utils::get_from_node<dpf_type>(from);
|
||||
integral_type to_node = utils::get_to_node<dpf_type>(to);
|
||||
auto segs = utils::split_leaf_nodes(from_node, to_node, dpf.depth);
|
||||
constexpr auto to_int = utils::to_integral_type<InputT>{};
|
||||
const bool wraps = utils::interval_wraps(
|
||||
static_cast<integral_type>(to_int(from)),
|
||||
static_cast<integral_type>(to_int(to)),
|
||||
utils::bitlength_of_v<InputT>);
|
||||
auto segs = utils::split_leaf_nodes(from_node, to_node, dpf.depth, wraps);
|
||||
|
||||
auto accs = std::make_tuple(
|
||||
ip_accum<typename DpfKey::concrete_output_type<Is>>{}...);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
/// @file dpf/eval_interval.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Evaluate every input in a closed interval.
|
||||
/// @details `[from, to]` is inclusive. The returned iterable yields one
|
||||
/// share per input, in that order. Pass a named output buffer;
|
||||
/// this overload binds it as a non-const reference. An interval
|
||||
/// memoizer is optional and comes after the buffer.
|
||||
/// @snippet evaluation/eval_interval.cpp eval-interval
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -339,7 +343,12 @@ auto eval_interval_impl(const DpfKey & dpf, InputT from, InputT to,
|
|||
|
||||
integral_type from_node = utils::get_from_node<dpf_type>(from),
|
||||
to_node = utils::get_to_node<dpf_type>(to);
|
||||
auto segs = utils::split_leaf_nodes(from_node, to_node, dpf.depth);
|
||||
constexpr auto to_int = utils::to_integral_type<InputT>{};
|
||||
const bool wraps = utils::interval_wraps(
|
||||
static_cast<integral_type>(to_int(from)),
|
||||
static_cast<integral_type>(to_int(to)),
|
||||
utils::bitlength_of_v<InputT>);
|
||||
auto segs = utils::split_leaf_nodes(from_node, to_node, dpf.depth, wraps);
|
||||
|
||||
auto idxs = std::index_sequence<IIs...>{};
|
||||
std::size_t start = 0;
|
||||
|
|
@ -388,6 +397,10 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
|
|||
|
||||
} // namespace internal
|
||||
|
||||
/// Write outputs `I, Is...` for `[from, to]` into `outbufs`.
|
||||
/// @param outbufs Named buffer, or a tuple of buffers when several outputs
|
||||
/// are selected. Must outlive the returned iterable.
|
||||
/// @param memoizer Workspace sized for at least this interval.
|
||||
template <std::size_t I = 0,
|
||||
std::size_t ...Is,
|
||||
typename DpfKey,
|
||||
|
|
@ -404,6 +417,7 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
|
|||
return internal::eval_interval<I, Is...>(dpf, dpf.offset_x(from), dpf.offset_x(to), outbufs, memoizer, std::make_index_sequence<1+sizeof...(Is)>());
|
||||
}
|
||||
|
||||
/// Evaluate `[from, to]` into `outbufs`, allocating a basic interval memoizer.
|
||||
template <std::size_t I = 0,
|
||||
std::size_t ...Is,
|
||||
typename DpfKey,
|
||||
|
|
@ -421,6 +435,9 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
|
|||
dpf::make_basic_interval_memoizer<DpfKey>(from, to));
|
||||
}
|
||||
|
||||
/// Evaluate `[from, to]` with a caller-supplied memoizer.
|
||||
/// @return `std::pair` of a new buffer (or tuple of buffers) and an iterable
|
||||
/// into that buffer.
|
||||
template <std::size_t I = 0,
|
||||
std::size_t ...Is,
|
||||
typename DpfKey,
|
||||
|
|
@ -445,6 +462,7 @@ auto eval_interval(const DpfKey & dpf, InputT from, InputT to,
|
|||
return std::make_pair(std::move(outbufs), std::move(iterable));
|
||||
}
|
||||
|
||||
/// Evaluate `[from, to]`, allocating a basic interval memoizer and a buffer.
|
||||
template <std::size_t I = 0,
|
||||
std::size_t ...Is,
|
||||
typename DpfKey,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/// @file dpf/eval_point.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Evaluate one DPF input.
|
||||
/// @details `eval_point(key, x)` returns a handle; `*handle` is that party's
|
||||
/// share of output 0. `eval_point<I>` selects another output.
|
||||
/// `eval_point<I0, I1, ...>` 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 <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -72,6 +77,10 @@ auto eval_point(const DpfKey & dpf, InputT && x, PathMemoizer && 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::size_t I = 0,
|
||||
typename DpfKey,
|
||||
typename InputT,
|
||||
|
|
@ -88,6 +97,8 @@ auto eval_point(const DpfKey & dpf, InputT && x, PathMemoizer && path = PathMemo
|
|||
internal::eval_point<I>(dpf, tx, path), tx);
|
||||
}
|
||||
|
||||
/// Evaluate several outputs at `x`.
|
||||
/// @return Tuple of shares, already dereferenced.
|
||||
template <std::size_t I0,
|
||||
std::size_t I1,
|
||||
std::size_t ...Is,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/// @file dpf/eval_sequence.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Evaluate a sorted list of DPF inputs.
|
||||
/// @details The range is nondecreasing; an unsorted range throws
|
||||
/// `std::runtime_error`. `return_output_only_tag_` stores one share
|
||||
/// per point. `return_entire_node_tag_` stores whole leaves and is
|
||||
/// the default. A `sequence_recipe` repeats the list, and a sequence
|
||||
/// memoizer bound to that recipe object resumes the traversal.
|
||||
/// @snippet evaluation/eval_sequence.cpp eval-sequence
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -143,6 +148,9 @@ inline auto eval_sequence(const DpfKey & dpf, ForwardIterator begin, ForwardIter
|
|||
}
|
||||
}
|
||||
|
||||
/// Evaluate the sorted range `[begin, end)`, allocating a buffer.
|
||||
/// @param return_type `return_entire_node_tag_{}` or `return_output_only_tag_{}`.
|
||||
/// @return Pair of buffer (or tuple of buffers) and an iterable in list order.
|
||||
template <std::size_t I = 0,
|
||||
std::size_t ...Is,
|
||||
typename DpfKey,
|
||||
|
|
@ -446,6 +454,9 @@ auto eval_sequence(const DpfKey & dpf, const sequence_recipe & recipe,
|
|||
|
||||
} // namespace internal
|
||||
|
||||
/// Evaluate `recipe` into a named buffer, reusing `memoizer`.
|
||||
/// @param recipe The same object `memoizer` was constructed from.
|
||||
/// @param outbufs Named buffer. The returned iterable refers into it.
|
||||
template <std::size_t I = 0,
|
||||
std::size_t ...Is,
|
||||
typename DpfKey,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,15 @@ 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
|
||||
{
|
||||
|
|
@ -53,10 +62,22 @@ 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_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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/// @file dpf/eval_unified.hpp
|
||||
/// @brief Target-first eval surface for DPF / iDPF / DCF channels.
|
||||
/// @details `eval_*(out<I>, …)` and `eval_*(cmp, …)` are the public API.
|
||||
/// @details `eval_*(out<I>, …)` selects point-output slot `I`.
|
||||
/// `eval_*(cmp, …)` selects the comparison channel. Memoizer and
|
||||
/// buffer arguments match the classic overloads: a path memoizer
|
||||
/// on `eval_point`, an output buffer then an interval memoizer on
|
||||
/// `eval_interval`. `make_output_buffer(out<I>, key, from, to)` and
|
||||
/// `make_output_buffer(cmp, key, n)` size the buffer for that channel.
|
||||
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
|
||||
/// @license Released under a GNU General Public v2.0 (GPLv2) license.
|
||||
|
||||
|
|
@ -38,6 +43,7 @@ namespace detail
|
|||
{
|
||||
|
||||
template <std::size_t I, std::size_t N, typename KeyT>
|
||||
HEDLEY_NO_THROW
|
||||
constexpr std::size_t resolved_out_prefix() noexcept
|
||||
{
|
||||
if constexpr (is_multilevel_key_v<KeyT>)
|
||||
|
|
@ -91,6 +97,15 @@ auto eval_point(cmp_t, const KeyT & key, QueryT && x,
|
|||
std::forward<PathMemoizer>(path));
|
||||
}
|
||||
|
||||
template <std::size_t L, typename Beta = uint64_t, typename KeyT, typename QueryT,
|
||||
typename PathMemoizer = basic_path_memoizer<KeyT>>
|
||||
auto eval_point(cmp_prefix_t<L>, const KeyT & key, QueryT && x,
|
||||
PathMemoizer && path = PathMemoizer{})
|
||||
{
|
||||
return detail::incr::eval_cmp_prefix_point_impl<L, Beta>(key,
|
||||
std::forward<QueryT>(x), std::forward<PathMemoizer>(path));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// eval_interval(target, key, from, to [, buf [, memo]])
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -388,11 +403,12 @@ auto eval_out_inner_product_impl(const KeyT & dpf, LaneT from, LaneT to,
|
|||
utils::flip_msb_if_signed_integral(from);
|
||||
utils::flip_msb_if_signed_integral(to);
|
||||
|
||||
integral_type from_node = utils::leaf_node_floor(
|
||||
static_cast<integral_type>(to_int(from)), lg_opl);
|
||||
integral_type to_node = utils::leaf_node_ceil_exclusive(
|
||||
static_cast<integral_type>(to_int(to)), lg_opl);
|
||||
const auto segs = utils::split_leaf_nodes(from_node, to_node, to_level);
|
||||
const auto from_i = static_cast<integral_type>(to_int(from));
|
||||
const auto to_i = static_cast<integral_type>(to_int(to));
|
||||
integral_type from_node = utils::leaf_node_floor(from_i, lg_opl);
|
||||
integral_type to_node = utils::leaf_node_ceil_exclusive(to_i, lg_opl);
|
||||
const bool wraps = utils::interval_wraps(from_i, to_i, N);
|
||||
const auto segs = utils::split_leaf_nodes(from_node, to_node, to_level, wraps);
|
||||
|
||||
ml_ip_accum<output_type, exterior_node> acc{};
|
||||
std::size_t start = 0;
|
||||
|
|
@ -437,15 +453,27 @@ Beta eval_cmp_inner_product_impl(const KeyT & dpf, LaneT from, LaneT to,
|
|||
constexpr std::size_t stop =
|
||||
KeyT::cmp_depth == 0 ? KeyT::depth : KeyT::cmp_depth;
|
||||
detail::incr::cmp_full_interval_memo<KeyT, stop> memo{count};
|
||||
const std::size_t levels = unwrap_party_key_t<KeyT>::cmp_block > 0
|
||||
? unwrap_party_key_t<KeyT>::cmp_h : nbits;
|
||||
detail::incr::eval_cmp_interval_impl_interior(dpf, a, cmp_exclusive_end(b),
|
||||
nbits, memo);
|
||||
nbits, memo, levels);
|
||||
|
||||
uint64_t dot = 0;
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
const auto q = static_cast<integral>(a + static_cast<integral>(i));
|
||||
const uint64_t raw =
|
||||
detail::incr::eval_cmp_from_interval_memo(dpf, q, a, nbits, memo);
|
||||
const uint64_t raw = [&] {
|
||||
if constexpr (unwrap_party_key_t<KeyT>::cmp_block > 0)
|
||||
{
|
||||
return detail::blocked::eval_share_memo(dpf, q, a,
|
||||
cmp_exclusive_end(b), memo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return detail::incr::eval_cmp_from_interval_memo(
|
||||
dpf, q, a, nbits, memo);
|
||||
}
|
||||
}();
|
||||
const uint64_t wt = static_cast<uint64_t>(weights[i]) & mask;
|
||||
dot = (dot + ((raw & mask) * wt)) & mask;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
/// nodes are identical across the two parties, so a dummy word
|
||||
/// cancels.
|
||||
///
|
||||
/// A wildcard-input call takes additive shares of the real point and
|
||||
/// a public query. It samples a random target, runs geneval there,
|
||||
/// and shifts the query by `target - x`, which is what
|
||||
/// `offset_x` does after a wildcard key is bound to `x`.
|
||||
/// Default calls take XOR shares of the point. Tagged with
|
||||
/// `arith_input`, the point is the ring sum of the two shares; path
|
||||
/// bits are opened by a carry chain inside the local CW protocol so
|
||||
/// the words match `make_dpf(x0 + x1)` at the caller's query.
|
||||
///
|
||||
/// `geneval_cmp` is the comparison-channel form. The value-correction
|
||||
/// word is a function of the secret path at every level, so the walk
|
||||
|
|
@ -50,13 +50,6 @@
|
|||
namespace dpf
|
||||
{
|
||||
|
||||
/// Tag for a geneval whose point is known only as additive shares.
|
||||
struct wildcard_input_t
|
||||
{
|
||||
};
|
||||
|
||||
inline constexpr wildcard_input_t wildcard_input{};
|
||||
|
||||
/// Shares and the correction words opened along the query trie.
|
||||
/// `correction_words[i]` / `correction_advice[i]` match a reusable key at
|
||||
/// the same target for every `i < live_levels`. `leaf_live` means the
|
||||
|
|
@ -78,6 +71,7 @@ namespace detail
|
|||
|
||||
template <typename T>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
T geneval_mod_add(T a, T b) noexcept
|
||||
{
|
||||
using U = std::make_unsigned_t<T>;
|
||||
|
|
@ -87,17 +81,6 @@ T geneval_mod_add(T a, T b) noexcept
|
|||
return out;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
T geneval_mod_sub(T a, T b) noexcept
|
||||
{
|
||||
using U = std::make_unsigned_t<T>;
|
||||
U diff = static_cast<U>(static_cast<U>(a) - static_cast<U>(b));
|
||||
T out;
|
||||
std::memcpy(&out, &diff, sizeof(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T geneval_flipped(T x)
|
||||
{
|
||||
|
|
@ -151,8 +134,9 @@ template <typename InteriorPRG,
|
|||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
auto geneval_run(InputT x0, InputT x1, const std::vector<InputT> & queries,
|
||||
RootSampler & root_sampler, PadRng & pads, OutputT y)
|
||||
auto geneval_run(bool arith, InputT x0, InputT x1,
|
||||
const std::vector<InputT> & queries, RootSampler & root_sampler,
|
||||
PadRng & pads, OutputT y)
|
||||
{
|
||||
static_assert(std::is_integral_v<InputT>,
|
||||
"geneval input shares are an integral domain");
|
||||
|
|
@ -172,9 +156,10 @@ auto geneval_run(InputT x0, InputT x1, const std::vector<InputT> & queries,
|
|||
if (queries.size() > (std::size_t{1} << 22))
|
||||
throw std::length_error("geneval query is too large");
|
||||
|
||||
local_cw_protocol<PadRng> proto{pads};
|
||||
InputT x0c = x0;
|
||||
InputT x1c = x1;
|
||||
utils::flip_msb_if_signed_integral(x0c);
|
||||
proto.encode_walk_shares(x0c, x1c, arith);
|
||||
const InputT alpha = utils::xor_input_shares(x0c, x1c);
|
||||
|
||||
std::vector<InputT> flipped;
|
||||
|
|
@ -196,7 +181,6 @@ auto geneval_run(InputT x0, InputT x1, const std::vector<InputT> & queries,
|
|||
|
||||
const uint64_t secret_leaf = geneval_leaf_id<dpf_type>(alpha);
|
||||
|
||||
local_cw_protocol<PadRng> proto{pads};
|
||||
constexpr auto to_int = utils::to_integral_type<InputT>{};
|
||||
|
||||
const node root0 = dpf::unset_lo_bit(static_cast<node>(root_sampler()));
|
||||
|
|
@ -342,6 +326,19 @@ auto geneval_run(InputT x0, InputT x1, const std::vector<InputT> & queries,
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename InteriorPRG,
|
||||
typename ExteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
auto geneval_run(InputT x0, InputT x1, const std::vector<InputT> & queries,
|
||||
RootSampler & root_sampler, PadRng & pads, OutputT y)
|
||||
{
|
||||
return geneval_run<InteriorPRG, ExteriorPRG>(false, x0, x1, queries,
|
||||
root_sampler, pads, y);
|
||||
}
|
||||
|
||||
template <typename InputT>
|
||||
InputT geneval_from_bits(uint64_t bits)
|
||||
{
|
||||
|
|
@ -401,22 +398,6 @@ std::vector<InputT> geneval_inclusive(InputT from, InputT to)
|
|||
return qs;
|
||||
}
|
||||
|
||||
template <typename InputT, typename TargetSampler>
|
||||
InputT geneval_sample_target(TargetSampler & sample)
|
||||
{
|
||||
return static_cast<InputT>(sample());
|
||||
}
|
||||
|
||||
template <typename InputT>
|
||||
std::vector<InputT> geneval_shift_all(const std::vector<InputT> & qs, InputT delta)
|
||||
{
|
||||
std::vector<InputT> out;
|
||||
out.reserve(qs.size());
|
||||
for (const InputT & q : qs)
|
||||
out.push_back(geneval_mod_add(q, delta));
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Geneval at one public point. The secret point is `x0 XOR x1`.
|
||||
|
|
@ -430,7 +411,22 @@ HEDLEY_WARN_UNUSED_RESULT
|
|||
auto geneval_point(InputT x0, InputT x1, InputT query,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(x0, x1,
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(false, x0, x1,
|
||||
std::vector<InputT>{query}, rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
/// Geneval at one public point. The secret point is `x0 + x1`.
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_point(arith_input_t, InputT x0, InputT x1, InputT query,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(true, x0, x1,
|
||||
std::vector<InputT>{query}, rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +441,21 @@ HEDLEY_WARN_UNUSED_RESULT
|
|||
auto geneval_interval(InputT x0, InputT x1, InputT from, InputT to,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(x0, x1,
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(false, x0, x1,
|
||||
detail::geneval_inclusive(from, to), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_interval(arith_input_t, InputT x0, InputT x1, InputT from,
|
||||
InputT to, ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(true, x0, x1,
|
||||
detail::geneval_inclusive(from, to), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
|
|
@ -460,7 +470,21 @@ HEDLEY_WARN_UNUSED_RESULT
|
|||
auto geneval_full(InputT x0, InputT x1,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(x0, x1,
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(false, x0, x1,
|
||||
detail::geneval_full_domain<InputT>(), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_full(arith_input_t, InputT x0, InputT x1,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(true, x0, x1,
|
||||
detail::geneval_full_domain<InputT>(), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
|
|
@ -477,154 +501,10 @@ auto geneval_sequence(InputT x0, InputT x1, ForwardIterator begin,
|
|||
ForwardIterator end, ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
std::vector<InputT> qs(begin, end);
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(x0, x1,
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(false, x0, x1,
|
||||
std::move(qs), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
/// Wildcard-input geneval. `x0 + x1` is the real point (additive shares).
|
||||
/// `sample_target()` is the random DPF target; the public query is shifted
|
||||
/// by `target - (x0 + x1)` before the walk.
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng,
|
||||
typename TargetSampler>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_point(wildcard_input_t, InputT x0, InputT x1, InputT query,
|
||||
ds_randomness<RootSampler, PadRng> rng, TargetSampler sample_target,
|
||||
OutputT y)
|
||||
{
|
||||
const InputT alpha = detail::geneval_sample_target<InputT>(sample_target);
|
||||
const InputT delta = detail::geneval_mod_sub(alpha,
|
||||
detail::geneval_mod_add(x0, x1));
|
||||
const InputT shifted = detail::geneval_mod_add(query, delta);
|
||||
InputT zero{};
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(zero, alpha,
|
||||
std::vector<InputT>{shifted}, rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_point(wildcard_input_t, InputT x0, InputT x1, InputT query,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return geneval_point<InteriorPRG, ExteriorPRG>(wildcard_input, x0, x1, query,
|
||||
std::move(rng), [] { return dpf::uniform_sample<InputT>(); }, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng,
|
||||
typename TargetSampler>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_interval(wildcard_input_t, InputT x0, InputT x1, InputT from,
|
||||
InputT to, ds_randomness<RootSampler, PadRng> rng, TargetSampler sample_target,
|
||||
OutputT y)
|
||||
{
|
||||
const InputT alpha = detail::geneval_sample_target<InputT>(sample_target);
|
||||
const InputT delta = detail::geneval_mod_sub(alpha,
|
||||
detail::geneval_mod_add(x0, x1));
|
||||
auto shifted = detail::geneval_shift_all(
|
||||
detail::geneval_inclusive(from, to), delta);
|
||||
InputT zero{};
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(zero, alpha,
|
||||
std::move(shifted), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_interval(wildcard_input_t, InputT x0, InputT x1, InputT from,
|
||||
InputT to, ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return geneval_interval<InteriorPRG, ExteriorPRG>(wildcard_input, x0, x1,
|
||||
from, to, std::move(rng), [] { return dpf::uniform_sample<InputT>(); }, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng,
|
||||
typename TargetSampler>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_full(wildcard_input_t, InputT x0, InputT x1,
|
||||
ds_randomness<RootSampler, PadRng> rng, TargetSampler sample_target, OutputT y)
|
||||
{
|
||||
const InputT alpha = detail::geneval_sample_target<InputT>(sample_target);
|
||||
const InputT delta = detail::geneval_mod_sub(alpha,
|
||||
detail::geneval_mod_add(x0, x1));
|
||||
InputT zero{};
|
||||
auto full = detail::geneval_run<InteriorPRG, ExteriorPRG>(zero, alpha,
|
||||
detail::geneval_full_domain<InputT>(), rng.root, rng.pad, y);
|
||||
constexpr auto to_int = utils::to_integral_type<InputT>{};
|
||||
const std::size_t n = full.party0.size();
|
||||
std::vector<OutputT> p0(n), p1(n);
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
InputT q = detail::geneval_from_bits<InputT>(i);
|
||||
InputT s = detail::geneval_mod_add(q, delta);
|
||||
const std::size_t si = static_cast<std::size_t>(to_int(s));
|
||||
p0[i] = full.party0[si];
|
||||
p1[i] = full.party1[si];
|
||||
}
|
||||
full.party0 = std::move(p0);
|
||||
full.party1 = std::move(p1);
|
||||
return full;
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_full(wildcard_input_t, InputT x0, InputT x1,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return geneval_full<InteriorPRG, ExteriorPRG>(wildcard_input, x0, x1,
|
||||
std::move(rng), [] { return dpf::uniform_sample<InputT>(); }, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename OutputT,
|
||||
typename RootSampler,
|
||||
typename PadRng,
|
||||
typename ForwardIterator,
|
||||
typename TargetSampler>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_sequence(wildcard_input_t, InputT x0, InputT x1,
|
||||
ForwardIterator begin, ForwardIterator end,
|
||||
ds_randomness<RootSampler, PadRng> rng, TargetSampler sample_target, OutputT y)
|
||||
{
|
||||
const InputT alpha = detail::geneval_sample_target<InputT>(sample_target);
|
||||
const InputT delta = detail::geneval_mod_sub(alpha,
|
||||
detail::geneval_mod_add(x0, x1));
|
||||
std::vector<InputT> qs(begin, end);
|
||||
auto shifted = detail::geneval_shift_all(qs, delta);
|
||||
InputT zero{};
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(zero, alpha,
|
||||
std::move(shifted), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
|
|
@ -633,12 +513,13 @@ template <typename InteriorPRG = dpf::prg::aes128,
|
|||
typename PadRng,
|
||||
typename ForwardIterator>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto geneval_sequence(wildcard_input_t, InputT x0, InputT x1,
|
||||
auto geneval_sequence(arith_input_t, InputT x0, InputT x1,
|
||||
ForwardIterator begin, ForwardIterator end,
|
||||
ds_randomness<RootSampler, PadRng> rng, OutputT y)
|
||||
{
|
||||
return geneval_sequence<InteriorPRG, ExteriorPRG>(wildcard_input, x0, x1,
|
||||
begin, end, std::move(rng), [] { return dpf::uniform_sample<InputT>(); }, y);
|
||||
std::vector<InputT> qs(begin, end);
|
||||
return detail::geneval_run<InteriorPRG, ExteriorPRG>(true, x0, x1,
|
||||
std::move(qs), rng.root, rng.pad, y);
|
||||
}
|
||||
|
||||
/// Opened comparison key material and one prefix share per endpoint.
|
||||
|
|
@ -651,6 +532,7 @@ struct geneval_cmp_result
|
|||
std::vector<simde__m128i, aligned_allocator<simde__m128i>> correction_words;
|
||||
std::vector<uint8_t> correction_advice;
|
||||
std::vector<uint64_t> value_cw;
|
||||
std::vector<uint64_t> tail_cw;
|
||||
uint64_t cw_last = 0;
|
||||
uint64_t addend0 = 0;
|
||||
uint64_t addend1 = 0;
|
||||
|
|
@ -689,12 +571,77 @@ geneval_cmp_result geneval_cmp(InputT x0, InputT x1,
|
|||
out.addend1 = k1.cmp_addend().raw();
|
||||
out.correction_words.resize(depth);
|
||||
out.correction_advice.resize(depth);
|
||||
out.value_cw.resize(depth);
|
||||
if constexpr (key_type::cmp_block > 0)
|
||||
{
|
||||
out.value_cw.resize(key_type::cmp_checkpoints);
|
||||
for (std::size_t i = 0; i < key_type::cmp_checkpoints; ++i)
|
||||
out.value_cw[i] = k0.value_cw(i);
|
||||
out.tail_cw.resize(key_type::cmp_tail);
|
||||
for (std::size_t z = 0; z < key_type::cmp_tail; ++z)
|
||||
out.tail_cw[z] = k0.tail_cw(z);
|
||||
}
|
||||
else
|
||||
out.value_cw.resize(depth);
|
||||
for (std::size_t level = 0; level < depth; ++level)
|
||||
{
|
||||
out.correction_words[level] = k0.correction_word(level);
|
||||
out.correction_advice[level] = static_cast<uint8_t>(k0.correction_advice(level));
|
||||
out.value_cw[level] = k0.value_cw(level);
|
||||
if constexpr (key_type::cmp_block == 0)
|
||||
out.value_cw[level] = k0.value_cw(level);
|
||||
}
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
out.party0.push_back(eval_point(dpf::cmp, k0, *it).raw());
|
||||
out.party1.push_back(eval_point(dpf::cmp, k1, *it).raw());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Comparison geneval with additive shares of the point (`x0 + x1`).
|
||||
template <typename InputT,
|
||||
typename ForwardIterator,
|
||||
typename RootSampler,
|
||||
typename PadRng,
|
||||
typename Spec>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
geneval_cmp_result geneval_cmp(arith_input_t, InputT x0, InputT x1,
|
||||
ForwardIterator begin, ForwardIterator end,
|
||||
ds_randomness<RootSampler, PadRng> rng, Spec spec)
|
||||
{
|
||||
geneval_cmp_result out;
|
||||
if (begin == end)
|
||||
return out;
|
||||
|
||||
auto keys = make_dpf_doerner_shelat(arith_input, std::move(x0), std::move(x1),
|
||||
std::move(rng), std::move(spec));
|
||||
const auto & k0 = keys.first;
|
||||
const auto & k1 = keys.second;
|
||||
using key_type = std::decay_t<decltype(k0)>;
|
||||
constexpr std::size_t depth = key_type::depth;
|
||||
out.live_levels = depth;
|
||||
out.mask = k0.cmp().mask;
|
||||
out.cw_last = k0.cw_last();
|
||||
out.addend0 = k0.cmp_addend().raw();
|
||||
out.addend1 = k1.cmp_addend().raw();
|
||||
out.correction_words.resize(depth);
|
||||
out.correction_advice.resize(depth);
|
||||
if constexpr (key_type::cmp_block > 0)
|
||||
{
|
||||
out.value_cw.resize(key_type::cmp_checkpoints);
|
||||
for (std::size_t i = 0; i < key_type::cmp_checkpoints; ++i)
|
||||
out.value_cw[i] = k0.value_cw(i);
|
||||
out.tail_cw.resize(key_type::cmp_tail);
|
||||
for (std::size_t z = 0; z < key_type::cmp_tail; ++z)
|
||||
out.tail_cw[z] = k0.tail_cw(z);
|
||||
}
|
||||
else
|
||||
out.value_cw.resize(depth);
|
||||
for (std::size_t level = 0; level < depth; ++level)
|
||||
{
|
||||
out.correction_words[level] = k0.correction_word(level);
|
||||
out.correction_advice[level] = static_cast<uint8_t>(k0.correction_advice(level));
|
||||
if constexpr (key_type::cmp_block == 0)
|
||||
out.value_cw[level] = k0.value_cw(level);
|
||||
}
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
|
|
@ -718,6 +665,19 @@ geneval_cmp_result geneval_cmp(InputT x0, InputT x1,
|
|||
std::move(rng), dpf::gt(beta));
|
||||
}
|
||||
|
||||
template <typename InputT,
|
||||
typename ForwardIterator,
|
||||
typename RootSampler,
|
||||
typename PadRng>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
geneval_cmp_result geneval_cmp(arith_input_t, InputT x0, InputT x1,
|
||||
ForwardIterator begin, ForwardIterator end,
|
||||
ds_randomness<RootSampler, PadRng> rng, uint64_t beta)
|
||||
{
|
||||
return geneval_cmp(arith_input, std::move(x0), std::move(x1), begin, end,
|
||||
std::move(rng), dpf::gt(beta));
|
||||
}
|
||||
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_GENEVAL_HPP__
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
674
include/dpf/interval.hpp
Normal file
674
include/dpf/interval.hpp
Normal file
|
|
@ -0,0 +1,674 @@
|
|||
/// @file dpf/interval.hpp
|
||||
/// @brief Public-bound interval containment on one comparison key.
|
||||
/// @details `make_dpf(r, ic(p, q, β))` hides the mask `r` and the payload `β`.
|
||||
/// The bounds are public. Reconstruction is `β` when
|
||||
/// `p ≤ (x − r) mod 2^n ≤ q`, and the false payload otherwise.
|
||||
///
|
||||
/// The key is one `lt` comparison at `γ = r − 1`, the Boyle–Chandran–
|
||||
/// Gilboa–Gupta–Ishai–Kumar–Rathee reduction (EUROCRYPT 2021, Fig. 3).
|
||||
/// Evaluation walks that key at the two public shifts of `x` and adds
|
||||
/// a secret-shared correction. Seed corrections, advice bits, leaves,
|
||||
/// and the path memoizer stay single-path.
|
||||
/// @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_INTERVAL_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_INTERVAL_HPP__
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
|
||||
#include "dpf/dcf.hpp"
|
||||
#include "dpf/eval_unified.hpp"
|
||||
#include "dpf/geneval.hpp"
|
||||
#include "dpf/incremental.hpp"
|
||||
#include "dpf/output_buffer.hpp"
|
||||
#include "dpf/secret_share.hpp"
|
||||
#include "dpf/utils.hpp"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
|
||||
template <typename Beta>
|
||||
struct ic_pack
|
||||
{
|
||||
static constexpr bool is_ic = true;
|
||||
using beta_type = Beta;
|
||||
uint64_t lo = 0;
|
||||
uint64_t hi = 0;
|
||||
Beta if_true{};
|
||||
Beta if_false{};
|
||||
};
|
||||
|
||||
/// Spec tag and factory. `dpf::ic(p, q, beta)` builds a pack;
|
||||
/// `eval_point(dpf::ic, key, x)` evaluates it.
|
||||
struct ic_fn
|
||||
{
|
||||
template <typename Lo, typename Hi, typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
ic_pack<std::decay_t<Beta>> operator()(Lo lo, Hi hi, Beta t,
|
||||
Beta f = detail::dcf_impl::default_false<std::decay_t<Beta>>()) const
|
||||
{
|
||||
ic_pack<std::decay_t<Beta>> spec;
|
||||
spec.lo = static_cast<uint64_t>(lo);
|
||||
spec.hi = static_cast<uint64_t>(hi);
|
||||
spec.if_true = std::move(t);
|
||||
spec.if_false = std::move(f);
|
||||
return spec;
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr ic_fn ic{};
|
||||
|
||||
template <typename T>
|
||||
struct is_ic_key : std::false_type {};
|
||||
|
||||
template <std::size_t Party, typename Key, typename Input, typename Beta>
|
||||
struct ic_key
|
||||
{
|
||||
static constexpr std::size_t party = Party;
|
||||
static constexpr bool wildcard = Key::cmp_is_wildcard;
|
||||
using input_type = Input;
|
||||
using key_type = party_key<Party, Key>;
|
||||
using beta_type = Beta;
|
||||
|
||||
key_type key;
|
||||
uint64_t lo = 0;
|
||||
uint64_t hi = 0;
|
||||
uint64_t input_mask = 0;
|
||||
uint64_t group_mask = 0;
|
||||
/// Share of `δ`. Public `c_x ∈ {-1,0,1}` scales it locally.
|
||||
uint64_t delta_share = 0;
|
||||
/// Share of `δ · c_r + if_false`.
|
||||
uint64_t cr_share = 0;
|
||||
/// Wildcard only: shares of `1` and of `c_r`, scaled by `δ` in `assign_cmp`.
|
||||
uint64_t delta_coeff = 0;
|
||||
uint64_t cr_coeff = 0;
|
||||
bool assigned = !wildcard;
|
||||
|
||||
ic_key(key_type k, uint64_t lo_in, uint64_t hi_in, uint64_t nmask,
|
||||
uint64_t gmask, uint64_t dshare, uint64_t cshare, uint64_t dcoeff,
|
||||
uint64_t ccoeff)
|
||||
: key(std::move(k))
|
||||
, lo(lo_in)
|
||||
, hi(hi_in)
|
||||
, input_mask(nmask)
|
||||
, group_mask(gmask)
|
||||
, delta_share(dshare)
|
||||
, cr_share(cshare)
|
||||
, delta_coeff(dcoeff)
|
||||
, cr_coeff(ccoeff)
|
||||
{}
|
||||
};
|
||||
|
||||
template <std::size_t Party, typename Key, typename Input, typename Beta>
|
||||
struct is_ic_key<ic_key<Party, Key, Input, Beta>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_ic_key_v = is_ic_key<std::decay_t<T>>::value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace ic_impl
|
||||
{
|
||||
|
||||
template <typename Input>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t input_mask_of() noexcept
|
||||
{
|
||||
constexpr auto n = utils::bitlength_of_v<Input>;
|
||||
if constexpr (n >= 64)
|
||||
return ~uint64_t{0};
|
||||
else
|
||||
return (uint64_t{1} << n) - 1ULL;
|
||||
}
|
||||
|
||||
template <typename Input>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t bits_of(Input x) noexcept
|
||||
{
|
||||
constexpr auto to_int = utils::to_integral_type<Input>{};
|
||||
return static_cast<uint64_t>(to_int(x)) & input_mask_of<Input>();
|
||||
}
|
||||
|
||||
template <typename Input>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr Input input_from_bits(uint64_t u) noexcept
|
||||
{
|
||||
return static_cast<Input>(u & input_mask_of<Input>());
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t embed_small(int s, uint64_t mask) noexcept
|
||||
{
|
||||
if (s >= 0)
|
||||
return static_cast<uint64_t>(s) & mask;
|
||||
return dcf_impl::neg_m(static_cast<uint64_t>(-s), mask);
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t mul_mask(uint64_t a, uint64_t b, uint64_t mask) noexcept
|
||||
{
|
||||
return static_cast<uint64_t>(static_cast<unsigned __int128>(a) * b) & mask;
|
||||
}
|
||||
|
||||
/// Dealer correction in Fig. 3, as an element of the payload group.
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t correction(uint64_t r, uint64_t p, uint64_t q,
|
||||
uint64_t nmask, uint64_t gmask) noexcept
|
||||
{
|
||||
const uint64_t aq = (q + r) & nmask;
|
||||
const uint64_t ap = (p + r) & nmask;
|
||||
const uint64_t q0 = (q + 1ULL) & nmask;
|
||||
const uint64_t aq0 = (q0 + r) & nmask;
|
||||
const int s = (ap > aq ? 1 : 0) - (ap > p ? 1 : 0)
|
||||
+ (aq0 > q0 ? 1 : 0) + (aq == nmask ? 1 : 0);
|
||||
return embed_small(s, gmask);
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr int public_cx(uint64_t x, uint64_t p, uint64_t q, uint64_t nmask) noexcept
|
||||
{
|
||||
const uint64_t q0 = (q + 1ULL) & nmask;
|
||||
return (x > p ? 1 : 0) - (x > q0 ? 1 : 0);
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t shift_p(uint64_t x, uint64_t p, uint64_t nmask) noexcept
|
||||
{
|
||||
return (x + (nmask - p)) & nmask;
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t shift_q0(uint64_t x, uint64_t q, uint64_t nmask) noexcept
|
||||
{
|
||||
const uint64_t q0 = (q + 1ULL) & nmask;
|
||||
return (x + (nmask - q0)) & nmask;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
uint64_t opened_u64(const T & v, uint64_t mask) noexcept
|
||||
{
|
||||
if constexpr (is_secret_share_v<std::decay_t<T>>)
|
||||
return dcf_impl::beta_to_u64_simple(v.raw(), mask);
|
||||
else
|
||||
return dcf_impl::beta_to_u64_simple(v, mask);
|
||||
}
|
||||
|
||||
inline void split_target(uint64_t target, uint64_t mask,
|
||||
uint64_t & s0, uint64_t & s1)
|
||||
{
|
||||
const uint64_t blind = dcf_impl::sample_addend_blind(mask,
|
||||
[] { return dpf::uniform_sample<simde__m128i>(); });
|
||||
incr::split_cmp_addend(target, mask, blind, s0, s1);
|
||||
}
|
||||
|
||||
template <typename Input>
|
||||
void check_input()
|
||||
{
|
||||
static_assert(std::is_unsigned_v<Input> && !std::is_same_v<Input, bool>,
|
||||
"ic: input type must be an unsigned integer of at most 64 bits");
|
||||
static_assert(utils::bitlength_of_v<Input> <= 64,
|
||||
"ic: input type must be an unsigned integer of at most 64 bits");
|
||||
static_assert(utils::bitlength_of_v<Input> > 0,
|
||||
"ic: input type must be an unsigned integer of at most 64 bits");
|
||||
}
|
||||
|
||||
template <typename Input, typename Beta>
|
||||
void check_bounds(const ic_pack<Beta> & spec)
|
||||
{
|
||||
const uint64_t nmask = input_mask_of<Input>();
|
||||
if (spec.lo > nmask || spec.hi > nmask)
|
||||
throw std::invalid_argument("ic: bound does not fit in the input domain");
|
||||
if (spec.lo > spec.hi)
|
||||
throw std::invalid_argument("ic: require lo <= hi (the interval does not wrap)");
|
||||
}
|
||||
|
||||
template <typename Beta>
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t group_mask_of() noexcept
|
||||
{
|
||||
using B = concrete_type_t<Beta>;
|
||||
if constexpr (std::is_same_v<B, dpf::bit>)
|
||||
return 1ULL;
|
||||
else
|
||||
return dcf_impl::default_mask_for_bits(utils::bitlength_of_v<B>);
|
||||
}
|
||||
|
||||
template <std::size_t Party, typename Key, typename Input, typename Beta>
|
||||
ic_key<Party, Key, Input, Beta> make_side(party_key<Party, Key> key,
|
||||
uint64_t lo, uint64_t hi, uint64_t nmask, uint64_t gmask,
|
||||
uint64_t delta_share, uint64_t cr_share,
|
||||
uint64_t delta_coeff, uint64_t cr_coeff)
|
||||
{
|
||||
return ic_key<Party, Key, Input, Beta>(std::move(key), lo, hi, nmask, gmask,
|
||||
delta_share, cr_share, delta_coeff, cr_coeff);
|
||||
}
|
||||
|
||||
template <typename Input, typename Beta, typename Pair>
|
||||
auto finish(uint64_t r_bits, const ic_pack<Beta> & spec, Pair && inner)
|
||||
{
|
||||
using in_type = std::decay_t<Input>;
|
||||
using party0 = std::decay_t<decltype(inner.first)>;
|
||||
using raw_key = typename party0::key_type;
|
||||
using out_beta = concrete_type_t<Beta>;
|
||||
const uint64_t nmask = input_mask_of<in_type>();
|
||||
const uint64_t gmask = group_mask_of<Beta>();
|
||||
constexpr bool wild = is_wildcard_v<Beta>;
|
||||
uint64_t delta = 0;
|
||||
uint64_t fval = 0;
|
||||
if constexpr (!wild)
|
||||
{
|
||||
delta = dcf_impl::beta_delta_u64(spec.if_true, spec.if_false, gmask);
|
||||
fval = dcf_impl::beta_to_u64_simple(spec.if_false, gmask);
|
||||
}
|
||||
const uint64_t cr = correction(r_bits, spec.lo, spec.hi, nmask, gmask);
|
||||
|
||||
uint64_t d0 = 0, d1 = 0, c0 = 0, c1 = 0;
|
||||
uint64_t dc0 = 0, dc1 = 0, cc0 = 0, cc1 = 0;
|
||||
if constexpr (wild)
|
||||
{
|
||||
split_target(1ULL & gmask, gmask, dc0, dc1);
|
||||
split_target(cr, gmask, cc0, cc1);
|
||||
}
|
||||
else
|
||||
{
|
||||
split_target(delta, gmask, d0, d1);
|
||||
const uint64_t absorb =
|
||||
(mul_mask(delta, cr, gmask) + fval) & gmask;
|
||||
split_target(absorb, gmask, c0, c1);
|
||||
}
|
||||
|
||||
auto k0 = make_side<0, raw_key, in_type, out_beta>(std::move(inner.first),
|
||||
spec.lo, spec.hi, nmask, gmask, d0, c0, dc0, cc0);
|
||||
auto k1 = make_side<1, raw_key, in_type, out_beta>(std::move(inner.second),
|
||||
spec.lo, spec.hi, nmask, gmask, d1, c1, dc1, cc1);
|
||||
return std::make_pair(std::move(k0), std::move(k1));
|
||||
}
|
||||
|
||||
template <typename Beta>
|
||||
auto inner_lt(const ic_pack<Beta> & spec)
|
||||
{
|
||||
using B = std::decay_t<Beta>;
|
||||
if constexpr (is_wildcard_v<B>)
|
||||
return lt(spec.if_true, spec.if_false);
|
||||
else
|
||||
{
|
||||
const uint64_t gmask = group_mask_of<B>();
|
||||
const uint64_t delta =
|
||||
dcf_impl::beta_delta_u64(spec.if_true, spec.if_false, gmask);
|
||||
return lt(dcf_impl::u64_to_beta<B>(delta), dcf_impl::u64_to_beta<B>(0));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Input>
|
||||
Input gamma_of(Input r)
|
||||
{
|
||||
const uint64_t nmask = input_mask_of<Input>();
|
||||
const uint64_t ru = bits_of(r);
|
||||
return input_from_bits<Input>((ru - 1ULL) & nmask);
|
||||
}
|
||||
|
||||
template <typename IcKey, typename Query, typename Memo>
|
||||
auto eval_one(const IcKey & k, Query && x, Memo & memo)
|
||||
{
|
||||
if (!k.assigned)
|
||||
throw std::invalid_argument(
|
||||
"ic eval: wildcard payload not assigned (call assign_cmp)");
|
||||
using in_type = typename IcKey::input_type;
|
||||
const uint64_t xu = bits_of(in_type(std::forward<Query>(x)));
|
||||
const uint64_t xp = shift_p(xu, k.lo, k.input_mask);
|
||||
const uint64_t xq = shift_q0(xu, k.hi, k.input_mask);
|
||||
const uint64_t a = opened_u64(
|
||||
eval_point(dpf::cmp, k.key, input_from_bits<in_type>(xp), memo),
|
||||
k.group_mask);
|
||||
const uint64_t b = opened_u64(
|
||||
eval_point(dpf::cmp, k.key, input_from_bits<in_type>(xq), memo),
|
||||
k.group_mask);
|
||||
const int cx = public_cx(xu, k.lo, k.hi, k.input_mask);
|
||||
uint64_t scaled = 0;
|
||||
if (cx == 1)
|
||||
scaled = k.delta_share & k.group_mask;
|
||||
else if (cx == -1)
|
||||
scaled = dcf_impl::neg_m(k.delta_share, k.group_mask);
|
||||
const uint64_t y = (dcf_impl::neg_m(a, k.group_mask) + b + k.cr_share
|
||||
+ scaled) & k.group_mask;
|
||||
return make_eval_cmp_result<typename IcKey::key_type>(
|
||||
dcf_impl::u64_to_beta<typename IcKey::beta_type>(y));
|
||||
}
|
||||
|
||||
} // namespace ic_impl
|
||||
} // namespace detail
|
||||
|
||||
/// Dealer key for public bounds `spec` and secret mask `r`.
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto make_dpf(InputT && r, const ic_pack<Beta> & spec)
|
||||
{
|
||||
using input_type = std::decay_t<InputT>;
|
||||
detail::ic_impl::check_input<input_type>();
|
||||
detail::ic_impl::check_bounds<input_type>(spec);
|
||||
const uint64_t r_bits = detail::ic_impl::bits_of(input_type(r));
|
||||
const input_type gamma = detail::ic_impl::gamma_of(input_type(r));
|
||||
auto inner = make_dpf<InteriorPRG, ExteriorPRG>(gamma,
|
||||
detail::ic_impl::inner_lt(spec));
|
||||
return detail::ic_impl::finish<input_type>(r_bits, spec, std::move(inner));
|
||||
}
|
||||
|
||||
/// Doerner–Shelat key. `r0 XOR r1` is the secret mask.
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename RootSampler,
|
||||
typename PadRng,
|
||||
typename InputT,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto make_dpf_doerner_shelat(InputT r0, InputT r1,
|
||||
ds_randomness<RootSampler, PadRng> rng, const ic_pack<Beta> & spec)
|
||||
{
|
||||
using input_type = std::decay_t<InputT>;
|
||||
detail::ic_impl::check_input<input_type>();
|
||||
detail::ic_impl::check_bounds<input_type>(spec);
|
||||
const input_type r = utils::xor_input_shares(r0, r1);
|
||||
const uint64_t r_bits = detail::ic_impl::bits_of(r);
|
||||
const input_type gamma = detail::ic_impl::gamma_of(r);
|
||||
const input_type g0 = r0;
|
||||
const input_type g1 = utils::xor_input_shares(g0, gamma);
|
||||
auto inner = make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(g0, g1,
|
||||
std::move(rng), detail::ic_impl::inner_lt(spec));
|
||||
return detail::ic_impl::finish<input_type>(r_bits, spec, std::move(inner));
|
||||
}
|
||||
|
||||
/// Doerner–Shelat IC key. `r0 + r1` is the secret mask; γ = (r0 + r1) − 1.
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename RootSampler,
|
||||
typename PadRng,
|
||||
typename InputT,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto make_dpf_doerner_shelat(arith_input_t, InputT r0, InputT r1,
|
||||
ds_randomness<RootSampler, PadRng> rng, const ic_pack<Beta> & spec)
|
||||
{
|
||||
using input_type = std::decay_t<InputT>;
|
||||
detail::ic_impl::check_input<input_type>();
|
||||
detail::ic_impl::check_bounds<input_type>(spec);
|
||||
const uint64_t nmask = detail::ic_impl::input_mask_of<input_type>();
|
||||
const uint64_t r_bits =
|
||||
(detail::ic_impl::bits_of(r0) + detail::ic_impl::bits_of(r1)) & nmask;
|
||||
const input_type r = detail::ic_impl::input_from_bits<input_type>(r_bits);
|
||||
// Additive shares of γ = r − 1: (r0 − 1, r1).
|
||||
const input_type g0 = detail::ic_impl::input_from_bits<input_type>(
|
||||
(detail::ic_impl::bits_of(r0) - 1ULL) & nmask);
|
||||
const input_type g1 = r1;
|
||||
auto inner = make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||||
arith_input, g0, g1, std::move(rng), detail::ic_impl::inner_lt(spec));
|
||||
return detail::ic_impl::finish<input_type>(
|
||||
detail::ic_impl::bits_of(r), spec, std::move(inner));
|
||||
}
|
||||
|
||||
/// Doerner–Shelat key sampled from the library entropy source.
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto make_dpf_doerner_shelat(InputT r0, InputT r1, const ic_pack<Beta> & spec)
|
||||
{
|
||||
using block = typename InteriorPRG::block_type;
|
||||
ds_randomness<block (*)(), detail::urandom_pad_rng> rng{
|
||||
dpf::uniform_sample<block>, {}};
|
||||
return make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||||
std::move(r0), std::move(r1), rng, spec);
|
||||
}
|
||||
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto make_dpf_doerner_shelat(arith_input_t, InputT r0, InputT r1,
|
||||
const ic_pack<Beta> & spec)
|
||||
{
|
||||
using block = typename InteriorPRG::block_type;
|
||||
ds_randomness<block (*)(), detail::urandom_pad_rng> rng{
|
||||
dpf::uniform_sample<block>, {}};
|
||||
return make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||||
arith_input, std::move(r0), std::move(r1), rng, spec);
|
||||
}
|
||||
|
||||
/// Open a wildcard interval payload onto an existing key pair.
|
||||
template <typename Key, typename Input, typename Beta, typename Payload>
|
||||
void assign_cmp(ic_key<0, Key, Input, Beta> & k0,
|
||||
ic_key<1, Key, Input, Beta> & k1, const Payload & if_true,
|
||||
const Payload & if_false = Payload{})
|
||||
{
|
||||
static_assert(Key::cmp_is_wildcard,
|
||||
"assign_cmp: interval payload is not a wildcard");
|
||||
const uint64_t mask = k0.group_mask;
|
||||
const uint64_t delta =
|
||||
detail::dcf_impl::beta_delta_u64(if_true, if_false, mask);
|
||||
const uint64_t fval =
|
||||
detail::dcf_impl::beta_to_u64_simple(if_false, mask);
|
||||
assign_cmp(k0.key, k1.key,
|
||||
detail::dcf_impl::u64_to_beta<Beta>(delta),
|
||||
detail::dcf_impl::u64_to_beta<Beta>(0));
|
||||
k0.delta_share = detail::ic_impl::mul_mask(k0.delta_coeff, delta, mask);
|
||||
k1.delta_share = detail::ic_impl::mul_mask(k1.delta_coeff, delta, mask);
|
||||
k0.cr_share = detail::ic_impl::mul_mask(k0.cr_coeff, delta, mask);
|
||||
k1.cr_share = detail::ic_impl::mul_mask(k1.cr_coeff, delta, mask);
|
||||
uint64_t f0 = 0, f1 = 0;
|
||||
detail::ic_impl::split_target(fval, mask, f0, f1);
|
||||
k0.cr_share = (k0.cr_share + f0) & mask;
|
||||
k1.cr_share = (k1.cr_share + f1) & mask;
|
||||
k0.assigned = true;
|
||||
k1.assigned = true;
|
||||
}
|
||||
|
||||
/// Point evaluation. `memo` is a path memoizer for the inner comparison key.
|
||||
template <typename IcKey, typename Query,
|
||||
typename Memo = basic_path_memoizer<typename IcKey::key_type>,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto eval_point(ic_fn, const IcKey & key, Query && x, Memo && memo = Memo{})
|
||||
{
|
||||
return detail::ic_impl::eval_one(key, std::forward<Query>(x), memo);
|
||||
}
|
||||
|
||||
/// Inclusive interval `[from, to]` on the input domain.
|
||||
template <typename IcKey, typename Lane, typename Buffer, typename Memo,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
void eval_interval(ic_fn, const IcKey & key, Lane from, Lane to,
|
||||
Buffer && buf, Memo && memo)
|
||||
{
|
||||
using in_type = typename IcKey::input_type;
|
||||
const uint64_t nmask = key.input_mask;
|
||||
const uint64_t a = detail::ic_impl::bits_of(in_type(from));
|
||||
const uint64_t b = detail::ic_impl::bits_of(in_type(to));
|
||||
if (a > b)
|
||||
throw std::invalid_argument("ic interval: to < from");
|
||||
std::size_t i = 0;
|
||||
for (uint64_t x = a;; ++x)
|
||||
{
|
||||
buf[i++] = detail::ic_impl::eval_one(key,
|
||||
detail::ic_impl::input_from_bits<in_type>(x), memo);
|
||||
if (x == b)
|
||||
break;
|
||||
if (x == nmask)
|
||||
throw std::invalid_argument("ic interval: to < from");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IcKey, typename Lane, typename Buffer,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
void eval_interval(ic_fn, const IcKey & key, Lane from, Lane to, Buffer && buf)
|
||||
{
|
||||
basic_path_memoizer<typename IcKey::key_type> memo;
|
||||
eval_interval(ic, key, from, to, std::forward<Buffer>(buf), memo);
|
||||
}
|
||||
|
||||
/// Evaluate the points in `[begin, end)`.
|
||||
template <typename IcKey, typename Iter, typename Buffer, typename Memo,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
void eval_sequence(ic_fn, const IcKey & key, Iter begin, Iter end,
|
||||
Buffer && buf, Memo && memo)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
for (auto it = begin; it != end; ++it, ++i)
|
||||
buf[i] = detail::ic_impl::eval_one(key, *it, memo);
|
||||
}
|
||||
|
||||
template <typename IcKey, typename Iter, typename Buffer,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
void eval_sequence(ic_fn, const IcKey & key, Iter begin, Iter end, Buffer && buf)
|
||||
{
|
||||
basic_path_memoizer<typename IcKey::key_type> memo;
|
||||
eval_sequence(ic, key, begin, end, std::forward<Buffer>(buf), memo);
|
||||
}
|
||||
|
||||
/// Buffer of `n` interval shares.
|
||||
template <typename IcKey, typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto make_output_buffer(ic_fn, const IcKey &, std::size_t n)
|
||||
{
|
||||
using beta = typename IcKey::beta_type;
|
||||
using elem = cmp_buffer_elem_t<typename IcKey::key_type, beta>;
|
||||
return output_buffer<elem>(n);
|
||||
}
|
||||
|
||||
/// Buffer large enough for the inclusive interval `[from, to]`.
|
||||
template <typename IcKey, typename Lane,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
auto make_output_buffer(ic_fn, const IcKey & key, Lane from, Lane to)
|
||||
{
|
||||
using in_type = typename IcKey::input_type;
|
||||
const uint64_t a = detail::ic_impl::bits_of(in_type(from));
|
||||
const uint64_t b = detail::ic_impl::bits_of(in_type(to));
|
||||
if (a > b)
|
||||
throw std::invalid_argument("ic interval: to < from");
|
||||
const uint64_t n = b - a + 1ULL;
|
||||
return make_output_buffer(ic, key, static_cast<std::size_t>(n));
|
||||
}
|
||||
|
||||
/// Doerner–Shelat geneval. `r0 XOR r1` is the secret mask. Each query is
|
||||
/// returned already combined into the interval share.
|
||||
template <typename InputT, typename Iter, typename RootSampler, typename PadRng,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
geneval_cmp_result geneval_ic(InputT r0, InputT r1, Iter begin, Iter end,
|
||||
ds_randomness<RootSampler, PadRng> rng, const ic_pack<Beta> & spec)
|
||||
{
|
||||
static_assert(!is_wildcard_v<Beta>,
|
||||
"geneval_ic: payload must be concrete (assign_cmp is a separate step)");
|
||||
geneval_cmp_result out;
|
||||
if (begin == end)
|
||||
return out;
|
||||
|
||||
auto keys = make_dpf_doerner_shelat(std::move(r0), std::move(r1),
|
||||
std::move(rng), spec);
|
||||
const auto & k0 = keys.first;
|
||||
const auto & k1 = keys.second;
|
||||
using key_type = unwrap_party_key_t<typename std::decay_t<decltype(k0)>::key_type>;
|
||||
constexpr std::size_t depth = key_type::depth;
|
||||
out.live_levels = depth;
|
||||
out.mask = k0.key.cmp().mask;
|
||||
out.cw_last = k0.key.cw_last();
|
||||
out.addend0 = k0.key.cmp_addend().raw();
|
||||
out.addend1 = k1.key.cmp_addend().raw();
|
||||
out.correction_words.resize(depth);
|
||||
out.correction_advice.resize(depth);
|
||||
out.value_cw.resize(depth);
|
||||
for (std::size_t level = 0; level < depth; ++level)
|
||||
{
|
||||
out.correction_words[level] = k0.key.correction_word(level);
|
||||
out.correction_advice[level] =
|
||||
static_cast<uint8_t>(k0.key.correction_advice(level));
|
||||
out.value_cw[level] = k0.key.value_cw(level);
|
||||
}
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
out.party0.push_back(detail::ic_impl::opened_u64(
|
||||
eval_point(ic, k0, *it), out.mask));
|
||||
out.party1.push_back(detail::ic_impl::opened_u64(
|
||||
eval_point(ic, k1, *it), out.mask));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Additive-share geneval_ic. `r0 + r1` is the secret mask.
|
||||
template <typename InputT, typename Iter, typename RootSampler, typename PadRng,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
geneval_cmp_result geneval_ic(arith_input_t, InputT r0, InputT r1, Iter begin,
|
||||
Iter end, ds_randomness<RootSampler, PadRng> rng, const ic_pack<Beta> & spec)
|
||||
{
|
||||
static_assert(!is_wildcard_v<Beta>,
|
||||
"geneval_ic: payload must be concrete (assign_cmp is a separate step)");
|
||||
geneval_cmp_result out;
|
||||
if (begin == end)
|
||||
return out;
|
||||
|
||||
auto keys = make_dpf_doerner_shelat(arith_input, std::move(r0), std::move(r1),
|
||||
std::move(rng), spec);
|
||||
const auto & k0 = keys.first;
|
||||
const auto & k1 = keys.second;
|
||||
using key_type = unwrap_party_key_t<typename std::decay_t<decltype(k0)>::key_type>;
|
||||
constexpr std::size_t depth = key_type::depth;
|
||||
out.live_levels = depth;
|
||||
out.mask = k0.key.cmp().mask;
|
||||
out.cw_last = k0.key.cw_last();
|
||||
out.addend0 = k0.key.cmp_addend().raw();
|
||||
out.addend1 = k1.key.cmp_addend().raw();
|
||||
out.correction_words.resize(depth);
|
||||
out.correction_advice.resize(depth);
|
||||
out.value_cw.resize(depth);
|
||||
for (std::size_t level = 0; level < depth; ++level)
|
||||
{
|
||||
out.correction_words[level] = k0.key.correction_word(level);
|
||||
out.correction_advice[level] =
|
||||
static_cast<uint8_t>(k0.key.correction_advice(level));
|
||||
out.value_cw[level] = k0.key.value_cw(level);
|
||||
}
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
out.party0.push_back(detail::ic_impl::opened_u64(
|
||||
eval_point(ic, k0, *it), out.mask));
|
||||
out.party1.push_back(detail::ic_impl::opened_u64(
|
||||
eval_point(ic, k1, *it), out.mask));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_INTERVAL_HPP__
|
||||
|
|
@ -1,6 +1,13 @@
|
|||
/// @file dpf/interval_memoizer.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Workspaces for an inclusive interval of DPF leaves.
|
||||
/// @details `basic_interval_memoizer` keeps two levels of the interval.
|
||||
/// `full_tree_interval_memoizer` keeps every level. Size either one
|
||||
/// for the widest interval you will evaluate; a wider interval
|
||||
/// throws `std::length_error`. The same key and the same endpoints
|
||||
/// leave the final interior level in place.
|
||||
///
|
||||
/// Factories unwrap `party_key`. Pass the memoizer as a mutable
|
||||
/// lvalue to `eval_interval` or `eval_full`.
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -55,10 +62,13 @@ struct interval_memoizer_base
|
|||
|
||||
// level 0 should access the root
|
||||
// level goes up to (and including) depth
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type operator[](std::size_t) const noexcept = 0;
|
||||
|
||||
// iterators should access most recently completed level
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type begin() const noexcept = 0;
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type end() const noexcept = 0;
|
||||
|
||||
virtual std::size_t assign_interval(const dpf_type & dpf, integral_type new_from, integral_type new_to)
|
||||
|
|
@ -151,6 +161,8 @@ struct interval_memoizer_base
|
|||
std::optional<integral_type> to_;
|
||||
};
|
||||
|
||||
/// Two-level workspace for one interval. This is what
|
||||
/// `eval_interval(key, from, to)` allocates when you omit the memoizer.
|
||||
template <typename DpfKey,
|
||||
typename Allocator = aligned_allocator<
|
||||
typename interval_memoizer_key_t<DpfKey>::interior_node>>
|
||||
|
|
@ -229,6 +241,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
unique_ptr buf;
|
||||
};
|
||||
|
||||
/// Every level of the interval. `retains_all_levels` is true.
|
||||
template <typename DpfKey,
|
||||
typename Allocator = aligned_allocator<
|
||||
typename interval_memoizer_key_t<DpfKey>::interior_node>>
|
||||
|
|
@ -392,6 +405,7 @@ struct basic_interval_memoizer_at
|
|||
- utils::shift_right(from_node, offset) + 1;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
return_type operator[](std::size_t level) const noexcept
|
||||
{
|
||||
bool b = (depth ^ level) & 1;
|
||||
|
|
@ -420,9 +434,6 @@ auto make_interval_memoizer(InputT from, InputT to)
|
|||
{
|
||||
using dpf_type = DpfKey;
|
||||
|
||||
utils::flip_msb_if_signed_integral(from);
|
||||
utils::flip_msb_if_signed_integral(to);
|
||||
|
||||
std::size_t nodes_in_interval = utils::get_leafnodes_in_output_interval<dpf_type>(from, to);
|
||||
|
||||
return MemoizerT(nodes_in_interval);
|
||||
|
|
@ -430,6 +441,10 @@ auto make_interval_memoizer(InputT from, InputT to)
|
|||
|
||||
} // namespace detail
|
||||
|
||||
/// Two-level workspace sized for the closed interval `[from, to]`.
|
||||
/// @param from Inclusive start, in the key's input domain.
|
||||
/// @param to Inclusive end. `to` is at least `from` in that domain.
|
||||
/// @snippet evaluation/memoizers.cpp interval-memoizer
|
||||
template <typename DpfKey,
|
||||
typename InputT>
|
||||
inline auto make_basic_interval_memoizer(InputT from, InputT to)
|
||||
|
|
@ -448,6 +463,7 @@ inline auto make_basic_interval_memoizer(const DpfKey &, InputT from, InputT to)
|
|||
return make_basic_interval_memoizer<DpfKey>(from, to);
|
||||
}
|
||||
|
||||
/// `make_basic_interval_memoizer` sized for the whole input domain.
|
||||
template <typename DpfKey>
|
||||
inline auto make_basic_full_memoizer()
|
||||
{
|
||||
|
|
@ -464,6 +480,7 @@ inline auto make_basic_full_memoizer(const DpfKey &)
|
|||
return make_basic_full_memoizer<DpfKey>();
|
||||
}
|
||||
|
||||
/// Full-tree workspace sized for the closed interval `[from, to]`.
|
||||
template <typename DpfKey,
|
||||
typename InputT>
|
||||
inline auto make_full_tree_interval_memoizer(InputT from, InputT to)
|
||||
|
|
@ -482,6 +499,7 @@ inline auto make_full_tree_interval_memoizer(const DpfKey &, InputT from, InputT
|
|||
return make_full_tree_interval_memoizer<DpfKey>(from, to);
|
||||
}
|
||||
|
||||
/// `make_full_tree_interval_memoizer` sized for the whole input domain.
|
||||
template <typename DpfKey>
|
||||
inline auto make_full_tree_full_memoizer()
|
||||
{
|
||||
|
|
@ -521,11 +539,13 @@ inline auto make_basic_interval_memoizer(InputT from, InputT to)
|
|||
utils::flip_msb_if_signed_integral(from);
|
||||
utils::flip_msb_if_signed_integral(to);
|
||||
|
||||
const integral_type from_node = utils::leaf_node_floor(
|
||||
static_cast<integral_type>(to_int(from)), lg);
|
||||
const integral_type to_node = utils::leaf_node_ceil_exclusive(
|
||||
static_cast<integral_type>(to_int(to)), lg);
|
||||
const auto segs = utils::split_leaf_nodes(from_node, to_node, stop);
|
||||
const auto from_i = static_cast<integral_type>(to_int(from));
|
||||
const auto to_i = static_cast<integral_type>(to_int(to));
|
||||
const integral_type from_node = utils::leaf_node_floor(from_i, lg);
|
||||
const integral_type to_node = utils::leaf_node_ceil_exclusive(to_i, lg);
|
||||
const bool wraps = utils::interval_wraps(from_i, to_i,
|
||||
utils::bitlength_of_v<InputT>);
|
||||
const auto segs = utils::split_leaf_nodes(from_node, to_node, stop, wraps);
|
||||
return basic_interval_memoizer_at<DpfKey, stop>(segs.total);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/// @file dpf/json.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief nlohmann::json serializers for DPF keys and beaver triples.
|
||||
/// @details ADL `adl_serializer` specializations so `nlohmann::json` can
|
||||
/// convert the library's key and triple types.
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
/// @license Released under a GNU General Public v2.0 (GPLv2) license;
|
||||
|
|
@ -92,6 +93,9 @@ struct adl_serializer<dpf::detail::cmp_meta>
|
|||
j.at("eval_as_ge").get_to(c.eval_as_ge);
|
||||
j.at("include_eq").get_to(c.include_eq);
|
||||
j.at("active").get_to(c.active);
|
||||
c.incremental = j.value("incremental", false);
|
||||
c.block_width = j.value("block_width", 0);
|
||||
c.tail_bits = j.value("tail_bits", 0);
|
||||
}
|
||||
|
||||
static void to_json(nlohmann::json & j, const dpf::detail::cmp_meta & c) // NOLINT(runtime/references)
|
||||
|
|
@ -105,6 +109,13 @@ struct adl_serializer<dpf::detail::cmp_meta>
|
|||
{"include_eq", c.include_eq},
|
||||
{"active", c.active}
|
||||
};
|
||||
if (c.incremental)
|
||||
j["incremental"] = true;
|
||||
if (c.block_width != 0)
|
||||
{
|
||||
j["block_width"] = c.block_width;
|
||||
j["tail_bits"] = c.tail_bits;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -197,6 +208,12 @@ struct adl_serializer<dpf::dpf_key<InteriorPRG, ExteriorPRG, InputT, OutputT, Ou
|
|||
j.at("value_cw").get_to(value_cws);
|
||||
uint64_t cw_last = j.at("cw_last").template get<uint64_t>();
|
||||
uint64_t cmp_addend = j.at("cmp_addend").template get<uint64_t>();
|
||||
typename dpf_type::tail_array tail{};
|
||||
if constexpr (dpf_type::cmp_block > 0)
|
||||
j.at("tail_cw").get_to(tail);
|
||||
typename dpf_type::prefix_cw_array prefix{};
|
||||
if constexpr (dpf_type::cmp_idcf)
|
||||
j.at("prefix_cw").get_to(prefix);
|
||||
|
||||
typename dpf_type::leaf_wrapper_tuple leaves{};
|
||||
input_type offset_share{};
|
||||
|
|
@ -204,7 +221,7 @@ struct adl_serializer<dpf::dpf_key<InteriorPRG, ExteriorPRG, InputT, OutputT, Ou
|
|||
|
||||
return dpf_type{root, correction_words, correction_advice,
|
||||
std::move(leaves), offset_share, cmp, value_cws, cw_last,
|
||||
cmp_addend, addends};
|
||||
cmp_addend, addends, {}, 0, tail, {}, prefix};
|
||||
}
|
||||
|
||||
static void to_json(nlohmann::json & j, const dpf_type & dpf) // NOLINT(runtime/references)
|
||||
|
|
@ -221,6 +238,10 @@ struct adl_serializer<dpf::dpf_key<InteriorPRG, ExteriorPRG, InputT, OutputT, Ou
|
|||
{"cw_last", static_cast<uint64_t>(dpf.cw_last())},
|
||||
{"cmp_addend", static_cast<uint64_t>(dpf.cmp_addend())}
|
||||
};
|
||||
if constexpr (dpf_type::cmp_block > 0)
|
||||
j["tail_cw"] = dpf.tail_cw();
|
||||
if constexpr (dpf_type::cmp_idcf)
|
||||
j["prefix_cw"] = dpf.prefix_cws();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -174,11 +174,13 @@ class basic_fixed_length_string : public dpf::modint<static_cast<std::size_t>(st
|
|||
/// @brief default constructor
|
||||
/// @details Constructs the `basic_fixed_length_string` with a value
|
||||
/// corresponding to the empty string.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr basic_fixed_length_string() noexcept = default;
|
||||
|
||||
/// @brief copy constructor
|
||||
/// @details Constructs the `basic_fixed_length_string` with a value
|
||||
/// copied from another `basic_fixed_length_string`.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr
|
||||
basic_fixed_length_string(const basic_fixed_length_string &)
|
||||
noexcept = default;
|
||||
|
|
@ -186,6 +188,7 @@ class basic_fixed_length_string : public dpf::modint<static_cast<std::size_t>(st
|
|||
/// @brief move constructor
|
||||
/// @details Constructs the `basic_fixed_length_string` from another
|
||||
/// `basic_fixed_length_string` using move semantics.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr
|
||||
basic_fixed_length_string(basic_fixed_length_string &&)
|
||||
noexcept = default;
|
||||
|
|
@ -232,6 +235,7 @@ class basic_fixed_length_string : public dpf::modint<static_cast<std::size_t>(st
|
|||
/// @brief move assignment
|
||||
/// @details Assigns the `basic_fixed_length_string` from another
|
||||
/// `basic_fixed_length_string` using move semantics.
|
||||
HEDLEY_NO_THROW
|
||||
constexpr basic_fixed_length_string &
|
||||
operator=(basic_fixed_length_string &&) noexcept = default;
|
||||
|
||||
|
|
@ -268,10 +272,12 @@ class basic_fixed_length_string : public dpf::modint<static_cast<std::size_t>(st
|
|||
private:
|
||||
constexpr
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
HEDLEY_NO_THROW
|
||||
basic_fixed_length_string(integral_type val) // NOLINT(runtime/explicit)
|
||||
noexcept
|
||||
: parent::modint(val) { }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
constexpr basic_fixed_length_string(parent val) noexcept
|
||||
: parent::modint(val) { }
|
||||
|
||||
|
|
@ -448,6 +454,7 @@ struct make_from_integral_value<dpf::basic_fixed_length_string<MaxLen, CharT, Al
|
|||
{
|
||||
using T = dpf::basic_fixed_length_string<MaxLen, CharT, Alpha, Traits, Alloc>;
|
||||
using integral_type = integral_type_from_bitlength_t<bitlength_of_v<T>>;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr T operator()(integral_type val) const noexcept
|
||||
{
|
||||
return T{val};
|
||||
|
|
@ -499,14 +506,23 @@ class numeric_limits<dpf::basic_fixed_length_string<MaxLen, CharT, Alpha, Traits
|
|||
= std::numeric_limits<typename keyword_type::integral_type>::traps;
|
||||
static constexpr bool tinyness_before = false;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type min() noexcept { return keyword_type{""}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type lowest() noexcept { return keyword_type{""}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type max() noexcept { return ~keyword_type{""}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type epsilon() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type round_error() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type infinity() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type quiet_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type signaling_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr keyword_type denorm_min() noexcept { return 0; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@
|
|||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
|
||||
#include "dpf/modint.hpp"
|
||||
#include "dpf/utils.hpp"
|
||||
|
||||
|
|
@ -1492,6 +1494,7 @@ constexpr hit match_full(const program & p, const char * s, std::size_t n)
|
|||
return run_id(c, root, 0, u256{}, nullptr, 0, 0);
|
||||
}
|
||||
|
||||
HEDLEY_NON_NULL(4)
|
||||
constexpr int unrank_node(const program & p, std::uint16_t id, u256 rank, char * out, int n);
|
||||
|
||||
constexpr int unrank_node(const program & p, std::uint16_t id, u256 rank, char * out, int n)
|
||||
|
|
@ -1590,12 +1593,14 @@ constexpr int unrank_node(const program & p, std::uint16_t id, u256 rank, char *
|
|||
return n;
|
||||
}
|
||||
|
||||
HEDLEY_NON_NULL(3)
|
||||
constexpr int unrank_root(const program & p, u256 rank, char * out)
|
||||
{
|
||||
if (!p.lang.all && cmp_card_u(rank, p.lang) >= 0) return -1;
|
||||
return unrank_node(p, p.tree.root, rank, out, 0);
|
||||
}
|
||||
|
||||
HEDLEY_NON_NULL(1)
|
||||
constexpr program compile_pattern(const char * pattern)
|
||||
{
|
||||
program p{};
|
||||
|
|
@ -1719,6 +1724,7 @@ class keyword2
|
|||
constexpr keyword2(std::string_view str)
|
||||
: parent(encode_(str)) { }
|
||||
|
||||
HEDLEY_NON_NULL(1)
|
||||
constexpr keyword2(const char * str)
|
||||
: keyword2(std::string_view(str)) { }
|
||||
|
||||
|
|
@ -1731,7 +1737,7 @@ class keyword2
|
|||
constexpr keyword2 & operator=(const keyword2 &) noexcept = default;
|
||||
constexpr keyword2 & operator=(keyword2 &&) noexcept = default;
|
||||
|
||||
~keyword2() = default;
|
||||
~keyword2() noexcept = default;
|
||||
|
||||
/// @brief Rank, including values outside the language that fill the bit width.
|
||||
static constexpr keyword2 from_rank(integral_type rank) noexcept
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ static constexpr std::size_t block_length_of_leaf_v
|
|||
template <typename OutputT,
|
||||
typename NodeT,
|
||||
typename InputT>
|
||||
HEDLEY_NO_THROW
|
||||
constexpr std::size_t offset_within_block(InputT x) noexcept
|
||||
{
|
||||
constexpr auto mod = utils::mod_pow_2<InputT>{};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/// @file dpf/literals.hpp
|
||||
/// @brief Re-exports the user-defined literal namespaces.
|
||||
/// @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_LITERALS_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_LITERALS_HPP__
|
||||
|
||||
|
|
|
|||
|
|
@ -57,18 +57,21 @@ class modint
|
|||
|
||||
/// @brief default constructor
|
||||
/// @details Constructs a `modint` whose value is initialized to `0`.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint() noexcept = default;
|
||||
|
||||
/// @brief copy constructor
|
||||
/// @details Constructs the `modint` with a value copied from another
|
||||
/// `modint`.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint(const modint &) noexcept = default;
|
||||
|
||||
/// @brief move constructor
|
||||
/// @details Constructs the `modint` from another `modint` using move
|
||||
/// semantics.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint(modint &&) noexcept = default;
|
||||
|
||||
|
|
@ -91,12 +94,14 @@ class modint
|
|||
/// @brief copy assignment
|
||||
/// @details Assigns the `modint` with a value copied from another
|
||||
/// `modint`.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint & operator=(const modint &) noexcept = default;
|
||||
|
||||
/// @brief move assignment
|
||||
/// @details Assigns the `modint` from another `modint` using move
|
||||
/// semantics.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint & operator=(modint &&) noexcept = default;
|
||||
|
||||
|
|
@ -278,7 +283,11 @@ class modint
|
|||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint operator<<(std::size_t shift_amount) const noexcept
|
||||
{
|
||||
return modint{static_cast<integral_type>(this->val << shift_amount)};
|
||||
if (shift_amount >= Nbits)
|
||||
return modint{integral_type{0}};
|
||||
// Reduce first: an unreduced limb shifted by less than Nbits can
|
||||
// still leave the modulus, and a shift of the limb width is UB.
|
||||
return modint{static_cast<integral_type>(this->reduced_value() << shift_amount)};
|
||||
}
|
||||
|
||||
/// @brief bitwise-left-shift-assignment operator
|
||||
|
|
@ -290,7 +299,10 @@ class modint
|
|||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint & operator<<=(std::size_t shift_amount) noexcept
|
||||
{
|
||||
this->val <<= shift_amount;
|
||||
if (shift_amount >= Nbits)
|
||||
this->val = integral_type{0};
|
||||
else
|
||||
this->val = static_cast<integral_type>(this->reduced_value() << shift_amount);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -304,6 +316,8 @@ class modint
|
|||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint operator>>(std::size_t shift_amount) const noexcept
|
||||
{
|
||||
if (shift_amount >= Nbits)
|
||||
return modint{integral_type{0}};
|
||||
return modint{static_cast<integral_type>(this->reduced_value() >> shift_amount)};
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +330,10 @@ class modint
|
|||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr modint & operator>>=(std::size_t shift_amount) noexcept
|
||||
{
|
||||
this->val = this->reduced_value() >> shift_amount;
|
||||
if (shift_amount >= Nbits)
|
||||
this->val = integral_type{0};
|
||||
else
|
||||
this->val = this->reduced_value() >> shift_amount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -603,6 +620,7 @@ class modint
|
|||
template <std::size_t Nbits>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr modint<Nbits> operator*(typename modint<Nbits>::integral_type lhs,
|
||||
modint<Nbits> rhs) noexcept
|
||||
{
|
||||
|
|
@ -616,6 +634,7 @@ constexpr modint<Nbits> operator*(typename modint<Nbits>::integral_type lhs,
|
|||
template <std::size_t Nbits>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator<(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
||||
{
|
||||
return static_cast<typename modint<Nbits>::integral_type>(lhs)
|
||||
|
|
@ -626,6 +645,7 @@ constexpr bool operator<(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
|||
template <std::size_t Nbits>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator<=(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
||||
{
|
||||
return static_cast<typename modint<Nbits>::integral_type>(lhs)
|
||||
|
|
@ -636,6 +656,7 @@ constexpr bool operator<=(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
|||
template <std::size_t Nbits>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator>(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
||||
{
|
||||
return static_cast<typename modint<Nbits>::integral_type>(lhs)
|
||||
|
|
@ -646,6 +667,7 @@ constexpr bool operator>(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
|||
template <std::size_t Nbits>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator>=(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
||||
{
|
||||
return static_cast<typename modint<Nbits>::integral_type>(lhs)
|
||||
|
|
@ -656,6 +678,7 @@ constexpr bool operator>=(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
|||
template <std::size_t Nbits>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator==(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
||||
{
|
||||
return static_cast<typename modint<Nbits>::integral_type>(lhs)
|
||||
|
|
@ -666,6 +689,7 @@ constexpr bool operator==(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
|||
template <std::size_t Nbits>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator!=(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
|
||||
{
|
||||
return static_cast<typename modint<Nbits>::integral_type>(lhs)
|
||||
|
|
@ -695,6 +719,7 @@ template <std::size_t Nbits>
|
|||
struct countl_zero_symmetric_difference<dpf::modint<Nbits>>
|
||||
{
|
||||
using T = dpf::modint<Nbits>;
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(T lhs, T rhs) const noexcept
|
||||
|
|
@ -731,6 +756,7 @@ struct mod_pow_2<dpf::modint<Nbits>>
|
|||
{
|
||||
using T = dpf::modint<Nbits>;
|
||||
static constexpr auto mod = mod_pow_2<typename T::integral_type>{};
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t operator()(T val, std::size_t n) const noexcept
|
||||
{
|
||||
return mod(val.val, n);
|
||||
|
|
@ -1106,218 +1132,218 @@ constexpr static auto operator "" _u61(unsigned long long int x) { return dpf::m
|
|||
constexpr static auto operator "" _u62(unsigned long long int x) { return dpf::modints::modint62_t{static_cast<psnip_uint64_t>(x)}; }
|
||||
constexpr static auto operator "" _u63(unsigned long long int x) { return dpf::modints::modint63_t{static_cast<psnip_uint64_t>(x)}; }
|
||||
constexpr static auto operator "" _u64(unsigned long long int x) { return dpf::modints::modint64_t{static_cast<psnip_uint64_t>(x)}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u65() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint65_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u66() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint66_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u67() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint67_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u68() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint68_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u69() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint69_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u65() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint65_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u66() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint66_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u67() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint67_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u68() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint68_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u69() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint69_t{x}; }
|
||||
// 70--79
|
||||
template <char ...digits> constexpr static auto operator "" _u70() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint70_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u71() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint71_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u72() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint72_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u73() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint73_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u74() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint74_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u75() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint75_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u76() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint76_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u77() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint77_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u78() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint78_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u79() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint79_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u70() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint70_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u71() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint71_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u72() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint72_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u73() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint73_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u74() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint74_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u75() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint75_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u76() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint76_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u77() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint77_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u78() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint78_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u79() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint79_t{x}; }
|
||||
// 80--89
|
||||
template <char ...digits> constexpr static auto operator "" _u80() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint80_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u81() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint81_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u82() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint82_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u83() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint83_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u84() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint84_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u85() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint85_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u86() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint86_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u87() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint87_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u88() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint88_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u89() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint89_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u80() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint80_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u81() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint81_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u82() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint82_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u83() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint83_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u84() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint84_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u85() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint85_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u86() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint86_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u87() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint87_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u88() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint88_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u89() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint89_t{x}; }
|
||||
// 90--99
|
||||
template <char ...digits> constexpr static auto operator "" _u90() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint90_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u91() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint91_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u92() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint92_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u93() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint93_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u94() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint94_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u95() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint95_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u96() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint96_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u97() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint97_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u98() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint98_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u99() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint99_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u90() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint90_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u91() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint91_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u92() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint92_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u93() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint93_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u94() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint94_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u95() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint95_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u96() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint96_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u97() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint97_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u98() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint98_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u99() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint99_t{x}; }
|
||||
// 100--109
|
||||
template <char ...digits> constexpr static auto operator "" _u100() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint100_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u101() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint101_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u102() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint102_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u103() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint103_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u104() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint104_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u105() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint105_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u106() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint106_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u107() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint107_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u108() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint108_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u109() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint109_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u100() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint100_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u101() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint101_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u102() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint102_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u103() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint103_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u104() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint104_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u105() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint105_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u106() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint106_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u107() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint107_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u108() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint108_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u109() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint109_t{x}; }
|
||||
// 110--119
|
||||
template <char ...digits> constexpr static auto operator "" _u110() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint110_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u111() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint111_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u112() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint112_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u113() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint113_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u114() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint114_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u115() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint115_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u116() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint116_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u117() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint117_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u118() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint118_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u119() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint119_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u110() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint110_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u111() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint111_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u112() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint112_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u113() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint113_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u114() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint114_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u115() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint115_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u116() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint116_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u117() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint117_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u118() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint118_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u119() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint119_t{x}; }
|
||||
// 120--128
|
||||
template <char ...digits> constexpr static auto operator "" _u120() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint120_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u121() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint121_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u122() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint122_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u123() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint123_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u124() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint124_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u125() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint125_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u126() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint126_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u127() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint127_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u128() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint128_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u129() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint129_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u120() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint120_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u121() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint121_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u122() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint122_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u123() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint123_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u124() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint124_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u125() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint125_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u126() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint126_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u127() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint127_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u128() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint128_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u129() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint129_t{x}; }
|
||||
|
||||
// 120--139
|
||||
template <char ...digits> constexpr static auto operator "" _u130() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint130_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u131() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint131_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u132() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint132_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u133() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint133_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u134() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint134_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u135() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint135_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u136() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint136_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u137() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint137_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u138() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint138_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u139() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint139_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u130() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint130_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u131() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint131_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u132() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint132_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u133() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint133_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u134() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint134_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u135() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint135_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u136() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint136_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u137() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint137_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u138() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint138_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u139() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint139_t{x}; }
|
||||
// 140--149
|
||||
template <char ...digits> constexpr static auto operator "" _u140() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint140_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u141() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint141_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u142() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint142_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u143() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint143_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u144() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint144_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u145() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint145_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u146() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint146_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u147() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint147_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u148() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint148_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u149() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint149_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u140() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint140_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u141() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint141_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u142() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint142_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u143() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint143_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u144() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint144_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u145() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint145_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u146() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint146_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u147() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint147_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u148() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint148_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u149() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint149_t{x}; }
|
||||
// 150--159
|
||||
template <char ...digits> constexpr static auto operator "" _u150() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint150_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u151() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint151_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u152() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint152_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u153() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint153_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u154() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint154_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u155() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint155_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u156() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint156_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u157() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint157_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u158() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint158_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u159() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint159_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u150() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint150_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u151() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint151_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u152() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint152_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u153() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint153_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u154() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint154_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u155() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint155_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u156() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint156_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u157() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint157_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u158() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint158_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u159() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint159_t{x}; }
|
||||
// 160--169
|
||||
template <char ...digits> constexpr static auto operator "" _u160() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint160_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u161() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint161_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u162() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint162_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u163() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint163_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u164() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint164_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u165() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint165_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u166() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint166_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u167() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint167_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u168() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint168_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u169() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint169_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u160() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint160_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u161() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint161_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u162() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint162_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u163() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint163_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u164() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint164_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u165() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint165_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u166() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint166_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u167() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint167_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u168() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint168_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u169() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint169_t{x}; }
|
||||
// 170-179
|
||||
template <char ...digits> constexpr static auto operator "" _u170() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint170_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u171() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint171_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u172() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint172_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u173() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint173_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u174() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint174_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u175() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint175_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u176() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint176_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u177() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint177_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u178() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint178_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u179() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint179_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u170() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint170_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u171() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint171_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u172() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint172_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u173() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint173_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u174() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint174_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u175() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint175_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u176() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint176_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u177() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint177_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u178() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint178_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u179() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint179_t{x}; }
|
||||
// 180--189
|
||||
template <char ...digits> constexpr static auto operator "" _u180() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint180_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u181() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint181_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u182() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint182_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u183() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint183_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u184() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint184_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u185() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint185_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u186() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint186_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u187() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint187_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u188() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint188_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u189() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint189_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u180() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint180_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u181() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint181_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u182() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint182_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u183() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint183_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u184() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint184_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u185() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint185_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u186() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint186_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u187() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint187_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u188() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint188_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u189() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint189_t{x}; }
|
||||
// 190--199
|
||||
template <char ...digits> constexpr static auto operator "" _u190() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint190_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u191() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint191_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u192() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint192_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u193() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint193_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u194() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint194_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u195() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint195_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u196() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint196_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u197() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint197_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u198() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint198_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u199() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint199_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u190() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint190_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u191() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint191_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u192() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint192_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u193() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint193_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u194() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint194_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u195() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint195_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u196() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint196_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u197() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint197_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u198() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint198_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u199() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint199_t{x}; }
|
||||
// 200--209
|
||||
template <char ...digits> constexpr static auto operator "" _u200() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint200_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u201() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint201_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u202() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint202_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u203() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint203_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u204() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint204_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u205() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint205_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u206() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint206_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u207() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint207_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u208() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint208_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u209() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint209_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u200() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint200_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u201() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint201_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u202() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint202_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u203() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint203_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u204() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint204_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u205() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint205_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u206() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint206_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u207() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint207_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u208() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint208_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u209() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint209_t{x}; }
|
||||
// 210--219
|
||||
template <char ...digits> constexpr static auto operator "" _u210() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint210_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u211() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint211_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u212() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint212_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u213() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint213_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u214() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint214_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u215() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint215_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u216() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint216_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u217() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint217_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u218() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint218_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u219() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint219_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u210() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint210_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u211() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint211_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u212() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint212_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u213() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint213_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u214() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint214_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u215() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint215_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u216() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint216_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u217() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint217_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u218() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint218_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u219() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint219_t{x}; }
|
||||
// 220--229
|
||||
template <char ...digits> constexpr static auto operator "" _u220() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint220_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u221() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint221_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u222() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint222_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u223() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint223_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u224() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint224_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u225() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint225_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u226() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint226_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u227() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint227_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u228() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint228_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u229() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint229_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u220() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint220_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u221() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint221_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u222() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint222_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u223() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint223_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u224() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint224_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u225() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint225_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u226() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint226_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u227() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint227_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u228() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint228_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u229() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint229_t{x}; }
|
||||
// 230--239
|
||||
template <char ...digits> constexpr static auto operator "" _u230() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint230_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u231() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint231_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u232() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint232_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u233() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint233_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u234() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint234_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u235() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint235_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u236() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint236_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u237() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint237_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u238() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint238_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u239() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint239_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u230() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint230_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u231() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint231_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u232() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint232_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u233() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint233_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u234() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint234_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u235() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint235_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u236() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint236_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u237() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint237_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u238() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint238_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u239() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint239_t{x}; }
|
||||
// 240--249
|
||||
template <char ...digits> constexpr static auto operator "" _u240() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint240_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u241() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint241_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u242() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint242_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u243() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint243_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u244() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint244_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u245() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint245_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u246() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint246_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u247() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint247_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u248() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint248_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u249() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint249_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u240() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint240_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u241() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint241_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u242() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint242_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u243() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint243_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u244() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint244_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u245() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint245_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u246() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint246_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u247() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint247_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u248() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint248_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u249() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint249_t{x}; }
|
||||
// 250--256
|
||||
template <char ...digits> constexpr static auto operator "" _u250() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint250_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u251() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint251_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u252() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint252_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u253() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint253_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u254() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint254_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u255() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint255_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u256() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::modints::modint256_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u250() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint250_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u251() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint251_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u252() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint252_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u253() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint253_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u254() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint254_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u255() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint255_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _u256() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::modints::modint256_t{x}; }
|
||||
|
||||
} // namespace modints
|
||||
|
||||
|
|
@ -1362,14 +1388,23 @@ class numeric_limits<dpf::modint<Nbits>>
|
|||
= std::numeric_limits<typename dpf::modint<Nbits>::integral_type>::traps;
|
||||
static constexpr bool tinyness_before = false;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> min() noexcept { return dpf::modint<Nbits>{0}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> lowest() noexcept { return dpf::modint<Nbits>{0}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> max() noexcept { return ~dpf::modint<Nbits>{0}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> epsilon() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> round_error() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> infinity() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> quiet_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> signaling_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::modint<Nbits> denorm_min() noexcept { return 0; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ template <>
|
|||
struct make_from_integral_value<dpf::nyble>
|
||||
{
|
||||
using integral_type = std::uint8_t;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr dpf::nyble operator()(integral_type val) const noexcept
|
||||
{
|
||||
return dpf::to_nyble(val);
|
||||
|
|
@ -189,8 +190,11 @@ class numeric_limits<dpf::nyble> : public numeric_limits<std::uint8_t>
|
|||
public:
|
||||
static constexpr int digits = 4;
|
||||
static constexpr int digits10 = 1;
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::nyble min() noexcept { return dpf::nyble::zero; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::nyble max() noexcept { return dpf::nyble{15}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::nyble lowest() noexcept { return min(); }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
/// @file dpf/output_buffer.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Move-only storage for shares written by multi-point evaluation.
|
||||
/// @details Slot type follows the key. A `party_key` leaf buffer holds
|
||||
/// `subtractive_share`s; a comparison buffer holds
|
||||
/// `additive_share`s. `bit`, `twobit`, and `nyble` slots are packed.
|
||||
/// Trivially default-constructible slots are left uninitialized
|
||||
/// because evaluation overwrites every slot it is responsible for.
|
||||
///
|
||||
/// `eval_interval` and recipe `eval_sequence` take the buffer by
|
||||
/// non-const reference. The returned iterable refers into it.
|
||||
/// @snippet evaluation/output_buffers.cpp output-buffer
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
/// @license Released under a GNU General Public v2.0 (GPLv2) license;
|
||||
|
|
@ -9,6 +17,8 @@
|
|||
#ifndef LIBDPF_INCLUDE_DPF_OUTPUT_BUFFER_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_OUTPUT_BUFFER_HPP__
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
|
@ -77,9 +87,12 @@ class output_buffer_allocator : public aligned_allocator<T, Alignment>
|
|||
using other = output_buffer_allocator<U, Alignment>;
|
||||
};
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer_allocator() noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer_allocator(const output_buffer_allocator &) noexcept = default;
|
||||
template <typename U>
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer_allocator(const output_buffer_allocator<U, Alignment> &) noexcept {}
|
||||
|
||||
template <typename U>
|
||||
|
|
@ -100,6 +113,7 @@ class output_buffer_allocator : public aligned_allocator<T, Alignment>
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
HEDLEY_NO_THROW
|
||||
void destroy(U * p) noexcept
|
||||
{
|
||||
if constexpr (!std::is_trivially_destructible_v<U>)
|
||||
|
|
@ -110,6 +124,7 @@ class output_buffer_allocator : public aligned_allocator<T, Alignment>
|
|||
};
|
||||
|
||||
template <typename T, std::size_t A, typename U, std::size_t B>
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator==(const output_buffer_allocator<T, A> &,
|
||||
const output_buffer_allocator<U, B> &) noexcept
|
||||
{
|
||||
|
|
@ -117,12 +132,15 @@ constexpr bool operator==(const output_buffer_allocator<T, A> &,
|
|||
}
|
||||
|
||||
template <typename T, std::size_t A, typename U, std::size_t B>
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator!=(const output_buffer_allocator<T, A> & lhs,
|
||||
const output_buffer_allocator<U, B> & rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// Move-only vector of `T`. Copy construction and copy assignment are
|
||||
/// deleted. `at`, `operator[]`, `data`, iterators, and `size` are public.
|
||||
template <typename T,
|
||||
std::size_t Alignment = utils::max_align_v>
|
||||
class output_buffer final
|
||||
|
|
@ -135,13 +153,17 @@ class output_buffer final
|
|||
using iterator = typename vector::iterator;
|
||||
using const_iterator = typename vector::const_iterator;
|
||||
using size_type = typename vector::size_type;
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer() noexcept = default;
|
||||
explicit output_buffer(size_type size) : vector(size) { }
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer(output_buffer &&) noexcept = default;
|
||||
output_buffer(const output_buffer &) = delete;
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer & operator=(output_buffer &&) noexcept = default;
|
||||
output_buffer & operator=(const output_buffer &) = delete;
|
||||
~output_buffer() = default;
|
||||
HEDLEY_NO_THROW
|
||||
~output_buffer() noexcept = default;
|
||||
|
||||
// "selectively public" inheritance
|
||||
using vector::at;
|
||||
|
|
@ -161,11 +183,14 @@ class output_buffer<dpf::bit> : public dpf::dynamic_bit_array<>
|
|||
using size_type = typename dpf::dynamic_bit_array<>::size_type;
|
||||
public:
|
||||
explicit output_buffer(size_type size) : dynamic_bit_array(size) { }
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer(output_buffer &&) noexcept = default;
|
||||
output_buffer(const output_buffer &) = delete;
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer & operator=(output_buffer &&) noexcept = default;
|
||||
output_buffer & operator=(const output_buffer &) = delete;
|
||||
~output_buffer() = default;
|
||||
HEDLEY_NO_THROW
|
||||
~output_buffer() noexcept = default;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
|
@ -175,11 +200,14 @@ class output_buffer<dpf::twobit> : public dpf::dynamic_packed_array<dpf::twobit>
|
|||
public:
|
||||
using size_type = typename base::size_type;
|
||||
explicit output_buffer(size_type size) : base(size) { }
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer(output_buffer &&) noexcept = default;
|
||||
output_buffer(const output_buffer &) = delete;
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer & operator=(output_buffer &&) noexcept = default;
|
||||
output_buffer & operator=(const output_buffer &) = delete;
|
||||
~output_buffer() = default;
|
||||
HEDLEY_NO_THROW
|
||||
~output_buffer() noexcept = default;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
|
@ -189,11 +217,14 @@ class output_buffer<dpf::nyble> : public dpf::dynamic_packed_array<dpf::nyble>
|
|||
public:
|
||||
using size_type = typename base::size_type;
|
||||
explicit output_buffer(size_type size) : base(size) { }
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer(output_buffer &&) noexcept = default;
|
||||
output_buffer(const output_buffer &) = delete;
|
||||
HEDLEY_NO_THROW
|
||||
output_buffer & operator=(output_buffer &&) noexcept = default;
|
||||
output_buffer & operator=(const output_buffer &) = delete;
|
||||
~output_buffer() = default;
|
||||
HEDLEY_NO_THROW
|
||||
~output_buffer() noexcept = default;
|
||||
};
|
||||
|
||||
#define LIBDPF_PACKED_SHARE_BUFFER(LANE, PARTY) \
|
||||
|
|
@ -205,11 +236,14 @@ class output_buffer<subtractive_share<LANE, PARTY>>
|
|||
public: \
|
||||
using size_type = typename base::size_type; \
|
||||
explicit output_buffer(size_type size) : base(size) {} \
|
||||
HEDLEY_NO_THROW \
|
||||
output_buffer(output_buffer &&) noexcept = default; \
|
||||
output_buffer(const output_buffer &) = delete; \
|
||||
HEDLEY_NO_THROW \
|
||||
output_buffer & operator=(output_buffer &&) noexcept = default; \
|
||||
output_buffer & operator=(const output_buffer &) = delete; \
|
||||
~output_buffer() = default; \
|
||||
HEDLEY_NO_THROW \
|
||||
~output_buffer() noexcept = default; \
|
||||
};
|
||||
|
||||
LIBDPF_PACKED_SHARE_BUFFER(dpf::twobit, 0);
|
||||
|
|
@ -232,12 +266,14 @@ class output_buffer<subtractive_share<dpf::bit, PARTY>>
|
|||
output_buffer(const output_buffer &) = delete; \
|
||||
output_buffer & operator=(output_buffer &&) noexcept = default; \
|
||||
output_buffer & operator=(const output_buffer &) = delete; \
|
||||
~output_buffer() = default; \
|
||||
~output_buffer() noexcept = default; \
|
||||
};
|
||||
LIBDPF_BIT_SHARE_BUFFER(0);
|
||||
LIBDPF_BIT_SHARE_BUFFER(1);
|
||||
#undef LIBDPF_BIT_SHARE_BUFFER
|
||||
|
||||
/// Buffer sized for the closed interval `[from, to]` of output `I`.
|
||||
/// On a `party_key`, elements are subtractive shares of that output.
|
||||
template <typename DpfKey,
|
||||
std::size_t I = 0,
|
||||
typename InputT>
|
||||
|
|
@ -247,9 +283,6 @@ auto make_output_buffer_for_interval(InputT from, InputT to)
|
|||
using output_type = typename DpfKey::concrete_output_type<I>;
|
||||
using buffer_elem = leaf_buffer_elem_t<DpfKey, output_type>;
|
||||
|
||||
utils::flip_msb_if_signed_integral(from);
|
||||
utils::flip_msb_if_signed_integral(to);
|
||||
|
||||
std::size_t nodes_in_interval = utils::get_leafnodes_in_output_interval<dpf_type>(from, to);
|
||||
return dpf::output_buffer<buffer_elem>(nodes_in_interval*dpf_type::outputs_per_leaf);
|
||||
}
|
||||
|
|
@ -285,6 +318,7 @@ inline auto make_output_buffer_for_interval(const DpfKey &, InputT from, InputT
|
|||
return make_output_buffer_for_interval<DpfKey, I0, I1, Is...>(from, to);
|
||||
}
|
||||
|
||||
/// Buffer sized for every input of output `I`.
|
||||
template <typename DpfKey,
|
||||
std::size_t I = 0>
|
||||
auto make_output_buffer_for_full()
|
||||
|
|
|
|||
|
|
@ -50,15 +50,18 @@ class dynamic_packed_array
|
|||
class lane_ref
|
||||
{
|
||||
public:
|
||||
HEDLEY_NO_THROW
|
||||
lane_ref(word_type * word, unsigned shift) noexcept
|
||||
: word_{word}, shift_{shift} {}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
operator LaneT() const noexcept
|
||||
{
|
||||
return static_cast<LaneT>((*word_ >> shift_) & lane_mask);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
lane_ref & operator=(LaneT value) noexcept
|
||||
{
|
||||
|
|
@ -69,23 +72,28 @@ class dynamic_packed_array
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
lane_ref & operator=(const lane_ref & other) noexcept
|
||||
{
|
||||
return (*this = static_cast<LaneT>(other));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator==(lane_ref lhs, LaneT rhs) noexcept
|
||||
{
|
||||
return static_cast<LaneT>(lhs) == rhs;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator==(LaneT lhs, lane_ref rhs) noexcept
|
||||
{
|
||||
return rhs == lhs;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator!=(lane_ref lhs, LaneT rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator!=(LaneT lhs, lane_ref rhs) noexcept
|
||||
{
|
||||
return !(rhs == lhs);
|
||||
|
|
@ -108,25 +116,33 @@ class dynamic_packed_array
|
|||
using pointer = void;
|
||||
using reference = lane_ref;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
iterator() noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
iterator(word_type * data, size_type index) noexcept
|
||||
: data_{data}, index_{index} {}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
lane_ref operator*() const noexcept { return ref_at(index_); }
|
||||
HEDLEY_NO_THROW
|
||||
lane_ref operator[](difference_type n) const noexcept
|
||||
{
|
||||
return ref_at(static_cast<size_type>(
|
||||
static_cast<difference_type>(index_) + n));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator++() noexcept { ++index_; return *this; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator operator++(int) noexcept
|
||||
{
|
||||
iterator prev = *this;
|
||||
++*this;
|
||||
return prev;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator--() noexcept { --index_; return *this; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator operator--(int) noexcept
|
||||
{
|
||||
iterator prev = *this;
|
||||
|
|
@ -134,53 +150,66 @@ class dynamic_packed_array
|
|||
return prev;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator+=(difference_type n) noexcept
|
||||
{
|
||||
index_ = static_cast<size_type>(
|
||||
static_cast<difference_type>(index_) + n);
|
||||
return *this;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator-=(difference_type n) noexcept
|
||||
{
|
||||
return *this += -n;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend iterator operator+(iterator it, difference_type n) noexcept
|
||||
{
|
||||
it += n;
|
||||
return it;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend iterator operator+(difference_type n, iterator it) noexcept
|
||||
{
|
||||
return it + n;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend iterator operator-(iterator it, difference_type n) noexcept
|
||||
{
|
||||
it -= n;
|
||||
return it;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend difference_type operator-(iterator a, iterator b) noexcept
|
||||
{
|
||||
return static_cast<difference_type>(a.index_)
|
||||
- static_cast<difference_type>(b.index_);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator==(iterator a, iterator b) noexcept
|
||||
{
|
||||
return a.index_ == b.index_;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator!=(iterator a, iterator b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator<(iterator a, iterator b) noexcept
|
||||
{
|
||||
return a.index_ < b.index_;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator>(iterator a, iterator b) noexcept { return b < a; }
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator<=(iterator a, iterator b) noexcept { return !(b < a); }
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator>=(iterator a, iterator b) noexcept { return !(a < b); }
|
||||
|
||||
private:
|
||||
HEDLEY_NO_THROW
|
||||
lane_ref ref_at(size_type index) const noexcept
|
||||
{
|
||||
const size_type bit = index * lane_bits;
|
||||
|
|
@ -213,12 +242,14 @@ class dynamic_packed_array
|
|||
dynamic_packed_array(const dynamic_packed_array &) = delete;
|
||||
dynamic_packed_array & operator=(const dynamic_packed_array &) = delete;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
dynamic_packed_array(dynamic_packed_array && other) noexcept
|
||||
: nlanes_{std::exchange(other.nlanes_, 0)},
|
||||
nwords_{std::exchange(other.nwords_, 0)},
|
||||
data_{std::move(other.data_)}
|
||||
{}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
dynamic_packed_array & operator=(dynamic_packed_array && other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
|
|
@ -232,13 +263,19 @@ class dynamic_packed_array
|
|||
|
||||
~dynamic_packed_array() = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
size_type size() const noexcept { return nlanes_; }
|
||||
HEDLEY_NO_THROW
|
||||
bool empty() const noexcept { return nlanes_ == 0; }
|
||||
HEDLEY_NO_THROW
|
||||
size_type data_length() const noexcept { return nwords_; }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
word_type * data() noexcept { return data_.get(); }
|
||||
HEDLEY_NO_THROW
|
||||
const word_type * data() const noexcept { return data_.get(); }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
LaneT operator[](size_type i) const noexcept
|
||||
{
|
||||
assert(i < nlanes_);
|
||||
|
|
@ -247,6 +284,7 @@ class dynamic_packed_array
|
|||
return static_cast<LaneT>((data_[bit / 64u] >> shift) & lane_mask);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
lane_ref operator[](size_type i) noexcept
|
||||
{
|
||||
assert(i < nlanes_);
|
||||
|
|
@ -255,11 +293,17 @@ class dynamic_packed_array
|
|||
static_cast<unsigned>(bit % 64u));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
iterator begin() noexcept { return iterator{data(), 0}; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator end() noexcept { return iterator{data(), nlanes_}; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator begin() const noexcept { return iterator{data_.get(), 0}; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator end() const noexcept { return iterator{data_.get(), nlanes_}; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator cbegin() const noexcept { return begin(); }
|
||||
HEDLEY_NO_THROW
|
||||
iterator cend() const noexcept { return end(); }
|
||||
|
||||
private:
|
||||
|
|
@ -284,25 +328,30 @@ class packed_share_output : public dynamic_packed_array<LaneT>
|
|||
class reference
|
||||
{
|
||||
public:
|
||||
HEDLEY_NO_THROW
|
||||
explicit reference(typename lanes::reference lane) noexcept : lane_{lane} {}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
operator share_type() const noexcept
|
||||
{
|
||||
return share_type::from_raw(static_cast<LaneT>(lane_));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
reference & operator=(const share_type & share) noexcept
|
||||
{
|
||||
lane_ = share.raw();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
reference & operator=(LaneT value) noexcept
|
||||
{
|
||||
lane_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
reference & operator=(const reference & other) noexcept
|
||||
{
|
||||
return (*this = static_cast<share_type>(other));
|
||||
|
|
@ -321,48 +370,68 @@ class packed_share_output : public dynamic_packed_array<LaneT>
|
|||
using pointer = void;
|
||||
using reference = share_type;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
iterator() noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
explicit iterator(typename lanes::iterator it) noexcept : it_{it} {}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
share_type operator*() const noexcept
|
||||
{
|
||||
return share_type::from_raw(static_cast<LaneT>(*it_));
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
share_type operator[](difference_type n) const noexcept
|
||||
{
|
||||
return share_type::from_raw(static_cast<LaneT>(it_[n]));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator++() noexcept { ++it_; return *this; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator operator++(int) noexcept { iterator p = *this; ++*this; return p; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator--() noexcept { --it_; return *this; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator operator--(int) noexcept { iterator p = *this; --*this; return p; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator+=(difference_type n) noexcept { it_ += n; return *this; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator & operator-=(difference_type n) noexcept { it_ -= n; return *this; }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend iterator operator+(iterator it, difference_type n) noexcept
|
||||
{
|
||||
it += n;
|
||||
return it;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend iterator operator+(difference_type n, iterator it) noexcept
|
||||
{
|
||||
return it + n;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend iterator operator-(iterator it, difference_type n) noexcept
|
||||
{
|
||||
it -= n;
|
||||
return it;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend difference_type operator-(iterator a, iterator b) noexcept
|
||||
{
|
||||
return a.it_ - b.it_;
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator==(iterator a, iterator b) noexcept { return a.it_ == b.it_; }
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator!=(iterator a, iterator b) noexcept { return !(a == b); }
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator<(iterator a, iterator b) noexcept { return a.it_ < b.it_; }
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator>(iterator a, iterator b) noexcept { return b < a; }
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator<=(iterator a, iterator b) noexcept { return !(b < a); }
|
||||
HEDLEY_NO_THROW
|
||||
friend bool operator>=(iterator a, iterator b) noexcept { return !(a < b); }
|
||||
|
||||
private:
|
||||
|
|
@ -375,7 +444,9 @@ class packed_share_output : public dynamic_packed_array<LaneT>
|
|||
|
||||
packed_share_output(const packed_share_output &) = delete;
|
||||
packed_share_output & operator=(const packed_share_output &) = delete;
|
||||
HEDLEY_NO_THROW
|
||||
packed_share_output(packed_share_output &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
packed_share_output & operator=(packed_share_output &&) noexcept = default;
|
||||
~packed_share_output() = default;
|
||||
|
||||
|
|
@ -383,26 +454,34 @@ class packed_share_output : public dynamic_packed_array<LaneT>
|
|||
using lanes::empty;
|
||||
using lanes::size;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
reference operator[](size_type i) noexcept
|
||||
{
|
||||
return reference{lanes::operator[](i)};
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
share_type operator[](size_type i) const noexcept
|
||||
{
|
||||
return share_type::from_raw(lanes::operator[](i));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
iterator begin() noexcept { return iterator{lanes::begin()}; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator end() noexcept { return iterator{lanes::end()}; }
|
||||
HEDLEY_NO_THROW
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return iterator{typename lanes::iterator{this->data(), 0}};
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return iterator{typename lanes::iterator{this->data(), this->size()}};
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
iterator cbegin() const noexcept { return begin(); }
|
||||
HEDLEY_NO_THROW
|
||||
iterator cend() const noexcept { return end(); }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ namespace detail
|
|||
|
||||
template <unsigned Bits>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
unsigned lane_at(unsigned byte, unsigned shift) noexcept
|
||||
{
|
||||
constexpr unsigned mask = (1u << Bits) - 1u;
|
||||
|
|
@ -67,6 +68,7 @@ NodeT apply_bytes(const NodeT & a, const NodeT & b, Op op) noexcept
|
|||
return out;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m128i nibble_lut(const unsigned char lut[16]) noexcept
|
||||
{
|
||||
simde__m128i table;
|
||||
|
|
@ -74,6 +76,7 @@ inline simde__m128i nibble_lut(const unsigned char lut[16]) noexcept
|
|||
return table;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m256i nibble_lut256(const unsigned char lut[16]) noexcept
|
||||
{
|
||||
alignas(32) unsigned char both[32];
|
||||
|
|
@ -84,6 +87,7 @@ inline simde__m256i nibble_lut256(const unsigned char lut[16]) noexcept
|
|||
return table;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline void fill_epi2_mul_lut(unsigned k, unsigned char lut[16]) noexcept
|
||||
{
|
||||
k &= 3u;
|
||||
|
|
@ -95,6 +99,7 @@ inline void fill_epi2_mul_lut(unsigned k, unsigned char lut[16]) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline void fill_epi4_mul_lut(unsigned k, unsigned char lut[16]) noexcept
|
||||
{
|
||||
k &= 0x0fu;
|
||||
|
|
@ -104,6 +109,7 @@ inline void fill_epi4_mul_lut(unsigned k, unsigned char lut[16]) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m128i shuffle_nibbles(simde__m128i table, simde__m128i a) noexcept
|
||||
{
|
||||
const auto m = simde_mm_set1_epi8(0x0f);
|
||||
|
|
@ -114,6 +120,7 @@ inline simde__m128i shuffle_nibbles(simde__m128i table, simde__m128i a) noexcept
|
|||
simde_mm_slli_epi16(simde_mm_and_si128(hi, m), 4));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m256i shuffle_nibbles(simde__m256i table, simde__m256i a) noexcept
|
||||
{
|
||||
const auto m = simde_mm256_set1_epi8(0x0f);
|
||||
|
|
@ -126,6 +133,7 @@ inline simde__m256i shuffle_nibbles(simde__m256i table, simde__m256i a) noexcept
|
|||
|
||||
/// Low nibble of every byte, product mod 16. Even and odd bytes are split
|
||||
/// so a product in one byte cannot land in the next.
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m128i mul_low_nibbles(simde__m128i a, simde__m128i b) noexcept
|
||||
{
|
||||
const auto lane = simde_mm_set1_epi16(0x000f);
|
||||
|
|
@ -138,6 +146,7 @@ inline simde__m128i mul_low_nibbles(simde__m128i a, simde__m128i b) noexcept
|
|||
return simde_mm_or_si128(pe, simde_mm_slli_epi16(po, 8));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
inline simde__m256i mul_low_nibbles(simde__m256i a, simde__m256i b) noexcept
|
||||
{
|
||||
const auto lane = simde_mm256_set1_epi16(0x000f);
|
||||
|
|
|
|||
|
|
@ -143,9 +143,11 @@ class parallel_const_bit_iterator
|
|||
using const_reference = const value_type &;
|
||||
using pointer = std::add_pointer_t<value_type>;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr
|
||||
parallel_const_bit_iterator(parallel_const_bit_iterator &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr
|
||||
parallel_const_bit_iterator(const parallel_const_bit_iterator &) noexcept = default;
|
||||
|
|
@ -273,6 +275,7 @@ class parallel_const_bit_iterator
|
|||
std::make_index_sequence<batch_size>());
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
explicit constexpr parallel_const_bit_iterator(
|
||||
const word_pointer_array & arr) noexcept
|
||||
: iter_{arr},
|
||||
|
|
@ -293,7 +296,9 @@ class parallel_const_bit_iterator
|
|||
simde_type vec_mask_;
|
||||
simde_array all_vecs_;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend parallel_const_bit_iterator parallel_bit_iterable<batch_size, ChildT>::begin() const noexcept;
|
||||
HEDLEY_NO_THROW
|
||||
friend parallel_const_bit_iterator parallel_bit_iterable<batch_size, ChildT>::end() const noexcept;
|
||||
}; // class dpf::parallel_const_bit_iterator
|
||||
|
||||
|
|
@ -302,6 +307,7 @@ template <std::size_t N,
|
|||
typename Iter>
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
auto batch_of(Iter it) noexcept
|
||||
{
|
||||
return dpf::parallel_bit_iterable<N, ChildT>{it};
|
||||
|
|
@ -311,6 +317,7 @@ template <typename ChildT,
|
|||
typename ...Ts>
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
auto batch_of(const dpf::bit_array_base<ChildT> & t, const Ts & ...ts) noexcept
|
||||
{
|
||||
return dpf::parallel_bit_iterable<1+sizeof...(Ts), ChildT>{t, ts...};
|
||||
|
|
|
|||
|
|
@ -75,10 +75,12 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
static constexpr auto left_shift = simde_mm256_slli_epi64;
|
||||
static constexpr auto right_shift = simde_mm256_srli_epi64;
|
||||
static constexpr auto bit_and = simde_mm256_and_si256;
|
||||
HEDLEY_NO_THROW
|
||||
static auto get_mask() noexcept
|
||||
{
|
||||
return simde_mm256_set1_epi64x(1);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
static simde_array build_vecs(const word_type * cur_word, std::size_t nwords) noexcept
|
||||
{
|
||||
return { loadu_word_vec(cur_word, nwords, 0) };
|
||||
|
|
@ -104,10 +106,12 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
static constexpr auto left_shift = simde_mm256_slli_epi64;
|
||||
static constexpr auto right_shift = simde_mm256_srli_epi64;
|
||||
static constexpr auto bit_and = simde_mm256_and_si256;
|
||||
HEDLEY_NO_THROW
|
||||
static auto get_mask() noexcept
|
||||
{
|
||||
return simde_mm256_set1_epi32(1);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
static simde_array build_vecs(const typename dpf::bit_array_base<ChildT>::word_type * cur_word,
|
||||
std::size_t nwords) noexcept
|
||||
{
|
||||
|
|
@ -149,10 +153,12 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
static constexpr auto left_shift = simde_mm256_slli_epi64;
|
||||
static constexpr auto right_shift = simde_mm256_srli_epi64;
|
||||
static constexpr auto bit_and = simde_mm256_and_si256;
|
||||
HEDLEY_NO_THROW
|
||||
static auto get_mask() noexcept
|
||||
{
|
||||
return simde_mm256_set1_epi16(1);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
static simde_array build_vecs(const typename dpf::bit_array_base<ChildT>::word_type * cur_word,
|
||||
std::size_t nwords) noexcept
|
||||
{
|
||||
|
|
@ -215,10 +221,12 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
static constexpr auto left_shift = simde_mm256_slli_epi64;
|
||||
static constexpr auto right_shift = simde_mm256_srli_epi64;
|
||||
static constexpr auto bit_and = simde_mm256_and_si256;
|
||||
HEDLEY_NO_THROW
|
||||
static auto get_mask() noexcept
|
||||
{
|
||||
return simde_mm256_set1_epi8(1);
|
||||
}
|
||||
HEDLEY_NO_THROW
|
||||
static simde_array build_vecs(const typename dpf::bit_array_base<ChildT>::word_type * cur_word,
|
||||
std::size_t nwords) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
/// @file dpf/path_memoizer.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Workspaces that resume a root-to-leaf DPF walk.
|
||||
/// @details `basic_path_memoizer` keeps one interior node per level. The next
|
||||
/// `eval_point` recomputes the suffix after the common prefix with
|
||||
/// the previous input. `nonmemoizing_path_memoizer` keeps a single
|
||||
/// node and starts at the root on every call.
|
||||
///
|
||||
/// Pass a mutable lvalue to `eval_point`. The factories unwrap
|
||||
/// `party_key`, so a memoizer built from either party's type
|
||||
/// accepts both parties. A different root restarts the path.
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -44,13 +51,21 @@ struct path_memoizer_base
|
|||
using return_type = ReturnT;
|
||||
using iterator_type = return_type;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
virtual std::size_t assign_x(const dpf_type &, input_type) noexcept = 0;
|
||||
HEDLEY_NO_THROW
|
||||
virtual node_type & operator[](std::size_t) noexcept = 0;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type begin() const noexcept = 0;
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type end() const noexcept = 0;
|
||||
};
|
||||
|
||||
/// One interior node per level. `assign_x` returns the first level that the
|
||||
/// next walk must recompute. `filled_to` is the deepest level already
|
||||
/// written for the current input. Callers pass this object to `eval_point`;
|
||||
/// they do not call `assign_x` themselves.
|
||||
template <typename DpfKey>
|
||||
struct alignas(alignof(typename path_memoizer_key_t<DpfKey>::interior_node))
|
||||
basic_path_memoizer final
|
||||
|
|
@ -69,12 +84,15 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
basic_path_memoizer()
|
||||
: dpf_{std::nullopt}, x_{std::nullopt}, filled_to_{0} { }
|
||||
HEDLEY_NO_THROW
|
||||
basic_path_memoizer(basic_path_memoizer &&) noexcept = default;
|
||||
basic_path_memoizer(const basic_path_memoizer &) = default;
|
||||
HEDLEY_NO_THROW
|
||||
basic_path_memoizer & operator=(basic_path_memoizer &&) noexcept = default;
|
||||
basic_path_memoizer & operator=(const basic_path_memoizer &) = default;
|
||||
~basic_path_memoizer() = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t assign_x(const dpf_type & dpf, input_type new_x) noexcept override
|
||||
{
|
||||
static constexpr auto clz_xor = utils::countl_zero_symmetric_difference<input_type>{};
|
||||
|
|
@ -100,11 +118,13 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
return 1;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
node_type & operator[](std::size_t i) noexcept override
|
||||
{
|
||||
return arr_[i];
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
return_type begin() const noexcept override
|
||||
{
|
||||
if (x_.has_value() == true)
|
||||
|
|
@ -117,14 +137,17 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
}
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
return_type end() const noexcept override
|
||||
{
|
||||
return std::addressof(arr_[depth+1]);
|
||||
}
|
||||
|
||||
/// Inclusive high-water: `arr_[0..filled_to_]` are valid for the current x.
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t filled_to() const noexcept { return filled_to_; }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
void note_filled(std::size_t level) noexcept
|
||||
{
|
||||
if (level > filled_to_)
|
||||
|
|
@ -143,6 +166,7 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
|
|||
HEDLEY_PRAGMA(GCC diagnostic pop)
|
||||
};
|
||||
|
||||
/// A single interior node. Every `assign_x` restarts at the root.
|
||||
template <typename DpfKey>
|
||||
struct nonmemoizing_path_memoizer final
|
||||
: public path_memoizer_base<path_memoizer_key_t<DpfKey>>
|
||||
|
|
@ -159,8 +183,10 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
nonmemoizing_path_memoizer()
|
||||
: dpf_{std::nullopt} { }
|
||||
HEDLEY_NO_THROW
|
||||
nonmemoizing_path_memoizer(nonmemoizing_path_memoizer &&) noexcept = default;
|
||||
nonmemoizing_path_memoizer(const nonmemoizing_path_memoizer &) = default;
|
||||
HEDLEY_NO_THROW
|
||||
nonmemoizing_path_memoizer & operator=(nonmemoizing_path_memoizer &&) noexcept = default;
|
||||
nonmemoizing_path_memoizer & operator=(const nonmemoizing_path_memoizer &) = default;
|
||||
~nonmemoizing_path_memoizer() = default;
|
||||
|
|
@ -186,6 +212,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
return std::addressof(v);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
return_type end() const noexcept override
|
||||
{
|
||||
return std::addressof(v) + 1;
|
||||
|
|
@ -260,6 +287,9 @@ void ensure_level(const DpfKey & dpf, typename DpfKey::input_type x,
|
|||
|
||||
} // namespace detail
|
||||
|
||||
/// Path workspace for `DpfKey`. A `party_key` argument is unwrapped, and the
|
||||
/// result accepts both parties.
|
||||
/// @snippet evaluation/memoizers.cpp path-memoizer
|
||||
template <typename DpfKey>
|
||||
auto make_basic_path_memoizer()
|
||||
{
|
||||
|
|
@ -272,6 +302,7 @@ auto make_basic_path_memoizer(const DpfKey &)
|
|||
return make_basic_path_memoizer<DpfKey>();
|
||||
}
|
||||
|
||||
/// Single-node path workspace. Suitable for one query.
|
||||
template <typename DpfKey>
|
||||
auto make_nonmemoizing_path_memoizer()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ template <typename T> inline constexpr bool is_at_v = is_at<T>::value;
|
|||
/// `OutBits` is the comparison output group width (bits of the β payload),
|
||||
/// so the value CWs / addend can be stored at group width instead of a full
|
||||
/// padded `uint64_t` per level.
|
||||
template <std::size_t Depth, std::size_t OutBits = 0, bool Wild = false>
|
||||
template <std::size_t Depth, std::size_t OutBits = 0, bool Wild = false,
|
||||
std::size_t BlockWidth = 0, bool Incremental = false>
|
||||
struct cmp_channel_tag
|
||||
{
|
||||
static constexpr std::size_t depth = Depth;
|
||||
|
|
@ -73,11 +74,17 @@ struct cmp_channel_tag
|
|||
/// after keygen. Concrete (non-wildcard) cmp keys keep `Wild == false`
|
||||
/// so their layout / type name is unchanged.
|
||||
static constexpr bool wild = Wild;
|
||||
/// 0 keeps the per-level path-sum. `B >= 1` selects blocked checkpoints
|
||||
/// of target width `B`.
|
||||
static constexpr std::size_t block_width = BlockWidth;
|
||||
/// Save a final correction at every depth (`idcf`).
|
||||
static constexpr bool incremental = Incremental;
|
||||
};
|
||||
|
||||
template <typename T> struct is_cmp_channel_tag : std::false_type {};
|
||||
template <std::size_t Depth, std::size_t OutBits, bool Wild>
|
||||
struct is_cmp_channel_tag<cmp_channel_tag<Depth, OutBits, Wild>>
|
||||
template <std::size_t Depth, std::size_t OutBits, bool Wild, std::size_t Block,
|
||||
bool Incremental>
|
||||
struct is_cmp_channel_tag<cmp_channel_tag<Depth, OutBits, Wild, Block, Incremental>>
|
||||
: std::true_type {};
|
||||
template <typename T>
|
||||
inline constexpr bool is_cmp_channel_tag_v =
|
||||
|
|
@ -107,6 +114,28 @@ struct is_placed<placed<N, O>> : std::true_type {};
|
|||
template <typename T>
|
||||
inline constexpr bool is_placed_v = is_placed<std::decay_t<T>>::value;
|
||||
|
||||
/// Heavy-hitters incremental point function: one payload per prefix length.
|
||||
/// `levels[i]` is the bit length of slot `i`.
|
||||
template <typename LevelSeq, typename ...Betas>
|
||||
struct idpf_pack;
|
||||
|
||||
template <std::size_t ...Levels, typename ...Betas>
|
||||
struct idpf_pack<std::index_sequence<Levels...>, Betas...>
|
||||
{
|
||||
static constexpr bool is_idpf = true;
|
||||
static constexpr std::size_t n = sizeof...(Levels);
|
||||
static constexpr std::array<std::size_t, n == 0 ? 1 : n> levels{
|
||||
Levels...};
|
||||
std::tuple<Betas...> values;
|
||||
};
|
||||
|
||||
template <typename T> struct is_idpf : std::false_type {};
|
||||
template <std::size_t ...Levels, typename ...Betas>
|
||||
struct is_idpf<idpf_pack<std::index_sequence<Levels...>, Betas...>>
|
||||
: std::true_type {};
|
||||
template <typename T>
|
||||
inline constexpr bool is_idpf_v = is_idpf<std::decay_t<T>>::value;
|
||||
|
||||
template <typename NodeT, typename OutputT>
|
||||
inline constexpr std::size_t out_bits_v =
|
||||
utils::bitlength_of_output_v<concrete_type_t<OutputT>, NodeT>;
|
||||
|
|
@ -385,6 +414,8 @@ struct normalize_one
|
|||
static constexpr std::size_t cmp_depth = 0;
|
||||
static constexpr std::size_t cmp_out_bits = 0;
|
||||
static constexpr bool cmp_wild = false;
|
||||
static constexpr std::size_t cmp_block = 0;
|
||||
static constexpr bool cmp_idcf = false;
|
||||
};
|
||||
template <std::size_t BitLen, std::size_t N, typename T>
|
||||
struct normalize_one<BitLen, placed<N, T>>
|
||||
|
|
@ -393,14 +424,20 @@ struct normalize_one<BitLen, placed<N, T>>
|
|||
static constexpr std::size_t cmp_depth = 0;
|
||||
static constexpr std::size_t cmp_out_bits = 0;
|
||||
static constexpr bool cmp_wild = false;
|
||||
static constexpr std::size_t cmp_block = 0;
|
||||
static constexpr bool cmp_idcf = false;
|
||||
};
|
||||
template <std::size_t BitLen, std::size_t Depth, std::size_t OutBits, bool Wild>
|
||||
struct normalize_one<BitLen, cmp_channel_tag<Depth, OutBits, Wild>>
|
||||
template <std::size_t BitLen, std::size_t Depth, std::size_t OutBits, bool Wild,
|
||||
std::size_t Block, bool Incremental>
|
||||
struct normalize_one<BitLen,
|
||||
cmp_channel_tag<Depth, OutBits, Wild, Block, Incremental>>
|
||||
{
|
||||
using placed_tuple = std::tuple<>;
|
||||
static constexpr std::size_t cmp_depth = Depth;
|
||||
static constexpr std::size_t cmp_out_bits = OutBits;
|
||||
static constexpr bool cmp_wild = Wild;
|
||||
static constexpr std::size_t cmp_block = Block;
|
||||
static constexpr bool cmp_idcf = Incremental;
|
||||
};
|
||||
|
||||
template <std::size_t BitLen, typename ...Elems>
|
||||
|
|
@ -419,6 +456,10 @@ struct normalize_pack
|
|||
// wildcard flag (false when there is no cmp channel).
|
||||
static constexpr bool cmp_wild =
|
||||
(false || ... || normalize_one<BitLen, Elems>::cmp_wild);
|
||||
static constexpr std::size_t cmp_block =
|
||||
(std::size_t{0} + ... + normalize_one<BitLen, Elems>::cmp_block);
|
||||
static constexpr bool cmp_idcf =
|
||||
(false || ... || normalize_one<BitLen, Elems>::cmp_idcf);
|
||||
};
|
||||
|
||||
template <std::size_t BitLen>
|
||||
|
|
@ -428,6 +469,8 @@ struct normalize_pack<BitLen>
|
|||
static constexpr std::size_t cmp_depth = 0;
|
||||
static constexpr std::size_t cmp_out_bits = 0;
|
||||
static constexpr bool cmp_wild = false;
|
||||
static constexpr std::size_t cmp_block = 0;
|
||||
static constexpr bool cmp_idcf = false;
|
||||
};
|
||||
|
||||
/// True iff the pack is "classic-shaped": every element is a bare output (no
|
||||
|
|
@ -439,6 +482,32 @@ inline constexpr bool is_classic_pack_v =
|
|||
} // namespace incr
|
||||
} // namespace detail
|
||||
|
||||
/// Sparse heavy-hitters IDPF. Slot `i` is the point function on prefix
|
||||
/// `Levels[i]`, evaluated with `out<i>`.
|
||||
template <std::size_t ...Levels, typename ...Betas>
|
||||
auto idpf_at(Betas ...betas)
|
||||
{
|
||||
static_assert(sizeof...(Levels) == sizeof...(Betas),
|
||||
"idpf_at: one payload per prefix length");
|
||||
return detail::incr::idpf_pack<std::index_sequence<Levels...>,
|
||||
std::decay_t<Betas>...>{
|
||||
std::tuple<std::decay_t<Betas>...>{std::move(betas)...}};
|
||||
}
|
||||
|
||||
template <std::size_t ...I, typename ...Betas>
|
||||
auto idpf_from_seq(std::index_sequence<I...>, Betas ...betas)
|
||||
{
|
||||
return idpf_at<(I + 1)...>(std::move(betas)...);
|
||||
}
|
||||
|
||||
/// Consecutive prefixes of length 1, 2, …, `sizeof...(Betas)`.
|
||||
template <typename ...Betas>
|
||||
auto idpf(Betas ...betas)
|
||||
{
|
||||
return idpf_from_seq(std::make_index_sequence<sizeof...(Betas)>{},
|
||||
std::move(betas)...);
|
||||
}
|
||||
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_PLACEMENT_HPP__
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include "dpf/prg_aes.hpp"
|
||||
#include "dpf/prg_chacha.hpp"
|
||||
#include "dpf/prg_dummy.hpp"
|
||||
#include "dpf/prg_lowmc.hpp"
|
||||
#include "dpf/secret_share.hpp"
|
||||
|
|
@ -63,23 +65,34 @@ auto expand_as_share(typename PRG::block_type seed,
|
|||
|
||||
template <typename AesKey>
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
auto aes<AesKey>::expand(block_type seed, psnip_uint32_t pos) noexcept
|
||||
{
|
||||
return detail::expand_as_share<aes<AesKey>, T, Party>(seed, pos);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
auto dummy::expand(block_type seed, psnip_uint32_t pos) noexcept
|
||||
{
|
||||
return detail::expand_as_share<dummy, T, Party>(seed, pos);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
auto lowmc128::expand(block_type seed, psnip_uint32_t pos) noexcept
|
||||
{
|
||||
return detail::expand_as_share<lowmc128, T, Party>(seed, pos);
|
||||
}
|
||||
|
||||
template <unsigned Rounds>
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
auto chacha<Rounds>::expand(block_type seed, psnip_uint32_t pos) noexcept
|
||||
{
|
||||
return detail::expand_as_share<chacha<Rounds>, T, Party>(seed, pos);
|
||||
}
|
||||
|
||||
template <typename PRG>
|
||||
struct counter_wrapper final
|
||||
{
|
||||
|
|
@ -101,17 +114,22 @@ struct counter_wrapper final
|
|||
return PRG::eval01(seed);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static void eval(block_type seed, block_type * HEDLEY_RESTRICT output,
|
||||
psnip_uint32_t count, psnip_uint32_t pos = 0) noexcept
|
||||
psnip_uint32_t count, psnip_uint32_t pos = 0)
|
||||
{
|
||||
if (count > 1 &&
|
||||
pos > static_cast<psnip_uint32_t>(~static_cast<psnip_uint32_t>(0)) - (count - 1u))
|
||||
{
|
||||
throw std::invalid_argument("prg lane index is out of range");
|
||||
}
|
||||
count_.fetch_add(count, std::memory_order::memory_order_relaxed);
|
||||
PRG::eval(seed, output, count, pos);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2, 3)
|
||||
static void eval01_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT left,
|
||||
block_type * HEDLEY_RESTRICT right) noexcept
|
||||
|
|
@ -122,6 +140,7 @@ struct counter_wrapper final
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos = 0) noexcept
|
||||
{
|
||||
|
|
@ -131,6 +150,7 @@ struct counter_wrapper final
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x8(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos = 0) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
#include "simde/simde/x86/avx2.h"
|
||||
|
|
@ -103,15 +104,21 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
/// `eval` / `eval01` (`set_epi64x(0, pos)`). The first AddRoundKey
|
||||
/// includes `rd_key[0]` so this matches the one-block `eval` for any
|
||||
/// key, not only the all-zero key this PRG currently installs.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static void eval(block_type seed, block_type * HEDLEY_RESTRICT output,
|
||||
psnip_uint32_t count, psnip_uint32_t pos = 0) noexcept
|
||||
psnip_uint32_t count, psnip_uint32_t pos = 0)
|
||||
{
|
||||
if (HEDLEY_UNLIKELY(count == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// `pos + i` is a uint32 add. A span that passes UINT32_MAX must
|
||||
// fail the same way buffered_prg does, rather than wrap to 0.
|
||||
if (count > 1 &&
|
||||
pos > static_cast<psnip_uint32_t>(~static_cast<psnip_uint32_t>(0)) - (count - 1u))
|
||||
{
|
||||
throw std::invalid_argument("prg lane index is out of range");
|
||||
}
|
||||
|
||||
require_block_aligned(output);
|
||||
block_type * HEDLEY_RESTRICT out =
|
||||
|
|
@ -161,6 +168,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
/// `left[i] == eval(seeds[i], 0)`, `right[i] == eval(seeds[i], 1)`.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2, 3)
|
||||
static void eval01_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT left,
|
||||
block_type * HEDLEY_RESTRICT right) noexcept
|
||||
|
|
@ -193,6 +201,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
/// Four independent `eval(seed, pos)` as one 4-block round-major AES.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos) noexcept
|
||||
{
|
||||
|
|
@ -223,6 +232,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
/// Eight independent `eval(seed, pos)` as one 8-block round-major AES.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x8(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos) noexcept
|
||||
{
|
||||
|
|
@ -252,6 +262,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
/// Raw-bit subtractive share of `T` for party `Party` (see `prg.hpp`).
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
static auto expand(block_type seed, psnip_uint32_t pos = 0) noexcept;
|
||||
|
||||
private:
|
||||
|
|
@ -261,6 +272,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
/// rounds 1..last and the MMO feed-forward `XOR seed[i]`.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void aes_mmo_rounds_x4(block_type * HEDLEY_RESTRICT blk,
|
||||
const block_type * HEDLEY_RESTRICT seed) noexcept
|
||||
{
|
||||
|
|
@ -283,6 +295,7 @@ HEDLEY_PRAGMA(GCC unroll(14))
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void aes_mmo_rounds_x8(block_type * HEDLEY_RESTRICT blk,
|
||||
const block_type * HEDLEY_RESTRICT seed) noexcept
|
||||
{
|
||||
|
|
|
|||
458
include/dpf/prg_chacha.hpp
Normal file
458
include/dpf/prg_chacha.hpp
Normal file
|
|
@ -0,0 +1,458 @@
|
|||
/// @file dpf/prg_chacha.hpp
|
||||
/// @brief ChaCha stream PRG. Same 128-bit block interface as `aes128`.
|
||||
/// @details `eval(seed, pos)` is the `pos`-th 16-byte chunk of ChaCha
|
||||
/// keystream (RFC 8439). The 256-bit key is the 128-bit seed
|
||||
/// followed by the fixed domain separator `"dpf-chacha-prg\0\0"`.
|
||||
/// The nonce is zero. The ChaCha block counter is `pos / 4`, and
|
||||
/// the chunk inside that block is `pos % 4`.
|
||||
///
|
||||
/// `chacha20` is the RFC round count. `chacha12` and `chacha8` are
|
||||
/// the same construction with fewer rounds. `chacha<R>` accepts any
|
||||
/// positive even round count.
|
||||
/// @copyright Copyright (c) 2019-2026 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_PRG_CHACHA_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_PRG_CHACHA_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
#include "simde/simde/x86/avx2.h"
|
||||
#include "portable-snippets/exact-int/exact-int.h"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
|
||||
namespace prg
|
||||
{
|
||||
|
||||
namespace chacha_detail
|
||||
{
|
||||
|
||||
inline constexpr std::uint32_t zero_nonce[3] = {0, 0, 0};
|
||||
|
||||
/// ASCII `"dpf-chacha-prg"` plus two zero bytes. Public second half of the key.
|
||||
inline constexpr std::uint8_t domain[16] = {
|
||||
'd', 'p', 'f', '-', 'c', 'h', 'a', 'c',
|
||||
'h', 'a', '-', 'p', 'r', 'g', 0, 0
|
||||
};
|
||||
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NON_NULL(1)
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::uint32_t load_le32(const std::uint8_t * p) noexcept
|
||||
{
|
||||
return static_cast<std::uint32_t>(p[0])
|
||||
| (static_cast<std::uint32_t>(p[1]) << 8)
|
||||
| (static_cast<std::uint32_t>(p[2]) << 16)
|
||||
| (static_cast<std::uint32_t>(p[3]) << 24);
|
||||
}
|
||||
|
||||
HEDLEY_NON_NULL(1)
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
void store_le32(std::uint8_t * p, std::uint32_t w) noexcept
|
||||
{
|
||||
p[0] = static_cast<std::uint8_t>(w);
|
||||
p[1] = static_cast<std::uint8_t>(w >> 8);
|
||||
p[2] = static_cast<std::uint8_t>(w >> 16);
|
||||
p[3] = static_cast<std::uint8_t>(w >> 24);
|
||||
}
|
||||
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NON_NULL(1)
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
simde__m128i load_block(const std::uint8_t * p) noexcept
|
||||
{
|
||||
simde__m128i out;
|
||||
std::memcpy(&out, p, sizeof(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
/// 128-bit seed in the low half, `domain` in the high half, both little-endian.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
void seed_key(simde__m128i seed, std::uint32_t key[8]) noexcept
|
||||
{
|
||||
std::uint8_t raw[16];
|
||||
std::memcpy(raw, &seed, sizeof(raw));
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
key[i] = load_le32(raw + 4 * i);
|
||||
key[4 + i] = load_le32(domain + 4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
template <int N>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr std::uint32_t rotl(std::uint32_t x) noexcept
|
||||
{
|
||||
static_assert(N > 0 && N < 32, "ChaCha rotation is between 1 and 31");
|
||||
return (x << N) | (x >> (32 - N));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
void quarter(std::uint32_t & a, std::uint32_t & b,
|
||||
std::uint32_t & c, std::uint32_t & d) noexcept
|
||||
{
|
||||
a += b; d ^= a; d = rotl<16>(d);
|
||||
c += d; b ^= c; b = rotl<12>(b);
|
||||
a += b; d ^= a; d = rotl<8>(d);
|
||||
c += d; b ^= c; b = rotl<7>(b);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
simde__m128i rotl_epi32(simde__m128i v) noexcept
|
||||
{
|
||||
static_assert(N > 0 && N < 32, "ChaCha rotation is between 1 and 31");
|
||||
return simde_mm_or_si128(simde_mm_slli_epi32(v, N),
|
||||
simde_mm_srli_epi32(v, 32 - N));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
void quarter(simde__m128i x[], int a, int b, int c, int d) noexcept
|
||||
{
|
||||
x[a] = simde_mm_add_epi32(x[a], x[b]);
|
||||
x[d] = rotl_epi32<16>(simde_mm_xor_si128(x[d], x[a]));
|
||||
x[c] = simde_mm_add_epi32(x[c], x[d]);
|
||||
x[b] = rotl_epi32<12>(simde_mm_xor_si128(x[b], x[c]));
|
||||
x[a] = simde_mm_add_epi32(x[a], x[b]);
|
||||
x[d] = rotl_epi32<8>(simde_mm_xor_si128(x[d], x[a]));
|
||||
x[c] = simde_mm_add_epi32(x[c], x[d]);
|
||||
x[b] = rotl_epi32<7>(simde_mm_xor_si128(x[b], x[c]));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
std::uint32_t epi32_lane(simde__m128i v, int lane) noexcept
|
||||
{
|
||||
// Shuffle control is an immediate, so each lane is its own case.
|
||||
switch (lane)
|
||||
{
|
||||
case 1: v = simde_mm_shuffle_epi32(v, 0x01); break;
|
||||
case 2: v = simde_mm_shuffle_epi32(v, 0x02); break;
|
||||
case 3: v = simde_mm_shuffle_epi32(v, 0x03); break;
|
||||
default: break;
|
||||
}
|
||||
return static_cast<std::uint32_t>(simde_mm_cvtsi128_si32(v));
|
||||
}
|
||||
|
||||
/// One ChaCha block. `key` is 8 little-endian words. `nonce` is 3 words.
|
||||
template <unsigned Rounds>
|
||||
HEDLEY_NO_THROW
|
||||
void block(const std::uint32_t key[8], std::uint32_t counter,
|
||||
const std::uint32_t nonce[3], std::uint8_t out[64]) noexcept
|
||||
{
|
||||
static_assert(Rounds >= 2 && Rounds % 2 == 0,
|
||||
"ChaCha rounds must be a positive even number");
|
||||
|
||||
std::uint32_t s[16] = {
|
||||
0x61707865u, 0x3320646eu, 0x79622d32u, 0x6b206574u,
|
||||
key[0], key[1], key[2], key[3],
|
||||
key[4], key[5], key[6], key[7],
|
||||
counter, nonce[0], nonce[1], nonce[2]
|
||||
};
|
||||
std::uint32_t orig[16];
|
||||
std::memcpy(orig, s, sizeof(orig));
|
||||
|
||||
HEDLEY_PRAGMA(GCC unroll 16)
|
||||
for (unsigned r = 0; r < Rounds; r += 2)
|
||||
{
|
||||
quarter(s[0], s[4], s[8], s[12]);
|
||||
quarter(s[1], s[5], s[9], s[13]);
|
||||
quarter(s[2], s[6], s[10], s[14]);
|
||||
quarter(s[3], s[7], s[11], s[15]);
|
||||
quarter(s[0], s[5], s[10], s[15]);
|
||||
quarter(s[1], s[6], s[11], s[12]);
|
||||
quarter(s[2], s[7], s[8], s[13]);
|
||||
quarter(s[3], s[4], s[9], s[14]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
store_le32(out + 4 * i, s[i] + orig[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Four independent ChaCha blocks. Lane `i` uses `key[i]` and `counter[i]`.
|
||||
/// Nonce is zero. Each `out[i]` receives 64 bytes.
|
||||
template <unsigned Rounds>
|
||||
HEDLEY_NO_THROW
|
||||
void block4(const std::uint32_t key[][8], const std::uint32_t counter[4],
|
||||
std::uint8_t out[][64]) noexcept
|
||||
{
|
||||
static_assert(Rounds >= 2 && Rounds % 2 == 0,
|
||||
"ChaCha rounds must be a positive even number");
|
||||
|
||||
simde__m128i x[16];
|
||||
x[0] = simde_mm_set1_epi32(static_cast<int>(0x61707865u));
|
||||
x[1] = simde_mm_set1_epi32(static_cast<int>(0x3320646eu));
|
||||
x[2] = simde_mm_set1_epi32(static_cast<int>(0x79622d32u));
|
||||
x[3] = simde_mm_set1_epi32(static_cast<int>(0x6b206574u));
|
||||
for (int w = 0; w < 8; ++w)
|
||||
{
|
||||
x[4 + w] = simde_mm_set_epi32(
|
||||
static_cast<int>(key[3][w]),
|
||||
static_cast<int>(key[2][w]),
|
||||
static_cast<int>(key[1][w]),
|
||||
static_cast<int>(key[0][w]));
|
||||
}
|
||||
x[12] = simde_mm_set_epi32(
|
||||
static_cast<int>(counter[3]),
|
||||
static_cast<int>(counter[2]),
|
||||
static_cast<int>(counter[1]),
|
||||
static_cast<int>(counter[0]));
|
||||
x[13] = simde_mm_setzero_si128();
|
||||
x[14] = simde_mm_setzero_si128();
|
||||
x[15] = simde_mm_setzero_si128();
|
||||
|
||||
simde__m128i orig[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
orig[i] = x[i];
|
||||
}
|
||||
|
||||
HEDLEY_PRAGMA(GCC unroll 16)
|
||||
for (unsigned r = 0; r < Rounds; r += 2)
|
||||
{
|
||||
quarter(x, 0, 4, 8, 12);
|
||||
quarter(x, 1, 5, 9, 13);
|
||||
quarter(x, 2, 6, 10, 14);
|
||||
quarter(x, 3, 7, 11, 15);
|
||||
quarter(x, 0, 5, 10, 15);
|
||||
quarter(x, 1, 6, 11, 12);
|
||||
quarter(x, 2, 7, 8, 13);
|
||||
quarter(x, 3, 4, 9, 14);
|
||||
}
|
||||
|
||||
for (int lane = 0; lane < 4; ++lane)
|
||||
{
|
||||
for (int w = 0; w < 16; ++w)
|
||||
{
|
||||
std::uint32_t sum = epi32_lane(x[w], lane) + epi32_lane(orig[w], lane);
|
||||
store_le32(out[lane] + 4 * w, sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chacha_detail
|
||||
|
||||
/// ChaCha stream PRG with `Rounds` rounds (20 is RFC 8439).
|
||||
template <unsigned Rounds = 20>
|
||||
struct chacha final
|
||||
{
|
||||
static_assert(Rounds >= 2 && Rounds % 2 == 0,
|
||||
"ChaCha rounds must be a positive even number");
|
||||
|
||||
using block_type = simde__m128i;
|
||||
static constexpr unsigned rounds = Rounds;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static block_type eval(block_type seed, psnip_uint32_t pos) noexcept
|
||||
{
|
||||
std::uint32_t key[8];
|
||||
chacha_detail::seed_key(seed, key);
|
||||
std::uint8_t buf[64];
|
||||
chacha_detail::block<Rounds>(key, pos >> 2,
|
||||
chacha_detail::zero_nonce, buf);
|
||||
return chacha_detail::load_block(buf + 16 * (pos & 3u));
|
||||
}
|
||||
|
||||
/// Positions 0 and 1, one ChaCha block (the first 32 keystream bytes).
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static auto eval01(block_type seed) noexcept
|
||||
{
|
||||
std::uint32_t key[8];
|
||||
chacha_detail::seed_key(seed, key);
|
||||
std::uint8_t buf[64];
|
||||
chacha_detail::block<Rounds>(key, 0, chacha_detail::zero_nonce, buf);
|
||||
HEDLEY_PRAGMA(GCC diagnostic push)
|
||||
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
|
||||
return std::array<block_type, 2>{
|
||||
chacha_detail::load_block(buf),
|
||||
chacha_detail::load_block(buf + 16)
|
||||
};
|
||||
HEDLEY_PRAGMA(GCC diagnostic pop)
|
||||
}
|
||||
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static void eval(block_type seed, block_type * HEDLEY_RESTRICT output,
|
||||
psnip_uint32_t count, psnip_uint32_t pos = 0)
|
||||
{
|
||||
if (HEDLEY_UNLIKELY(count == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (count > 1 &&
|
||||
pos > static_cast<psnip_uint32_t>(~static_cast<psnip_uint32_t>(0)) - (count - 1u))
|
||||
{
|
||||
throw std::invalid_argument("prg lane index is out of range");
|
||||
}
|
||||
if (count == 1)
|
||||
{
|
||||
output[0] = eval(seed, pos);
|
||||
return;
|
||||
}
|
||||
if (count == 2 && pos == 0)
|
||||
{
|
||||
auto kids = eval01(seed);
|
||||
output[0] = kids[0];
|
||||
output[1] = kids[1];
|
||||
return;
|
||||
}
|
||||
|
||||
std::uint32_t key[8];
|
||||
chacha_detail::seed_key(seed, key);
|
||||
psnip_uint32_t i = 0;
|
||||
|
||||
// `pos` may begin mid-block. Those chunks share one ChaCha block.
|
||||
if ((pos & 3u) != 0u)
|
||||
{
|
||||
std::uint8_t buf[64];
|
||||
chacha_detail::block<Rounds>(key, pos >> 2,
|
||||
chacha_detail::zero_nonce, buf);
|
||||
while (i < count && ((pos + i) & 3u) != 0u)
|
||||
{
|
||||
output[i] = chacha_detail::load_block(
|
||||
buf + 16 * ((pos + i) & 3u));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// Four consecutive counters cover 16 output blocks.
|
||||
while (i + 16u <= count)
|
||||
{
|
||||
std::uint32_t base = (pos + i) >> 2;
|
||||
std::uint32_t keys[4][8];
|
||||
std::uint32_t counters[4];
|
||||
for (int lane = 0; lane < 4; ++lane)
|
||||
{
|
||||
std::memcpy(keys[lane], key, sizeof(key));
|
||||
counters[lane] = base + static_cast<std::uint32_t>(lane);
|
||||
}
|
||||
std::uint8_t buf[4][64];
|
||||
chacha_detail::block4<Rounds>(keys, counters, buf);
|
||||
for (int lane = 0; lane < 4; ++lane)
|
||||
{
|
||||
for (int chunk = 0; chunk < 4; ++chunk)
|
||||
{
|
||||
output[i++] = chacha_detail::load_block(
|
||||
buf[lane] + 16 * chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (i + 4u <= count)
|
||||
{
|
||||
std::uint8_t buf[64];
|
||||
chacha_detail::block<Rounds>(key, (pos + i) >> 2,
|
||||
chacha_detail::zero_nonce, buf);
|
||||
for (int chunk = 0; chunk < 4; ++chunk)
|
||||
{
|
||||
output[i++] = chacha_detail::load_block(buf + 16 * chunk);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < count)
|
||||
{
|
||||
std::uint8_t buf[64];
|
||||
chacha_detail::block<Rounds>(key, (pos + i) >> 2,
|
||||
chacha_detail::zero_nonce, buf);
|
||||
unsigned chunk = 0;
|
||||
while (i < count)
|
||||
{
|
||||
output[i++] = chacha_detail::load_block(buf + 16 * chunk);
|
||||
++chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2, 3)
|
||||
static void eval01_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT left,
|
||||
block_type * HEDLEY_RESTRICT right) noexcept
|
||||
{
|
||||
std::uint32_t keys[4][8];
|
||||
std::uint32_t counters[4] = {0, 0, 0, 0};
|
||||
for (int lane = 0; lane < 4; ++lane)
|
||||
{
|
||||
chacha_detail::seed_key(seeds[lane], keys[lane]);
|
||||
}
|
||||
std::uint8_t buf[4][64];
|
||||
chacha_detail::block4<Rounds>(keys, counters, buf);
|
||||
for (int lane = 0; lane < 4; ++lane)
|
||||
{
|
||||
left[lane] = chacha_detail::load_block(buf[lane]);
|
||||
right[lane] = chacha_detail::load_block(buf[lane] + 16);
|
||||
}
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos = 0) noexcept
|
||||
{
|
||||
std::uint32_t keys[4][8];
|
||||
std::uint32_t ctr = pos >> 2;
|
||||
std::uint32_t counters[4] = {ctr, ctr, ctr, ctr};
|
||||
for (int lane = 0; lane < 4; ++lane)
|
||||
{
|
||||
chacha_detail::seed_key(seeds[lane], keys[lane]);
|
||||
}
|
||||
std::uint8_t buf[4][64];
|
||||
chacha_detail::block4<Rounds>(keys, counters, buf);
|
||||
unsigned chunk = pos & 3u;
|
||||
for (int lane = 0; lane < 4; ++lane)
|
||||
{
|
||||
output[lane] = chacha_detail::load_block(buf[lane] + 16 * chunk);
|
||||
}
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x8(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos = 0) noexcept
|
||||
{
|
||||
eval_x4(seeds, output, pos);
|
||||
eval_x4(seeds + 4, output + 4, pos);
|
||||
}
|
||||
|
||||
/// Raw-bit subtractive share of `T` for party `Party` (see `prg.hpp`).
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
static auto expand(block_type seed, psnip_uint32_t pos = 0) noexcept;
|
||||
}; // struct chacha
|
||||
|
||||
/// RFC 8439 ChaCha20.
|
||||
using chacha20 = chacha<20>;
|
||||
|
||||
/// ChaCha12. Same keying as `chacha20`, 12 rounds.
|
||||
using chacha12 = chacha<12>;
|
||||
|
||||
/// ChaCha8. Same keying as `chacha20`, 8 rounds.
|
||||
using chacha8 = chacha<8>;
|
||||
|
||||
} // namespace prg
|
||||
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_PRG_CHACHA_HPP__
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
/// @file dpf/prg_dummy.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Identity PRG. `eval` returns the seed and ignores the lane.
|
||||
/// @details Used where a PRG-shaped type is required and the block must stay
|
||||
/// equal to the seed. The batched entry points write that seed into
|
||||
/// every output lane.
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
/// @license Released under a GNU General Public v2.0 (GPLv2) license;
|
||||
|
|
@ -57,6 +59,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2, 3)
|
||||
static void eval01_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT left,
|
||||
block_type * HEDLEY_RESTRICT right) noexcept
|
||||
|
|
@ -69,6 +72,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t = 0) noexcept
|
||||
{
|
||||
|
|
@ -77,6 +81,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x8(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t = 0) noexcept
|
||||
{
|
||||
|
|
@ -85,6 +90,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
/// Raw-bit subtractive share of `T` for party `Party` (see `prg.hpp`).
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
static auto expand(block_type seed, psnip_uint32_t pos = 0) noexcept;
|
||||
}; // struct dummy
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
#include "simde/simde/x86/avx2.h"
|
||||
|
|
@ -49,11 +50,15 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
|
|||
HEDLEY_PRAGMA(GCC diagnostic pop)
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static void eval(block_type seed, block_type * HEDLEY_RESTRICT output,
|
||||
psnip_uint32_t count, psnip_uint32_t pos = 0) noexcept
|
||||
psnip_uint32_t count, psnip_uint32_t pos = 0)
|
||||
{
|
||||
if (count > 1 &&
|
||||
pos > static_cast<psnip_uint32_t>(~static_cast<psnip_uint32_t>(0)) - (count - 1u))
|
||||
{
|
||||
throw std::invalid_argument("prg lane index is out of range");
|
||||
}
|
||||
for (psnip_uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
output[i] = eval(seed, pos + i);
|
||||
|
|
@ -62,6 +67,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2, 3)
|
||||
static void eval01_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT left,
|
||||
block_type * HEDLEY_RESTRICT right) noexcept
|
||||
|
|
@ -76,6 +82,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x4(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos = 0) noexcept
|
||||
{
|
||||
|
|
@ -87,6 +94,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL(1, 2)
|
||||
static void eval_x8(const block_type * HEDLEY_RESTRICT seeds,
|
||||
block_type * HEDLEY_RESTRICT output, psnip_uint32_t pos = 0) noexcept
|
||||
{
|
||||
|
|
@ -98,9 +106,11 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
/// Raw-bit subtractive share of `T` for party `Party` (see `prg.hpp`).
|
||||
template <typename T, std::size_t Party>
|
||||
HEDLEY_NO_THROW
|
||||
static auto expand(block_type seed, psnip_uint32_t pos = 0) noexcept;
|
||||
|
||||
private:
|
||||
HEDLEY_NO_THROW
|
||||
static lowmc::block to_block(block_type x) noexcept
|
||||
{
|
||||
std::uint64_t lane[2];
|
||||
|
|
@ -114,6 +124,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
return b;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static block_type from_block(const lowmc::block & b) noexcept
|
||||
{
|
||||
std::uint64_t lane[2] = {0, 0};
|
||||
|
|
@ -127,6 +138,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
return x;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static block_type permute(block_type x) noexcept
|
||||
{
|
||||
static lowmc::LowMC cipher;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ inline thread_local void (*uniform_bytes_hook)(void *, std::size_t) = nullptr;
|
|||
|
||||
template <typename T>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
bool fill_from_hook(T & buf) noexcept
|
||||
{
|
||||
if (uniform_bytes_hook == nullptr)
|
||||
|
|
@ -52,6 +53,7 @@ bool fill_from_hook(T & buf) noexcept
|
|||
/// `bool` and `enum : bool` (including `dpf::bit`) have only two valid
|
||||
/// representations. Filling them with a raw entropy byte is undefined.
|
||||
template <typename T>
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool is_boolean_representation() noexcept
|
||||
{
|
||||
using U = std::remove_cv_t<T>;
|
||||
|
|
@ -94,7 +96,8 @@ struct entropy_source
|
|||
entropy_source(entropy_source &&) = delete;
|
||||
entropy_source & operator=(entropy_source &&) = delete;
|
||||
|
||||
~entropy_source()
|
||||
HEDLEY_NO_THROW
|
||||
~entropy_source() noexcept
|
||||
{
|
||||
if (fp != nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/// @file dpf/rotated_iterable.hpp
|
||||
/// @brief Retired container rotation view. The live type is `rotation_iterable`.
|
||||
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
|
||||
/// @license Released under a GNU General Public v2.0 (GPLv2) license.
|
||||
|
||||
// /// @file dpf/rotated_iterable.hpp
|
||||
// /// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
// /// @brief defines `dpf::rotated_iterable` and associated helpers
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
/// @file dpf/rotation_iterable.hpp
|
||||
/// @brief A rotated view of an iterator range.
|
||||
/// @details `begin()` starts `distance` elements into the wrapped range and
|
||||
/// wraps back to the original begin. Indexing is O(1) when the
|
||||
/// wrapped iterator is random-access.
|
||||
/// @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_ROTATED_VIEW_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_ROTATED_VIEW_HPP__
|
||||
|
||||
|
|
@ -30,20 +38,14 @@ struct rotation_iterable
|
|||
constexpr rotation_iterable(wrapped_iterator begin, wrapped_iterator end,
|
||||
difference_type distance)
|
||||
: size_{std::distance(begin, end)},
|
||||
distance_{
|
||||
[this, &distance]()
|
||||
{
|
||||
distance %= this->size_;
|
||||
if (distance < 0)
|
||||
{
|
||||
distance += this->size_;
|
||||
}
|
||||
return distance;
|
||||
}()},
|
||||
begin_{std::next(begin, static_cast<difference_type>(distance_))},
|
||||
distance_{normalize_distance(distance, size_)},
|
||||
begin_{size_ == 0 ? begin : std::next(begin, distance_)},
|
||||
wrap_to_{begin},
|
||||
wrap_after_{std::next(end, -difference_type(distance_ > 0))},
|
||||
end_after_{std::next(wrap_to_, static_cast<difference_type>(distance_-1))},
|
||||
wrap_after_{size_ == 0 || distance_ == 0
|
||||
? end : std::next(end, difference_type{-1})},
|
||||
end_after_{size_ == 0 ? begin
|
||||
: (distance_ == 0 ? std::next(end, difference_type{-1})
|
||||
: std::next(begin, distance_ - 1))},
|
||||
end_{end}
|
||||
{ }
|
||||
|
||||
|
|
@ -52,11 +54,11 @@ struct rotation_iterable
|
|||
constexpr rotation_iterable(wrapped_iterator begin, wrapped_iterator end,
|
||||
wrapped_iterator middle)
|
||||
: size_{std::distance(begin, end)},
|
||||
distance_{std::distance(begin, middle)},
|
||||
distance_{size_ == 0 ? difference_type{0} : std::distance(begin, middle)},
|
||||
begin_{middle},
|
||||
wrap_to_{begin},
|
||||
wrap_after_{std::next(end, difference_type(-1))},
|
||||
end_after_{std::next(middle, difference_type(-1))},
|
||||
wrap_after_{size_ == 0 ? end : std::next(end, difference_type{-1})},
|
||||
end_after_{size_ == 0 ? begin : std::next(middle, difference_type{-1})},
|
||||
end_{end}
|
||||
{ }
|
||||
|
||||
|
|
@ -136,6 +138,19 @@ struct rotation_iterable
|
|||
}
|
||||
|
||||
private:
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr difference_type normalize_distance(difference_type distance,
|
||||
difference_type size) noexcept
|
||||
{
|
||||
if (size == 0)
|
||||
return difference_type{0};
|
||||
distance %= size;
|
||||
if (distance < 0)
|
||||
distance += size;
|
||||
return distance;
|
||||
}
|
||||
|
||||
difference_type size_;
|
||||
difference_type distance_;
|
||||
wrapped_iterator begin_;
|
||||
|
|
@ -163,6 +178,7 @@ struct rotation_iterator_base
|
|||
std::add_const_t<reference>>;
|
||||
using pointer = typename std::iterator_traits<WrappedIterator>::pointer;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
rotation_iterator_base(const rotation_iterable<wrapped_iterator> & iterable_,
|
||||
wrapped_iterator iterator) noexcept
|
||||
: iterable{iterable_}, it{iterator} { }
|
||||
|
|
@ -256,6 +272,7 @@ struct rotation_iterator final
|
|||
using wrapped_iterator = WrappedIterator;
|
||||
using reference = typename base::reference;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
rotation_iterator(const rotation_iterable<WrappedIterator> & iterable,
|
||||
wrapped_iterator iterator) noexcept
|
||||
: base{iterable, iterator} {}
|
||||
|
|
@ -277,6 +294,7 @@ struct rotation_const_iterator final
|
|||
using wrapped_iterator = WrappedIterator;
|
||||
using const_reference = typename base::const_reference;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
rotation_const_iterator(const rotation_iterable<WrappedIterator> & iterable,
|
||||
wrapped_iterator iterator) noexcept
|
||||
: base{iterable, iterator} {}
|
||||
|
|
|
|||
|
|
@ -99,10 +99,19 @@ namespace detail
|
|||
template <sharing Scheme, std::size_t Party, typename T>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr T party_coeff_times(const T & v) noexcept
|
||||
{
|
||||
if constexpr (Scheme == sharing::additive || Party == 0)
|
||||
return v;
|
||||
else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>)
|
||||
{
|
||||
// Signed negation of the minimum is undefined. The two's-complement
|
||||
// negation is well-defined on the unsigned width.
|
||||
using unsigned_type = std::make_unsigned_t<T>;
|
||||
return static_cast<T>(static_cast<unsigned_type>(0)
|
||||
- static_cast<unsigned_type>(v));
|
||||
}
|
||||
else
|
||||
return static_cast<T>(-v);
|
||||
}
|
||||
|
|
@ -122,13 +131,18 @@ struct secret_share
|
|||
T value{};
|
||||
|
||||
secret_share() = default;
|
||||
HEDLEY_NO_THROW
|
||||
secret_share(const secret_share &) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
secret_share(secret_share &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
secret_share & operator=(const secret_share &) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
secret_share & operator=(secret_share &&) noexcept = default;
|
||||
~secret_share() = default;
|
||||
|
||||
/// Bit-preserving construction. Does not apply a party coefficient.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
static constexpr secret_share from_raw(T v) noexcept
|
||||
|
|
@ -138,15 +152,18 @@ struct secret_share
|
|||
return s;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
constexpr const T & raw() const noexcept { return value; }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
constexpr T & raw() noexcept { return value; }
|
||||
|
||||
/// Secret-preserving conversion to an additive share of the same party.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
constexpr additive_share<T, Party> as_additive() const noexcept
|
||||
|
|
@ -159,6 +176,7 @@ struct secret_share
|
|||
}
|
||||
|
||||
/// Secret-preserving conversion to a subtractive share of the same party.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
constexpr subtractive_share<T, Party> as_subtractive() const noexcept
|
||||
|
|
@ -174,18 +192,28 @@ struct secret_share
|
|||
template <sharing NewScheme, std::size_t NewParty = Party>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, NewParty, NewScheme> retag() const noexcept
|
||||
{
|
||||
return secret_share<T, NewParty, NewScheme>::from_raw(value);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
constexpr secret_share operator-() const noexcept
|
||||
{
|
||||
return from_raw(static_cast<T>(-value));
|
||||
if constexpr (std::is_integral_v<T> && std::is_signed_v<T>)
|
||||
{
|
||||
using unsigned_type = std::make_unsigned_t<T>;
|
||||
return from_raw(static_cast<T>(static_cast<unsigned_type>(0)
|
||||
- static_cast<unsigned_type>(value)));
|
||||
}
|
||||
else
|
||||
return from_raw(static_cast<T>(-value));
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr secret_share & operator+=(const secret_share & rhs) noexcept
|
||||
{
|
||||
|
|
@ -193,6 +221,7 @@ struct secret_share
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr secret_share & operator-=(const secret_share & rhs) noexcept
|
||||
{
|
||||
|
|
@ -203,6 +232,7 @@ struct secret_share
|
|||
template <typename Scalar,
|
||||
std::enable_if_t<!is_secret_share_v<Scalar>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share & operator*=(const Scalar & c) noexcept
|
||||
{
|
||||
value = static_cast<T>(value * static_cast<T>(c));
|
||||
|
|
@ -214,6 +244,7 @@ struct secret_share
|
|||
std::enable_if_t<!is_secret_share_v<Plain>
|
||||
&& std::is_convertible_v<Plain, T>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share & operator+=(const Plain & c) noexcept
|
||||
{
|
||||
if constexpr (Party == 0)
|
||||
|
|
@ -225,6 +256,7 @@ struct secret_share
|
|||
std::enable_if_t<!is_secret_share_v<Plain>
|
||||
&& std::is_convertible_v<Plain, T>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share & operator-=(const Plain & c) noexcept
|
||||
{
|
||||
if constexpr (Party == 0)
|
||||
|
|
@ -240,6 +272,7 @@ struct secret_share
|
|||
template <typename T, std::size_t Party, sharing Scheme>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, Scheme> operator+(
|
||||
secret_share<T, Party, Scheme> lhs,
|
||||
const secret_share<T, Party, Scheme> & rhs) noexcept
|
||||
|
|
@ -251,6 +284,7 @@ constexpr secret_share<T, Party, Scheme> operator+(
|
|||
template <typename T, std::size_t Party, sharing Scheme>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, Scheme> operator-(
|
||||
secret_share<T, Party, Scheme> lhs,
|
||||
const secret_share<T, Party, Scheme> & rhs) noexcept
|
||||
|
|
@ -263,6 +297,7 @@ template <typename T, std::size_t Party, sharing Scheme, typename Scalar,
|
|||
std::enable_if_t<!is_secret_share_v<Scalar>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, Scheme> operator*(
|
||||
secret_share<T, Party, Scheme> lhs, const Scalar & c) noexcept
|
||||
{
|
||||
|
|
@ -274,6 +309,7 @@ template <typename T, std::size_t Party, sharing Scheme, typename Scalar,
|
|||
std::enable_if_t<!is_secret_share_v<Scalar>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, Scheme> operator*(
|
||||
const Scalar & c, secret_share<T, Party, Scheme> rhs) noexcept
|
||||
{
|
||||
|
|
@ -290,6 +326,7 @@ template <typename T, std::size_t Party, sharing LhsScheme, sharing RhsScheme,
|
|||
std::enable_if_t<LhsScheme != RhsScheme, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, LhsScheme> operator+(
|
||||
const secret_share<T, Party, LhsScheme> & lhs,
|
||||
const secret_share<T, Party, RhsScheme> & rhs) noexcept
|
||||
|
|
@ -306,6 +343,7 @@ template <typename T, std::size_t Party, sharing LhsScheme, sharing RhsScheme,
|
|||
std::enable_if_t<LhsScheme != RhsScheme, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, LhsScheme> operator-(
|
||||
const secret_share<T, Party, LhsScheme> & lhs,
|
||||
const secret_share<T, Party, RhsScheme> & rhs) noexcept
|
||||
|
|
@ -327,6 +365,7 @@ template <typename T, std::size_t Party, sharing Scheme, typename Plain,
|
|||
&& std::is_convertible_v<Plain, T>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, Scheme> operator+(
|
||||
secret_share<T, Party, Scheme> lhs, const Plain & c) noexcept
|
||||
{
|
||||
|
|
@ -339,6 +378,7 @@ template <typename T, std::size_t Party, sharing Scheme, typename Plain,
|
|||
&& std::is_convertible_v<Plain, T>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, Scheme> operator+(
|
||||
const Plain & c, secret_share<T, Party, Scheme> rhs) noexcept
|
||||
{
|
||||
|
|
@ -351,6 +391,7 @@ template <typename T, std::size_t Party, sharing Scheme, typename Plain,
|
|||
&& std::is_convertible_v<Plain, T>, int> = 0>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr secret_share<T, Party, Scheme> operator-(
|
||||
secret_share<T, Party, Scheme> lhs, const Plain & c) noexcept
|
||||
{
|
||||
|
|
@ -365,6 +406,7 @@ constexpr secret_share<T, Party, Scheme> operator-(
|
|||
template <typename T, std::size_t Party, sharing Scheme>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator==(const secret_share<T, Party, Scheme> & lhs,
|
||||
const secret_share<T, Party, Scheme> & rhs) noexcept
|
||||
{
|
||||
|
|
@ -374,6 +416,7 @@ constexpr bool operator==(const secret_share<T, Party, Scheme> & lhs,
|
|||
template <typename T, std::size_t Party, sharing Scheme>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr bool operator!=(const secret_share<T, Party, Scheme> & lhs,
|
||||
const secret_share<T, Party, Scheme> & rhs) noexcept
|
||||
{
|
||||
|
|
@ -387,10 +430,21 @@ constexpr bool operator!=(const secret_share<T, Party, Scheme> & lhs,
|
|||
template <typename T, sharing Scheme>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr T reconstruct(const secret_share<T, 0, Scheme> & s0,
|
||||
const secret_share<T, 1, Scheme> & s1) noexcept
|
||||
{
|
||||
if constexpr (Scheme == sharing::additive)
|
||||
if constexpr (std::is_integral_v<T> && std::is_signed_v<T>)
|
||||
{
|
||||
using unsigned_type = std::make_unsigned_t<T>;
|
||||
if constexpr (Scheme == sharing::additive)
|
||||
return static_cast<T>(static_cast<unsigned_type>(s0.raw())
|
||||
+ static_cast<unsigned_type>(s1.raw()));
|
||||
else
|
||||
return static_cast<T>(static_cast<unsigned_type>(s0.raw())
|
||||
- static_cast<unsigned_type>(s1.raw()));
|
||||
}
|
||||
else if constexpr (Scheme == sharing::additive)
|
||||
return static_cast<T>(s0.raw() + s1.raw());
|
||||
else
|
||||
return static_cast<T>(s0.raw() - s1.raw());
|
||||
|
|
@ -399,6 +453,7 @@ constexpr T reconstruct(const secret_share<T, 0, Scheme> & s0,
|
|||
template <typename T, sharing Scheme>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr T reconstruct(const secret_share<T, 1, Scheme> & s1,
|
||||
const secret_share<T, 0, Scheme> & s0) noexcept
|
||||
{
|
||||
|
|
@ -412,6 +467,7 @@ constexpr T reconstruct(const secret_share<T, 1, Scheme> & s1,
|
|||
template <typename T>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
constexpr auto make_additive_shares(T secret) noexcept
|
||||
{
|
||||
using T_ = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
|
@ -423,6 +479,7 @@ constexpr auto make_additive_shares(T secret) noexcept
|
|||
template <typename T>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
constexpr auto make_subtractive_shares(T secret) noexcept
|
||||
{
|
||||
using T_ = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
|
@ -460,13 +517,16 @@ struct party_key : Key
|
|||
#endif
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
Key & key() noexcept { return static_cast<Key &>(*this); }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
const Key & key() const noexcept { return static_cast<const Key &>(*this); }
|
||||
|
||||
/// Party-tagged additive share of the comparison absorb addend.
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
auto cmp_addend() const noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
/// @file dpf/sequence_memoizer.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Workspaces for a `sequence_recipe` traversal.
|
||||
/// @details The memoizer stores a reference to the recipe it was built from
|
||||
/// and later calls must pass that same object (`std::logic_error`
|
||||
/// otherwise). The factories unwrap `party_key`.
|
||||
///
|
||||
/// `inplace_reversing_sequence_memoizer` keeps one level.
|
||||
/// `double_space_sequence_memoizer` keeps two and is the default
|
||||
/// inside `eval_sequence(key, recipe, buffer)`.
|
||||
/// `full_tree_sequence_memoizer` keeps every level.
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -22,6 +29,7 @@
|
|||
#include <stdexcept>
|
||||
#include <optional>
|
||||
|
||||
#include "dpf/secret_share.hpp"
|
||||
#include "dpf/sequence_recipe.hpp"
|
||||
|
||||
namespace dpf
|
||||
|
|
@ -42,10 +50,13 @@ struct sequence_recipe_memoizer_base : public sequence_memoizer_tag_
|
|||
|
||||
// level 0 should access the root
|
||||
// level goes up to (and including) depth
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type operator[](std::size_t) const noexcept = 0;
|
||||
|
||||
// iterators should access most recently completed level
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type begin() const noexcept = 0;
|
||||
HEDLEY_NO_THROW
|
||||
virtual return_type end() const noexcept = 0;
|
||||
|
||||
virtual std::size_t assign_dpf(const dpf_type & dpf, const sequence_recipe & r)
|
||||
|
|
@ -210,11 +221,13 @@ struct pointer_facade
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
pointer_facade operator+(std::size_t n) const noexcept
|
||||
{
|
||||
return pointer_facade(flip_, it_ + n, rit_ + n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
pointer_facade & operator-=(std::size_t n) noexcept
|
||||
{
|
||||
it_ -= n;
|
||||
|
|
@ -222,11 +235,13 @@ struct pointer_facade
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
pointer_facade operator-(std::size_t n) const noexcept
|
||||
{
|
||||
return pointer_facade(flip_, it_ - n, rit_ - n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
difference_type operator-(pointer_facade rhs) const noexcept
|
||||
{
|
||||
return std::make_pair(it_ - rhs.it_, rit_ - rhs.rit_);
|
||||
|
|
@ -235,7 +250,7 @@ struct pointer_facade
|
|||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
reference operator[](std::size_t i)
|
||||
reference operator[](std::size_t i) noexcept
|
||||
{
|
||||
return flip_ ? rit_[i] : it_[i];
|
||||
}
|
||||
|
|
@ -243,7 +258,7 @@ struct pointer_facade
|
|||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
const_reference operator[](std::size_t i) const
|
||||
const_reference operator[](std::size_t i) const noexcept
|
||||
{
|
||||
return flip_ ? rit_[i] : it_[i];
|
||||
}
|
||||
|
|
@ -270,6 +285,8 @@ struct pointer_facade
|
|||
|
||||
} // namespace detail
|
||||
|
||||
/// One level. The buffer is traversed in the opposite direction on
|
||||
/// alternate levels.
|
||||
template <typename DpfKey,
|
||||
typename Allocator = aligned_allocator<typename DpfKey::interior_node>>
|
||||
struct inplace_reversing_sequence_memoizer final
|
||||
|
|
@ -364,6 +381,8 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
unique_ptr buf;
|
||||
};
|
||||
|
||||
/// Two levels, so a level can be built while the previous level is still
|
||||
/// intact. Default workspace for `eval_sequence` on a recipe.
|
||||
template <typename DpfKey,
|
||||
typename Allocator = aligned_allocator<typename DpfKey::interior_node>>
|
||||
struct double_space_sequence_memoizer final
|
||||
|
|
@ -416,6 +435,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
unique_ptr buf;
|
||||
};
|
||||
|
||||
/// Every level of the recipe's traversal.
|
||||
template <typename DpfKey,
|
||||
typename Allocator = aligned_allocator<typename DpfKey::interior_node>>
|
||||
struct full_tree_sequence_memoizer final
|
||||
|
|
@ -482,10 +502,15 @@ auto make_sequence_memoizer(const sequence_recipe & recipe)
|
|||
|
||||
HEDLEY_PRAGMA(GCC diagnostic push)
|
||||
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
|
||||
/// One-level sequence workspace bound to `recipe`.
|
||||
/// @param recipe The object later passed to `eval_sequence`. The memoizer
|
||||
/// holds a reference to it.
|
||||
/// @snippet evaluation/memoizers.cpp sequence-memoizer
|
||||
template <typename DpfKey>
|
||||
inline auto make_inplace_reversing_sequence_memoizer(const sequence_recipe & recipe)
|
||||
{
|
||||
return detail::make_sequence_memoizer<inplace_reversing_sequence_memoizer<DpfKey>>(recipe);
|
||||
using key_t = unwrap_party_key_t<DpfKey>;
|
||||
return detail::make_sequence_memoizer<inplace_reversing_sequence_memoizer<key_t>>(recipe);
|
||||
}
|
||||
|
||||
template <typename DpfKey>
|
||||
|
|
@ -494,10 +519,13 @@ inline auto make_inplace_reversing_sequence_memoizer(const DpfKey &, const seque
|
|||
return make_inplace_reversing_sequence_memoizer<DpfKey>(recipe);
|
||||
}
|
||||
|
||||
/// Two-level sequence workspace bound to `recipe`.
|
||||
/// @snippet evaluation/eval_sequence.cpp eval-sequence-recipe
|
||||
template <typename DpfKey>
|
||||
inline auto make_double_space_sequence_memoizer(const sequence_recipe & recipe)
|
||||
{
|
||||
return detail::make_sequence_memoizer<double_space_sequence_memoizer<DpfKey>>(recipe);
|
||||
using key_t = unwrap_party_key_t<DpfKey>;
|
||||
return detail::make_sequence_memoizer<double_space_sequence_memoizer<key_t>>(recipe);
|
||||
}
|
||||
|
||||
template <typename DpfKey>
|
||||
|
|
@ -506,10 +534,12 @@ inline auto make_double_space_sequence_memoizer(const DpfKey &, const sequence_r
|
|||
return make_double_space_sequence_memoizer<DpfKey>(recipe);
|
||||
}
|
||||
|
||||
/// Full-tree sequence workspace bound to `recipe`.
|
||||
template <typename DpfKey>
|
||||
inline auto make_full_tree_sequence_memoizer(const sequence_recipe & recipe)
|
||||
{
|
||||
return detail::make_sequence_memoizer<full_tree_sequence_memoizer<DpfKey>>(recipe);
|
||||
using key_t = unwrap_party_key_t<DpfKey>;
|
||||
return detail::make_sequence_memoizer<full_tree_sequence_memoizer<key_t>>(recipe);
|
||||
}
|
||||
|
||||
template <typename DpfKey>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
/// @file dpf/sequence_recipe.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Compiled traversal of a sorted DPF point list.
|
||||
/// @details `make_sequence_recipe` requires a nondecreasing range and throws
|
||||
/// `std::runtime_error` otherwise. The recipe is independent of
|
||||
/// correction words, so one recipe serves every key of that input
|
||||
/// type. A sequence memoizer is bound to a particular recipe object.
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @author Christopher Jiang <christopher.jiang@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2024 Ryan Henry and [others](@ref authors)
|
||||
|
|
@ -10,6 +13,8 @@
|
|||
#ifndef LIBDPF_INCLUDE_DPF_SEQUENCE_RECIPE_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_SEQUENCE_RECIPE_HPP__
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
|
|
@ -21,6 +26,7 @@
|
|||
namespace dpf
|
||||
{
|
||||
|
||||
/// Steps, leaf count, and per-level endpoints for one sorted point list.
|
||||
struct sequence_recipe
|
||||
{
|
||||
public:
|
||||
|
|
@ -34,10 +40,21 @@ struct sequence_recipe
|
|||
level_endpoints_{level_endpoints}
|
||||
{ }
|
||||
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const std::vector<int8_t> & recipe_steps() const noexcept { return recipe_steps_; }
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const std::vector<std::size_t> & output_indices() const noexcept { return output_indices_; }
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr std::size_t num_leaf_nodes() const noexcept { return num_leaf_nodes_; }
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr const std::vector<std::size_t> & level_endpoints() const noexcept { return level_endpoints_; }
|
||||
/// `level_endpoints().size() - 1`. Not `constexpr`: `std::vector::size` is not a constant expression in C++17.
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t depth() const noexcept { return level_endpoints_.size()-1; }
|
||||
|
||||
private:
|
||||
|
|
@ -122,6 +139,10 @@ auto make_sequence_recipe(ForwardIterator begin, ForwardIterator end)
|
|||
|
||||
} // namespace detail
|
||||
|
||||
/// Compile `[begin, end)` into a recipe for `DpfKey`'s input type.
|
||||
/// @tparam DpfKey Key type, or a `party_key` of that key. Only the input
|
||||
/// type and depth are used.
|
||||
/// @throws std::runtime_error if the range is not sorted nondecreasing.
|
||||
template <typename DpfKey,
|
||||
typename ForwardIterator>
|
||||
auto make_sequence_recipe(ForwardIterator begin, ForwardIterator end)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,23 @@
|
|||
/// @file dpf/sequence_utils.hpp
|
||||
/// @brief Tags that select how `eval_sequence` stores each visited leaf.
|
||||
/// @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_SEQUENCE_UTILS_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_SEQUENCE_UTILS_HPP__
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
|
||||
/// Tag base for `eval_sequence` storage layout.
|
||||
struct return_type_tag_{};
|
||||
|
||||
/// Store whole leaves. Default for `eval_sequence`. The iterable still
|
||||
/// yields one share per listed point.
|
||||
struct return_entire_node_tag_ final : public return_type_tag_ {};
|
||||
// static constexpr auto return_entire_node_tag = return_entire_node_tag_{};
|
||||
|
||||
/// Store one share per listed point.
|
||||
struct return_output_only_tag_ final : public return_type_tag_ {};
|
||||
// static constexpr auto return_output_only_tag = return_output_only_tag_{};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ class setbit_index_iterable
|
|||
explicit setbit_index_iterable(iter it) noexcept
|
||||
: it_{std::move(it)},
|
||||
begin_{it_.it_.word_ptr_},
|
||||
end_{begin_ + it_.buf_size_},
|
||||
// `buf_size_` is a bit count (`bit_array::size()`). The sentinel word
|
||||
// sits one past the last data word, and the end iterator has to land
|
||||
// on it rather than `buf_size_` words later.
|
||||
end_{begin_ + utils::quotient_ceiling(it_.buf_size_, bits_per_word)},
|
||||
base_index_{calc_base_index(it_)},
|
||||
length_{calc_length(it_)}
|
||||
{
|
||||
|
|
@ -89,6 +92,7 @@ class setbit_index_iterable
|
|||
return it.outputs_ == 0 ? it.from_ : utils::quotient_floor(it.from_, it.outputs_) * it.outputs_;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr size_type calc_length(const iter & it) noexcept
|
||||
{
|
||||
return it.outputs_ == 0 ? utils::quotient_ceiling(it.to_, bits_per_word) * bits_per_word : utils::quotient_ceiling(it.to_, it.outputs_) * it.outputs_;
|
||||
|
|
@ -102,7 +106,7 @@ class setbit_index_iterable
|
|||
// while other words just need some bits to be masked out
|
||||
constexpr void update_bit_array()
|
||||
{
|
||||
if (it_.outputs_ == 0)
|
||||
if (it_.outputs_ == 0 || begin_ == end_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -124,11 +128,16 @@ class setbit_index_iterable
|
|||
cur = end_-1;
|
||||
loc = it_.to_ % it_.outputs_;
|
||||
|
||||
while (loc < it_.outputs_ - bits_per_word)
|
||||
// `outputs_ - bits_per_word` underflows when a leaf is narrower than
|
||||
// a word, and the loop then walks off the front of the buffer.
|
||||
if (it_.outputs_ > bits_per_word)
|
||||
{
|
||||
*cur = zero;
|
||||
--cur;
|
||||
loc += bits_per_word;
|
||||
while (loc < it_.outputs_ - bits_per_word)
|
||||
{
|
||||
*cur = zero;
|
||||
--cur;
|
||||
loc += bits_per_word;
|
||||
}
|
||||
}
|
||||
*cur &= mask;
|
||||
}
|
||||
|
|
@ -151,12 +160,16 @@ class const_setbit_iterator
|
|||
using difference_type = std::ptrdiff_t;
|
||||
static constexpr auto bits_per_word = array_type::bits_per_word;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_setbit_iterator(const_setbit_iterator &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_setbit_iterator(const const_setbit_iterator &) noexcept = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
~const_setbit_iterator() noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
const_setbit_iterator & operator=(const_setbit_iterator &&) noexcept = default;
|
||||
const_setbit_iterator & operator=(const const_setbit_iterator &) = default;
|
||||
|
||||
|
|
@ -279,6 +292,7 @@ class const_setbit_iterator
|
|||
struct const_iterator_end_tag final {};
|
||||
struct const_iterator_begin_tag final {};
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL()
|
||||
explicit constexpr const_setbit_iterator(word_pointer word_ptr,
|
||||
|
|
@ -290,6 +304,7 @@ class const_setbit_iterator
|
|||
seek_to_next_bit();
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NON_NULL()
|
||||
explicit constexpr const_setbit_iterator(word_pointer word_ptr,
|
||||
|
|
@ -303,13 +318,16 @@ class const_setbit_iterator
|
|||
word_type current_word_;
|
||||
size_type base_index_;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
friend const_setbit_iterator setbit_index_iterable<ChildT, WordT>::begin() const noexcept;
|
||||
HEDLEY_NO_THROW
|
||||
friend const_setbit_iterator setbit_index_iterable<ChildT, WordT>::end() const noexcept;
|
||||
}; // class dpf::const_setbit_iterator
|
||||
|
||||
template <typename ChildT,
|
||||
typename WordT>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
dpf::setbit_index_iterable<ChildT, WordT> indices_set_in(const subinterval_iterable<bit_iterator<ChildT, WordT>> & iter) noexcept
|
||||
{
|
||||
return dpf::setbit_index_iterable<ChildT, WordT>{iter};
|
||||
|
|
@ -318,6 +336,7 @@ dpf::setbit_index_iterable<ChildT, WordT> indices_set_in(const subinterval_itera
|
|||
template <typename ChildT,
|
||||
typename WordT>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
dpf::setbit_index_iterable<ChildT, WordT> indices_set_in(subinterval_iterable<bit_iterator<ChildT, WordT>> && iter) noexcept
|
||||
{
|
||||
return dpf::setbit_index_iterable<ChildT, WordT>{std::forward<subinterval_iterable<bit_iterator<ChildT, WordT>>>(iter)};
|
||||
|
|
|
|||
|
|
@ -80,16 +80,20 @@ class subsequence_iterable
|
|||
|
||||
using subsequence_iterator_type = points_iterator;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_iterator(output_iterator out_it, subsequence_iterator_type it) noexcept
|
||||
: out_it_{out_it}, it_{it}
|
||||
{ }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_iterator(const_iterator &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_iterator(const const_iterator &) noexcept = default;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator & operator=(const_iterator &&) noexcept = default;
|
||||
const_iterator & operator=(const const_iterator &) = default;
|
||||
~const_iterator() = default;
|
||||
|
|
@ -143,11 +147,13 @@ class subsequence_iterable
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator operator+(std::size_t n) const noexcept
|
||||
{
|
||||
return const_iterator(out_it_ + outputs_per_leaf*n, it_ + n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator & operator-=(std::size_t n) noexcept
|
||||
{
|
||||
it_ -= n;
|
||||
|
|
@ -155,16 +161,19 @@ class subsequence_iterable
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator operator-(std::size_t n) const noexcept
|
||||
{
|
||||
return const_iterator(out_it_ - outputs_per_leaf*n, it_ - n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
difference_type operator-(const_iterator rhs) const noexcept
|
||||
{
|
||||
return it_ - rhs.it_;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
reference operator[](std::size_t i) const noexcept
|
||||
{
|
||||
return out_it_[i*outputs_per_leaf + mod(it_[i], lg_outputs_per_leaf)];
|
||||
|
|
@ -279,17 +288,21 @@ class recipe_subsequence_iterable
|
|||
|
||||
using subsequence_iterator_type = typename std::vector<std::size_t>::const_iterator;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_iterator(output_iterator out_it, subsequence_iterator_type it) noexcept
|
||||
: out_it_{out_it}, it_{it}
|
||||
{ }
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_iterator(const_iterator &&) noexcept = default;
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr const_iterator(const const_iterator &) noexcept = default;
|
||||
|
||||
const_iterator & operator=(const const_iterator &) = default;
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator & operator=(const_iterator &&) noexcept = default;
|
||||
~const_iterator() = default;
|
||||
|
||||
|
|
@ -339,27 +352,32 @@ class recipe_subsequence_iterable
|
|||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator operator+(std::size_t n) const noexcept
|
||||
{
|
||||
return const_iterator(out_it_, it_ + n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator & operator-=(std::size_t n) noexcept
|
||||
{
|
||||
it_ -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
const_iterator operator-(std::size_t n) const noexcept
|
||||
{
|
||||
return const_iterator(out_it_, it_ - n);
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
difference_type operator-(const_iterator rhs) const noexcept
|
||||
{
|
||||
return it_ - rhs.it_;
|
||||
}
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
reference operator[](std::size_t i) const noexcept
|
||||
{
|
||||
return out_it_[it_[i]];
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ template <>
|
|||
struct make_from_integral_value<dpf::twobit>
|
||||
{
|
||||
using integral_type = std::uint8_t;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr dpf::twobit operator()(integral_type val) const noexcept
|
||||
{
|
||||
return dpf::to_twobit(val);
|
||||
|
|
@ -184,8 +185,11 @@ class numeric_limits<dpf::twobit> : public numeric_limits<std::uint8_t>
|
|||
public:
|
||||
static constexpr int digits = 2;
|
||||
static constexpr int digits10 = 0;
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::twobit min() noexcept { return dpf::twobit::zero; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::twobit max() noexcept { return dpf::twobit::three; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr dpf::twobit lowest() noexcept { return min(); }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/// @file dpf/uint256_t.hpp
|
||||
/// @brief Leaf arithmetic for `uint256_t` and the 128-bit SIMD lanes.
|
||||
/// @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_UINT256_T_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_UINT256_T_HPP__
|
||||
|
||||
|
|
@ -205,6 +210,7 @@ struct msb_of<uint256_t>
|
|||
template <>
|
||||
struct mod_pow_2<uint128_t>
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t operator()(uint128_t val, std::size_t n) const noexcept
|
||||
{
|
||||
return mod_pow_2<uint64_t>{}(static_cast<uint64_t>(val.lower()), n);
|
||||
|
|
@ -214,6 +220,7 @@ struct mod_pow_2<uint128_t>
|
|||
template <>
|
||||
struct mod_pow_2<uint256_t>
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t operator()(uint256_t val, std::size_t n) const noexcept
|
||||
{
|
||||
return mod_pow_2<uint128_t>{}(val.lower(), n);
|
||||
|
|
@ -227,6 +234,7 @@ struct to_integral_type<uint128_t>
|
|||
using parent = to_integral_type_base<uint128_t>;
|
||||
using typename parent::integral_type;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
constexpr integral_type operator()(uint128_t val) const noexcept
|
||||
{
|
||||
return (simde_uint128(val.upper()) << 64) | simde_uint128(val.lower());
|
||||
|
|
@ -240,6 +248,7 @@ struct to_integral_type<uint256_t>
|
|||
using parent = to_integral_type_base<uint256_t>;
|
||||
using typename parent::integral_type;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
constexpr integral_type operator()(uint256_t val) const noexcept
|
||||
{
|
||||
return val;
|
||||
|
|
|
|||
|
|
@ -69,14 +69,23 @@ class numeric_limits<::uint128_t>
|
|||
static constexpr bool traps = false;
|
||||
static constexpr bool tinyness_before = false;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t min() noexcept { return uint128_t{0ul, 0ul}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t lowest() noexcept { return uint128_t{0ul, 0ul}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t max() noexcept { return uint128_t{-1ul, -1ul}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t epsilon() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t round_error() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t infinity() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t quiet_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t signaling_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint128_t denorm_min() noexcept { return 0; }
|
||||
};
|
||||
|
||||
|
|
@ -127,14 +136,23 @@ class numeric_limits<::uint256_t>
|
|||
static constexpr bool traps = false;
|
||||
static constexpr bool tinyness_before = false;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t min() noexcept { return uint256_t{uint128_t{0ul, 0ul}, uint128_t{0ul, 0ul}}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t lowest() noexcept { return uint256_t{uint128_t{0ul, 0ul}, uint128_t{0ul, 0ul}}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t max() noexcept { return uint256_t{uint128_t{-1ul, -1ul}, uint128_t{-1ul, -1ul}}; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t epsilon() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t round_error() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t infinity() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t quiet_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t signaling_NaN() noexcept { return 0; }
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr uint256_t denorm_min() noexcept { return 0; }
|
||||
};
|
||||
|
||||
|
|
@ -266,6 +284,7 @@ auto make_bitset(Bools ...bs)
|
|||
}
|
||||
|
||||
template <typename NodeT>
|
||||
HEDLEY_NO_THROW
|
||||
static NodeT single_bit_mask(std::size_t i) noexcept;
|
||||
|
||||
template <>
|
||||
|
|
@ -449,6 +468,7 @@ struct make_from_integral_value
|
|||
// for `unsigned __int128`.
|
||||
using integral_type = typename make_signed_if<S_integral_type,
|
||||
std::is_signed_v<T> && sizeof(S_integral_type) <= 8>::type;
|
||||
HEDLEY_NO_THROW
|
||||
constexpr T operator()(integral_type val) const noexcept
|
||||
{
|
||||
return static_cast<T>(val);
|
||||
|
|
@ -459,6 +479,7 @@ struct make_from_integral_value
|
|||
/// `static_cast<T>(x0 ^ x1)`: for `keyword`, `operator^` yields the parent
|
||||
/// `modint`, which cannot convert back through the private keyword ctor.
|
||||
template <typename T>
|
||||
HEDLEY_NO_THROW
|
||||
constexpr T xor_input_shares(T x0, T x1) noexcept
|
||||
{
|
||||
constexpr auto to_int = to_integral_type<T>{};
|
||||
|
|
@ -490,6 +511,7 @@ static constexpr IntegralT get_node_mask(InputT mask, std::size_t level_index)
|
|||
/// width is undefined for the native unsigned types).
|
||||
template <typename IntegralT>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr IntegralT shift_right(IntegralT value, std::size_t offset) noexcept
|
||||
{
|
||||
if (offset >= bitlength_of_v<IntegralT>)
|
||||
|
|
@ -500,6 +522,7 @@ constexpr IntegralT shift_right(IntegralT value, std::size_t offset) noexcept
|
|||
/// Floor of `from_inclusive / 2^lg_opl`. `lg_opl` is `log2(outputs_per_leaf)`.
|
||||
template <typename IntegralT>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr IntegralT leaf_node_floor(IntegralT from_inclusive, std::size_t lg_opl) noexcept
|
||||
{
|
||||
if (lg_opl == 0)
|
||||
|
|
@ -514,6 +537,7 @@ constexpr IntegralT leaf_node_floor(IntegralT from_inclusive, std::size_t lg_opl
|
|||
/// end (`[from, 2^width)`), which `split_leaf_nodes` interprets.
|
||||
template <typename IntegralT>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr IntegralT leaf_node_ceil_exclusive(IntegralT to_inclusive, std::size_t lg_opl) noexcept
|
||||
{
|
||||
constexpr std::size_t width = bitlength_of_v<IntegralT>;
|
||||
|
|
@ -585,25 +609,87 @@ struct node_segments
|
|||
std::size_t total = 0;
|
||||
};
|
||||
|
||||
/// True when the inclusive walk `[from, to]` wraps the low `bits` of the
|
||||
/// domain. Comparison is on the post-MSB-flip bit pattern. Leaf ids alone
|
||||
/// cannot carry this: packing can put a wrapping pair into `from_node <= to_node`.
|
||||
template <typename IntegralT>
|
||||
inline bool interval_wraps(IntegralT from, IntegralT to, std::size_t bits)
|
||||
{
|
||||
if (bits == 0)
|
||||
return false;
|
||||
if (bits < bitlength_of_v<IntegralT>)
|
||||
{
|
||||
const IntegralT mask = static_cast<IntegralT>(
|
||||
(IntegralT{1} << bits) - IntegralT{1});
|
||||
return (from & mask) > (to & mask);
|
||||
}
|
||||
return from > to;
|
||||
}
|
||||
|
||||
/// Split an inclusive output interval, already reduced to leaf ids, into one
|
||||
/// or two half-open walks. A linearized `from_node > to_node` wraps the node
|
||||
/// id space `[0, 2^depth)`. A saturated `to_node == 0` means the exclusive end
|
||||
/// is `2^{bitwidth(IntegralT)}`, which is the whole id space when `depth` is
|
||||
/// that width.
|
||||
///
|
||||
/// `input_wraps` is the order of the original inputs, before leaf coarsening.
|
||||
/// The buffer is still two runs, `[from_node, 2^depth)` then `[0, to_node)`,
|
||||
/// even when packing makes `from_node <= to_node`. In that case the runs
|
||||
/// overlap on the shared leaf: the iterable's preclip consumes the start of
|
||||
/// the first copy and its length stops inside the second. Collapsing the
|
||||
/// overlap into one forward segment writes the wrong leaves.
|
||||
template <typename IntegralT>
|
||||
inline node_segments<IntegralT> split_leaf_nodes(IntegralT from_node,
|
||||
IntegralT to_node, std::size_t depth)
|
||||
IntegralT to_node, std::size_t depth, bool input_wraps = false)
|
||||
{
|
||||
node_segments<IntegralT> out;
|
||||
constexpr std::size_t width = bitlength_of_v<IntegralT>;
|
||||
constexpr std::size_t size_digits = bitlength_of_v<std::size_t>;
|
||||
auto push = [&](IntegralT lo, IntegralT hi)
|
||||
{
|
||||
const std::size_t count = static_cast<std::size_t>(hi - lo);
|
||||
std::size_t count = 0;
|
||||
if (hi == IntegralT{0} && lo != IntegralT{0})
|
||||
{
|
||||
// Exclusive end is 2^width. The count fits in size_t only when
|
||||
// that power is one past size_t's maximum and lo is nonzero.
|
||||
if (width > size_digits)
|
||||
throw std::length_error("DPF leaf domain does not fit in size_t");
|
||||
count = static_cast<std::size_t>(0) - static_cast<std::size_t>(lo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto wide = hi - lo;
|
||||
if (wide > IntegralT(std::numeric_limits<std::size_t>::max()))
|
||||
throw std::length_error("DPF leaf domain does not fit in size_t");
|
||||
count = static_cast<std::size_t>(wide);
|
||||
}
|
||||
if (count == 0)
|
||||
return;
|
||||
if (out.total > std::numeric_limits<std::size_t>::max() - count)
|
||||
throw std::length_error("DPF leaf domain does not fit in size_t");
|
||||
out.seg[out.n++] = node_segment<IntegralT>{lo, hi, count};
|
||||
out.total += count;
|
||||
};
|
||||
|
||||
if (input_wraps)
|
||||
{
|
||||
if (depth >= width)
|
||||
{
|
||||
if (from_node == IntegralT{0})
|
||||
throw std::length_error("DPF leaf domain does not fit in size_t");
|
||||
push(from_node, IntegralT{0});
|
||||
if (to_node != IntegralT{0})
|
||||
push(IntegralT{0}, to_node);
|
||||
return out;
|
||||
}
|
||||
const IntegralT domain_end = static_cast<IntegralT>(IntegralT{1} << depth);
|
||||
if (from_node < domain_end)
|
||||
push(from_node, domain_end);
|
||||
if (to_node != IntegralT{0})
|
||||
push(IntegralT{0}, to_node);
|
||||
return out;
|
||||
}
|
||||
|
||||
if (to_node != IntegralT{0} && from_node < to_node)
|
||||
{
|
||||
push(from_node, to_node);
|
||||
|
|
@ -612,7 +698,6 @@ inline node_segments<IntegralT> split_leaf_nodes(IntegralT from_node,
|
|||
if (to_node != IntegralT{0} && from_node == to_node)
|
||||
return out;
|
||||
|
||||
constexpr std::size_t width = bitlength_of_v<IntegralT>;
|
||||
if (from_node == IntegralT{0} && to_node == IntegralT{0})
|
||||
throw std::length_error("DPF leaf domain does not fit in size_t");
|
||||
|
||||
|
|
@ -638,14 +723,26 @@ static constexpr std::size_t get_leafnodes_in_node_interval(IntegralT from_node,
|
|||
return static_cast<std::size_t>(to_node - from_node);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void flip_msb_if_signed_integral(T & x);
|
||||
|
||||
template <typename DpfKey,
|
||||
typename InputT = typename DpfKey::input_type,
|
||||
typename IntegralT = typename DpfKey::integral_type>
|
||||
static std::size_t get_leafnodes_in_output_interval(InputT from, InputT to)
|
||||
{
|
||||
return split_leaf_nodes(get_from_node<DpfKey, InputT, IntegralT>(from),
|
||||
get_to_node<DpfKey, InputT, IntegralT>(to),
|
||||
static_cast<std::size_t>(DpfKey::depth)).total;
|
||||
// Match eval: the walk order is the bit pattern after the sign flip.
|
||||
InputT flipped_from = from;
|
||||
InputT flipped_to = to;
|
||||
flip_msb_if_signed_integral(flipped_from);
|
||||
flip_msb_if_signed_integral(flipped_to);
|
||||
constexpr auto to_int = to_integral_type<InputT>{};
|
||||
const auto from_i = static_cast<IntegralT>(to_int(flipped_from));
|
||||
const auto to_i = static_cast<IntegralT>(to_int(flipped_to));
|
||||
const bool wraps = interval_wraps(from_i, to_i, bitlength_of_v<InputT>);
|
||||
return split_leaf_nodes(get_from_node<DpfKey, InputT, IntegralT>(flipped_from),
|
||||
get_to_node<DpfKey, InputT, IntegralT>(flipped_to),
|
||||
static_cast<std::size_t>(DpfKey::depth), wraps).total;
|
||||
}
|
||||
|
||||
/// Historical name used by the test suite.
|
||||
|
|
@ -660,6 +757,7 @@ static std::size_t get_nodes_in_interval(InputT from, InputT to)
|
|||
template <typename T>
|
||||
struct mod_pow_2
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t operator()(T val, std::size_t n) const noexcept
|
||||
{
|
||||
if (n == 0)
|
||||
|
|
@ -696,6 +794,7 @@ static constexpr auto msb_of_v = msb_of<T>::value;
|
|||
template <typename T>
|
||||
struct countl_zero
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(T val) const noexcept
|
||||
|
|
@ -724,6 +823,7 @@ struct countl_zero
|
|||
template <typename T>
|
||||
struct countr_zero
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(T val) const noexcept
|
||||
|
|
@ -756,6 +856,7 @@ struct countr_zero
|
|||
template <typename T>
|
||||
struct countl_zero_symmetric_difference
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_CONST
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(T lhs, T rhs) const noexcept
|
||||
|
|
@ -773,6 +874,7 @@ struct countl_zero<simde_int128>
|
|||
{
|
||||
using T = simde_int128;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -795,6 +897,7 @@ struct countl_zero<simde_uint128>
|
|||
{
|
||||
using T = simde_uint128;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -812,6 +915,7 @@ struct countl_zero<uint128_t>
|
|||
{
|
||||
using T = uint128_t;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -828,6 +932,7 @@ struct countl_zero<uint256_t>
|
|||
{
|
||||
using T = uint256_t;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -844,6 +949,7 @@ struct countl_zero<simde__m128i>
|
|||
{
|
||||
using T = simde__m128i;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -860,6 +966,7 @@ template <>
|
|||
struct countl_zero<simde__m256i>
|
||||
{
|
||||
using T = simde__m256i;
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -882,6 +989,7 @@ struct countr_zero<simde_int128>
|
|||
{
|
||||
using T = simde_int128;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -898,6 +1006,7 @@ struct countr_zero<simde_uint128>
|
|||
{
|
||||
using T = simde_uint128;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -914,6 +1023,7 @@ struct countr_zero<uint128_t>
|
|||
{
|
||||
using T = uint128_t;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -930,6 +1040,7 @@ struct countr_zero<uint256_t>
|
|||
{
|
||||
using T = uint256_t;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -946,6 +1057,7 @@ struct countr_zero<simde__m128i>
|
|||
{
|
||||
using T = simde__m128i;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -963,6 +1075,7 @@ struct countr_zero<simde__m256i>
|
|||
{
|
||||
using T = simde__m256i;
|
||||
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr std::size_t operator()(const T & val) const noexcept
|
||||
|
|
@ -1026,13 +1139,19 @@ static constexpr std::size_t packed_lane_bits_v
|
|||
= packed_lane_bits<std::remove_cv_t<T>>::value;
|
||||
|
||||
template <typename T>
|
||||
auto data(T & bar) // NOLINT(runtime/references)
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr auto data(T & bar) noexcept // NOLINT(runtime/references)
|
||||
{
|
||||
return std::data(bar);
|
||||
}
|
||||
|
||||
/// Pointer overload. Constness of `bar` is the constness of `T`.
|
||||
template <typename T>
|
||||
auto data(T * bar)
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr T * data(T * bar) noexcept
|
||||
{
|
||||
return bar;
|
||||
}
|
||||
|
|
@ -1063,7 +1182,10 @@ template <typename T>
|
|||
static constexpr bool is_tuple_v = is_tuple<T>::value;
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
auto & get(T & t) // NOLINT(runtime/references)
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr auto & get(T & t) noexcept // NOLINT(runtime/references)
|
||||
{
|
||||
if constexpr(I == 0 && is_tuple_v<T> == false)
|
||||
{
|
||||
|
|
@ -1085,7 +1207,10 @@ template <typename T>
|
|||
static constexpr bool is_bit_array_v = is_bit_array<T>::value;
|
||||
|
||||
template <typename T>
|
||||
auto size(const T & t)
|
||||
HEDLEY_PURE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr auto size(const T & t) noexcept
|
||||
{
|
||||
if constexpr(is_bit_array_v<T> == false)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,8 +44,11 @@ struct wildcard_value
|
|||
static_assert(std::numeric_limits<T>::is_iec559 ||
|
||||
!(std::is_same_v<T, float> || std::is_same_v<T, double>),
|
||||
"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
|
||||
|
|
@ -93,6 +96,7 @@ template <typename T> using concrete_type_t = typename concrete_type<T>::type;
|
|||
|
||||
template <typename T> struct concrete_value
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
constexpr std::optional<T> operator()(T y) const noexcept
|
||||
|
|
@ -102,6 +106,7 @@ template <typename T> struct concrete_value
|
|||
};
|
||||
template <typename T> struct concrete_value<wildcard_value<T>>
|
||||
{
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
constexpr std::optional<T> operator()(wildcard_value<T>) const noexcept
|
||||
|
|
|
|||
|
|
@ -49,13 +49,16 @@ struct xor_wrapper
|
|||
constexpr xor_wrapper() = default;
|
||||
|
||||
/// @brief Copy c'tor
|
||||
HEDLEY_NO_THROW
|
||||
constexpr xor_wrapper(const xor_wrapper &) noexcept = default;
|
||||
|
||||
/// @brief Move c'tor
|
||||
HEDLEY_NO_THROW
|
||||
constexpr xor_wrapper(xor_wrapper &&) noexcept = default;
|
||||
|
||||
/// @brief Value c'tor
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
HEDLEY_NO_THROW
|
||||
constexpr xor_wrapper(value_type v) noexcept : value{v} { } // NOLINT(runtime/explicit)
|
||||
|
||||
/// @}
|
||||
|
|
@ -163,7 +166,7 @@ struct xor_wrapper
|
|||
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr xor_wrapper & operator<<=(std::size_t amount)
|
||||
constexpr xor_wrapper & operator<<=(std::size_t amount) noexcept
|
||||
{
|
||||
this->value <<= amount;
|
||||
return *this;
|
||||
|
|
@ -171,7 +174,7 @@ struct xor_wrapper
|
|||
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr xor_wrapper & operator>>=(std::size_t amount)
|
||||
constexpr xor_wrapper & operator>>=(std::size_t amount) noexcept
|
||||
{
|
||||
this->value >>= amount;
|
||||
return *this;
|
||||
|
|
@ -274,14 +277,14 @@ struct xor_wrapper
|
|||
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
friend constexpr xor_wrapper operator<<(const xor_wrapper & val, std::size_t amount)
|
||||
friend constexpr xor_wrapper operator<<(const xor_wrapper & val, std::size_t amount) noexcept
|
||||
{
|
||||
return xor_wrapper(val.value << amount);
|
||||
}
|
||||
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
friend constexpr xor_wrapper operator>>(const xor_wrapper & val, std::size_t amount)
|
||||
friend constexpr xor_wrapper operator>>(const xor_wrapper & val, std::size_t amount) noexcept
|
||||
{
|
||||
return xor_wrapper(val.value >> amount);
|
||||
}
|
||||
|
|
@ -670,217 +673,217 @@ constexpr static auto operator "" _x61(unsigned long long int x) { return dpf::x
|
|||
constexpr static auto operator "" _x62(unsigned long long int x) { return dpf::xints::xint62_t{static_cast<psnip_uint64_t>(x)}; }
|
||||
constexpr static auto operator "" _x63(unsigned long long int x) { return dpf::xints::xint63_t{static_cast<psnip_uint64_t>(x)}; }
|
||||
constexpr static auto operator "" _x64(unsigned long long int x) { return dpf::xints::xint64_t{static_cast<psnip_uint64_t>(x)}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x65() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint65_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x66() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint66_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x67() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint67_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x68() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint68_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x69() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint69_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x65() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint65_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x66() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint66_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x67() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint67_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x68() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint68_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x69() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint69_t{x}; }
|
||||
// 70--79
|
||||
template <char ...digits> constexpr static auto operator "" _x70() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint70_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x71() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint71_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x72() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint72_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x73() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint73_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x74() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint74_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x75() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint75_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x76() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint76_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x77() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint77_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x78() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint78_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x79() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint79_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x70() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint70_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x71() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint71_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x72() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint72_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x73() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint73_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x74() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint74_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x75() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint75_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x76() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint76_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x77() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint77_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x78() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint78_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x79() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint79_t{x}; }
|
||||
// 80--89
|
||||
template <char ...digits> constexpr static auto operator "" _x80() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint80_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x81() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint81_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x82() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint82_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x83() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint83_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x84() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint84_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x85() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint85_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x86() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint86_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x87() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint87_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x88() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint88_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x89() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint89_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x80() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint80_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x81() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint81_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x82() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint82_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x83() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint83_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x84() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint84_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x85() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint85_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x86() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint86_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x87() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint87_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x88() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint88_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x89() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint89_t{x}; }
|
||||
// 90--99
|
||||
template <char ...digits> constexpr static auto operator "" _x90() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint90_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x91() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint91_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x92() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint92_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x93() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint93_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x94() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint94_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x95() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint95_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x96() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint96_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x97() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint97_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x98() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint98_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x99() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint99_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x90() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint90_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x91() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint91_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x92() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint92_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x93() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint93_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x94() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint94_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x95() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint95_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x96() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint96_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x97() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint97_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x98() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint98_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x99() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint99_t{x}; }
|
||||
// 100--109
|
||||
template <char ...digits> constexpr static auto operator "" _x100() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint100_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x101() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint101_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x102() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint102_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x103() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint103_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x104() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint104_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x105() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint105_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x106() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint106_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x107() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint107_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x108() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint108_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x109() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint109_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x100() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint100_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x101() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint101_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x102() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint102_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x103() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint103_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x104() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint104_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x105() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint105_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x106() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint106_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x107() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint107_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x108() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint108_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x109() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint109_t{x}; }
|
||||
// 110--119
|
||||
template <char ...digits> constexpr static auto operator "" _x110() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint110_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x111() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint111_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x112() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint112_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x113() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint113_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x114() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint114_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x115() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint115_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x116() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint116_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x117() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint117_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x118() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint118_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x119() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint119_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x110() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint110_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x111() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint111_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x112() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint112_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x113() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint113_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x114() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint114_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x115() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint115_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x116() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint116_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x117() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint117_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x118() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint118_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x119() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint119_t{x}; }
|
||||
// 120--129
|
||||
template <char ...digits> constexpr static auto operator "" _x120() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint120_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x121() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint121_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x122() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint122_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x123() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint123_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x124() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint124_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x125() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint125_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x126() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint126_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x127() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint127_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x128() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint128_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x129() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint129_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x120() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint120_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x121() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint121_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x122() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint122_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x123() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint123_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x124() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint124_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x125() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint125_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x126() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint126_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x127() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint127_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x128() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); simde_uint128 x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint128_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x129() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint129_t{x}; }
|
||||
// 130--139
|
||||
template <char ...digits> constexpr static auto operator "" _x130() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint130_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x131() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint131_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x132() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint132_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x133() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint133_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x134() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint134_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x135() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint135_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x136() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint136_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x137() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint137_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x138() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint138_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x139() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint139_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x130() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint130_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x131() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint131_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x132() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint132_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x133() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint133_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x134() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint134_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x135() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint135_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x136() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint136_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x137() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint137_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x138() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint138_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x139() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint139_t{x}; }
|
||||
// 140--149
|
||||
template <char ...digits> constexpr static auto operator "" _x140() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint140_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x141() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint141_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x142() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint142_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x143() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint143_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x144() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint144_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x145() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint145_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x146() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint146_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x147() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint147_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x148() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint148_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x149() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint149_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x140() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint140_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x141() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint141_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x142() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint142_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x143() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint143_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x144() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint144_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x145() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint145_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x146() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint146_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x147() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint147_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x148() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint148_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x149() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint149_t{x}; }
|
||||
// 150--159
|
||||
template <char ...digits> constexpr static auto operator "" _x150() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint150_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x151() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint151_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x152() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint152_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x153() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint153_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x154() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint154_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x155() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint155_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x156() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint156_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x157() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint157_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x158() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint158_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x159() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint159_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x150() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint150_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x151() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint151_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x152() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint152_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x153() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint153_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x154() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint154_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x155() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint155_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x156() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint156_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x157() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint157_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x158() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint158_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x159() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint159_t{x}; }
|
||||
// 160--169
|
||||
template <char ...digits> constexpr static auto operator "" _x160() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint160_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x161() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint161_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x162() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint162_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x163() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint163_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x164() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint164_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x165() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint165_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x166() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint166_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x167() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint167_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x168() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint168_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x169() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint169_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x160() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint160_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x161() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint161_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x162() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint162_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x163() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint163_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x164() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint164_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x165() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint165_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x166() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint166_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x167() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint167_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x168() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint168_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x169() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint169_t{x}; }
|
||||
// 170--179
|
||||
template <char ...digits> constexpr static auto operator "" _x170() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint170_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x171() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint171_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x172() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint172_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x173() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint173_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x174() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint174_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x175() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint175_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x176() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint176_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x177() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint177_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x178() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint178_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x179() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint179_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x170() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint170_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x171() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint171_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x172() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint172_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x173() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint173_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x174() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint174_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x175() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint175_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x176() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint176_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x177() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint177_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x178() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint178_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x179() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint179_t{x}; }
|
||||
// 180--189
|
||||
template <char ...digits> constexpr static auto operator "" _x180() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint180_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x181() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint181_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x182() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint182_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x183() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint183_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x184() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint184_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x185() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint185_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x186() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint186_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x187() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint187_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x188() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint188_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x189() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint189_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x180() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint180_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x181() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint181_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x182() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint182_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x183() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint183_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x184() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint184_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x185() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint185_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x186() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint186_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x187() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint187_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x188() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint188_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x189() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint189_t{x}; }
|
||||
// 190--199
|
||||
template <char ...digits> constexpr static auto operator "" _x190() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint190_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x191() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint191_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x192() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint192_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x193() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint193_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x194() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint194_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x195() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint195_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x196() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint196_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x197() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint197_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x198() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint198_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x199() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint199_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x190() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint190_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x191() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint191_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x192() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint192_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x193() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint193_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x194() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint194_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x195() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint195_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x196() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint196_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x197() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint197_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x198() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint198_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x199() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint199_t{x}; }
|
||||
// 200--209
|
||||
template <char ...digits> constexpr static auto operator "" _x200() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint200_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x201() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint201_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x202() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint202_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x203() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint203_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x204() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint204_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x205() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint205_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x206() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint206_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x207() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint207_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x208() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint208_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x209() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint209_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x200() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint200_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x201() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint201_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x202() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint202_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x203() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint203_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x204() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint204_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x205() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint205_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x206() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint206_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x207() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint207_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x208() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint208_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x209() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint209_t{x}; }
|
||||
// 210--219
|
||||
template <char ...digits> constexpr static auto operator "" _x210() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint210_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x211() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint211_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x212() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint212_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x213() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint213_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x214() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint214_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x215() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint215_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x216() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint216_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x217() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint217_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x218() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint218_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x219() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint219_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x210() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint210_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x211() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint211_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x212() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint212_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x213() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint213_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x214() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint214_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x215() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint215_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x216() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint216_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x217() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint217_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x218() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint218_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x219() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint219_t{x}; }
|
||||
// 220--229
|
||||
template <char ...digits> constexpr static auto operator "" _x220() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint220_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x221() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint221_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x222() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint222_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x223() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint223_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x224() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint224_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x225() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint225_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x226() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint226_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x227() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint227_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x228() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint228_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x229() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint229_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x220() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint220_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x221() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint221_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x222() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint222_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x223() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint223_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x224() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint224_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x225() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint225_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x226() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint226_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x227() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint227_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x228() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint228_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x229() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint229_t{x}; }
|
||||
// 230--239
|
||||
template <char ...digits> constexpr static auto operator "" _x230() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint230_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x231() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint231_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x232() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint232_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x233() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint233_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x234() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint234_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x235() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint235_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x236() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint236_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x237() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint237_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x238() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint238_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x239() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint239_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x230() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint230_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x231() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint231_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x232() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint232_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x233() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint233_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x234() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint234_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x235() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint235_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x236() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint236_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x237() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint237_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x238() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint238_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x239() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint239_t{x}; }
|
||||
// 240--249
|
||||
template <char ...digits> constexpr static auto operator "" _x240() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint240_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x241() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint241_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x242() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint242_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x243() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint243_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x244() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint244_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x245() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint245_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x246() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint246_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x247() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint247_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x248() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint248_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x249() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint249_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x240() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint240_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x241() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint241_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x242() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint242_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x243() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint243_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x244() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint244_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x245() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint245_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x246() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint246_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x247() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint247_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x248() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint248_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x249() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint249_t{x}; }
|
||||
// 250--259
|
||||
template <char ...digits> constexpr static auto operator "" _x250() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint250_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x251() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint251_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x252() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint252_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x253() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint253_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x254() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint254_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x255() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint255_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x256() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; (~((x *= 10) | (x += digits - '0')), ...); return dpf::xints::xint256_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x250() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint250_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x251() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint251_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x252() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint252_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x253() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint253_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x254() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint254_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x255() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint255_t{x}; }
|
||||
template <char ...digits> constexpr static auto operator "" _x256() { utils::constexpr_maybe_throw<std::runtime_error>(!(std::isdigit(digits) && ...), "invalid char"); uint256_t x{0}; ((x = x * 10 + (digits - '0')), ...); return dpf::xints::xint256_t{x}; }
|
||||
|
||||
} // namespace xints
|
||||
|
||||
|
|
@ -929,6 +932,7 @@ template <typename T>
|
|||
struct mod_pow_2<xor_wrapper<T>>
|
||||
{
|
||||
static constexpr auto mod = mod_pow_2<T>{};
|
||||
HEDLEY_NO_THROW
|
||||
std::size_t operator()(xor_wrapper<T> val, std::size_t n) const noexcept
|
||||
{
|
||||
return mod(val.value, n);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ struct zip_iterator
|
|||
|
||||
template <typename ...Iterables>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
zip_iterable<Iterables...> tuple_as_zip(std::tuple<Iterables...> & tup) noexcept
|
||||
{
|
||||
return zip_iterable<Iterables...>(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue