Document the new DPF surfaces in one command set, and test the field, half-tree, and multipoint edges.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
0d8a5a8131
commit
0dff6df8ed
250 changed files with 12199 additions and 1981 deletions
|
|
@ -45,7 +45,7 @@ struct ic_pack
|
|||
Beta if_false{};
|
||||
};
|
||||
|
||||
/// Spec tag and factory. `dpf::ic(p, q, beta)` builds a pack;
|
||||
/// @brief Spec tag and factory. `dpf::ic(p, q, beta)` builds a pack;
|
||||
/// `eval_point(dpf::ic, key, x)` evaluates it.
|
||||
struct ic_fn
|
||||
{
|
||||
|
|
@ -68,6 +68,12 @@ inline constexpr ic_fn ic{};
|
|||
template <typename T>
|
||||
struct is_ic_key : std::false_type {};
|
||||
|
||||
/// @brief One party's interval key: the inner comparison, the public bounds, and the
|
||||
/// secret correction shares.
|
||||
/// @tparam Party party index, `0` or `1`
|
||||
/// @tparam Key key type
|
||||
/// @tparam Input input domain type
|
||||
/// @tparam Beta payload type
|
||||
template <std::size_t Party, typename Key, typename Input, typename Beta>
|
||||
struct ic_key
|
||||
{
|
||||
|
|
@ -76,24 +82,27 @@ struct ic_key
|
|||
using input_type = Input;
|
||||
using key_type = party_key<Party, Key>;
|
||||
using beta_type = Beta;
|
||||
using share_type = std::conditional_t<
|
||||
detail::cmp_group_info<dpf::concrete_type_t<Beta>>::custom,
|
||||
detail::group_elem, uint64_t>;
|
||||
|
||||
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;
|
||||
/// @brief Share of `δ`. Public `c_x ∈ {-1,0,1}` scales it locally.
|
||||
share_type delta_share{};
|
||||
/// @brief Share of `δ · c_r + if_false`.
|
||||
share_type cr_share{};
|
||||
/// @brief Wildcard only: shares of `1` and of `c_r`, scaled by `δ` in `assign_cmp`.
|
||||
share_type delta_coeff{};
|
||||
share_type cr_coeff{};
|
||||
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)
|
||||
uint64_t gmask, share_type dshare, share_type cshare, share_type dcoeff,
|
||||
share_type ccoeff) noexcept(std::is_nothrow_move_constructible_v<key_type>)
|
||||
: key(std::move(k))
|
||||
, lo(lo_in)
|
||||
, hi(hi_in)
|
||||
|
|
@ -167,20 +176,40 @@ 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.
|
||||
/// @brief Public integer in Fig. 3, before it is embedded in the payload group.
|
||||
/// @param r the `r`
|
||||
/// @param p the `p`
|
||||
/// @param q the `q`
|
||||
/// @param nmask the mask of the live input bits
|
||||
/// @return Public integer in Fig. 3, before it is embedded in the payload group
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr int correction_s(uint64_t r, uint64_t p, uint64_t q,
|
||||
uint64_t nmask) 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;
|
||||
return (ap > aq ? 1 : 0) - (ap > p ? 1 : 0)
|
||||
+ (aq0 > q0 ? 1 : 0) + (aq == nmask ? 1 : 0);
|
||||
}
|
||||
|
||||
/// @brief Dealer correction in Fig. 3, as an element of the payload group.
|
||||
/// @param r the `r`
|
||||
/// @param p the `p`
|
||||
/// @param q the `q`
|
||||
/// @param nmask the mask of the live input bits
|
||||
/// @param gmask the mask of the live payload bits
|
||||
/// @return 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);
|
||||
return embed_small(correction_s(r, p, q, nmask), gmask);
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
|
|
@ -251,8 +280,10 @@ void check_bounds(const ic_pack<Beta> & spec)
|
|||
}
|
||||
|
||||
template <typename Beta>
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
uint64_t group_mask_of() noexcept
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr uint64_t group_mask_of() noexcept
|
||||
{
|
||||
using B = concrete_type_t<Beta>;
|
||||
if constexpr (std::is_same_v<B, dpf::bit>)
|
||||
|
|
@ -261,11 +292,11 @@ uint64_t group_mask_of() noexcept
|
|||
return dcf_impl::default_mask_for_bits(utils::bitlength_of_v<B>);
|
||||
}
|
||||
|
||||
template <std::size_t Party, typename Key, typename Input, typename Beta>
|
||||
template <std::size_t Party, typename Key, typename Input, typename Beta,
|
||||
typename Share>
|
||||
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)
|
||||
Share delta_share, Share cr_share, Share delta_coeff, Share cr_coeff)
|
||||
{
|
||||
return ic_key<Party, Key, Input, Beta>(std::move(key), lo, hi, nmask, gmask,
|
||||
delta_share, cr_share, delta_coeff, cr_coeff);
|
||||
|
|
@ -281,6 +312,46 @@ auto finish(uint64_t r_bits, const ic_pack<Beta> & spec, Pair && inner)
|
|||
const uint64_t nmask = input_mask_of<in_type>();
|
||||
const uint64_t gmask = group_mask_of<Beta>();
|
||||
constexpr bool wild = is_wildcard_v<Beta>;
|
||||
if constexpr (detail::cmp_group_info<Beta>::custom)
|
||||
{
|
||||
using prg = typename raw_key::interior_prg;
|
||||
const auto layout = detail::group_layout<out_beta>();
|
||||
auto delta = detail::group_zero(layout);
|
||||
auto fval = detail::group_zero(layout);
|
||||
if constexpr (!wild)
|
||||
{
|
||||
delta = detail::group_sub(detail::group_from_beta(spec.if_true),
|
||||
detail::group_from_beta(spec.if_false));
|
||||
fval = detail::group_from_beta(spec.if_false);
|
||||
}
|
||||
const auto cr = detail::group_scalar(
|
||||
correction_s(r_bits, spec.lo, spec.hi, nmask), layout);
|
||||
auto splitg = [&](const detail::group_elem & target,
|
||||
detail::group_elem & a, detail::group_elem & b) {
|
||||
const auto blind = detail::group_from_node<prg>(
|
||||
dpf::uniform_sample<typename raw_key::interior_node>(), layout);
|
||||
a = blind;
|
||||
b = detail::group_sub(target, blind);
|
||||
};
|
||||
detail::group_elem d0{}, d1{}, c0{}, c1{}, dc0{}, dc1{}, cc0{}, cc1{};
|
||||
if constexpr (wild)
|
||||
{
|
||||
splitg(detail::group_one(layout), dc0, dc1);
|
||||
splitg(cr, cc0, cc1);
|
||||
}
|
||||
else
|
||||
{
|
||||
splitg(delta, d0, d1);
|
||||
splitg(detail::group_add(detail::group_mul(delta, cr), fval), 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));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t delta = 0;
|
||||
uint64_t fval = 0;
|
||||
if constexpr (!wild)
|
||||
|
|
@ -310,6 +381,7 @@ auto finish(uint64_t r_bits, const ic_pack<Beta> & spec, Pair && inner)
|
|||
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>
|
||||
|
|
@ -318,6 +390,15 @@ 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 if constexpr (detail::cmp_group_info<B>::custom)
|
||||
{
|
||||
const auto layout = detail::group_layout<concrete_type_t<B>>();
|
||||
const auto delta = detail::group_sub(
|
||||
detail::group_from_beta(spec.if_true),
|
||||
detail::group_from_beta(spec.if_false));
|
||||
return lt(detail::group_to_beta<B>(delta),
|
||||
detail::group_to_beta<B>(detail::group_zero(layout)));
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint64_t gmask = group_mask_of<B>();
|
||||
|
|
@ -342,9 +423,35 @@ auto eval_one(const IcKey & k, Query && x, Memo & memo)
|
|||
throw std::invalid_argument(
|
||||
"ic eval: wildcard payload not assigned (call assign_cmp)");
|
||||
using in_type = typename IcKey::input_type;
|
||||
using beta = typename IcKey::beta_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);
|
||||
if constexpr (detail::cmp_group_info<beta>::custom)
|
||||
{
|
||||
auto opened = [](const auto & v) {
|
||||
if constexpr (is_secret_share_v<std::decay_t<decltype(v)>>)
|
||||
return detail::group_from_beta(v.raw());
|
||||
else
|
||||
return detail::group_from_beta(v);
|
||||
};
|
||||
const auto a = opened(eval_point<beta>(dpf::cmp, k.key,
|
||||
input_from_bits<in_type>(xp), memo));
|
||||
const auto b = opened(eval_point<beta>(dpf::cmp, k.key,
|
||||
input_from_bits<in_type>(xq), memo));
|
||||
const int cx = public_cx(xu, k.lo, k.hi, k.input_mask);
|
||||
auto scaled = detail::group_zero(a);
|
||||
if (cx == 1)
|
||||
scaled = k.delta_share;
|
||||
else if (cx == -1)
|
||||
scaled = detail::group_neg(k.delta_share);
|
||||
const auto y = detail::group_add(detail::group_add(
|
||||
detail::group_add(detail::group_neg(a), b), k.cr_share), scaled);
|
||||
return make_eval_cmp_result<typename IcKey::key_type>(
|
||||
detail::group_to_beta<beta>(y));
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint64_t a = opened_u64(
|
||||
eval_point(dpf::cmp, k.key, input_from_bits<in_type>(xp), memo),
|
||||
k.group_mask);
|
||||
|
|
@ -361,12 +468,20 @@ auto eval_one(const IcKey & k, Query && x, Memo & memo)
|
|||
+ 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`.
|
||||
/// @brief Dealer key for public bounds `spec` and secret mask `r`.
|
||||
/// @tparam InteriorPRG PRG that expands interior nodes. Defaults to `dpf::prg::aes128`
|
||||
/// @tparam ExteriorPRG PRG that expands the root. Defaults to `InteriorPRG`
|
||||
/// @tparam InputT input domain type
|
||||
/// @tparam Beta payload type
|
||||
/// @param r the secret input mask
|
||||
/// @param spec the public bounds and payloads
|
||||
/// @return Dealer key for public bounds `spec` and secret mask `r`
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
|
|
@ -384,7 +499,24 @@ auto make_dpf(InputT && r, const ic_pack<Beta> & spec)
|
|||
return detail::ic_impl::finish<input_type>(r_bits, spec, std::move(inner));
|
||||
}
|
||||
|
||||
/// Doerner–Shelat key. `r0 XOR r1` is the secret mask.
|
||||
/// @name Doerner–Shelat interval keys
|
||||
/// @tparam InteriorPRG PRG that expands interior nodes. Defaults to `dpf::prg::aes128`
|
||||
/// @tparam ExteriorPRG PRG that expands the root. Defaults to `InteriorPRG`
|
||||
/// @tparam InputT input domain type
|
||||
/// @tparam Beta payload type
|
||||
/// @param r0 party 0's share of the mask
|
||||
/// @param r1 party 1's share of the mask
|
||||
/// @param spec the public bounds and payloads
|
||||
/// @{
|
||||
|
||||
/// @brief XOR shares. `r0 XOR r1` is the secret mask.
|
||||
/// @tparam RootSampler sampler for the Doerner–Shelat root seed
|
||||
/// @tparam PadRng pad stream for the Doerner–Shelat protocol
|
||||
/// @param r0 party 0's share of the mask
|
||||
/// @param r1 party 1's share of the mask
|
||||
/// @param rng the Doerner–Shelat randomness tapes
|
||||
/// @param spec the public bounds and payloads
|
||||
/// @return the two party keys
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename RootSampler,
|
||||
|
|
@ -408,7 +540,14 @@ auto make_dpf_doerner_shelat(InputT r0, InputT r1,
|
|||
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.
|
||||
/// @brief Additive shares. `r0 + r1` is the secret mask; γ = (r0 + r1) − 1.
|
||||
/// @tparam RootSampler sampler for the Doerner–Shelat root seed
|
||||
/// @tparam PadRng pad stream for the Doerner–Shelat protocol
|
||||
/// @param r0 party 0's share of the mask
|
||||
/// @param r1 party 1's share of the mask
|
||||
/// @param rng the Doerner–Shelat randomness tapes
|
||||
/// @param spec the public bounds and payloads
|
||||
/// @return the two party keys
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename RootSampler,
|
||||
|
|
@ -436,7 +575,8 @@ auto make_dpf_doerner_shelat(arith_input_t, InputT r0, InputT r1,
|
|||
detail::ic_impl::bits_of(r), spec, std::move(inner));
|
||||
}
|
||||
|
||||
/// Doerner–Shelat key sampled from the library entropy source.
|
||||
/// @brief XOR shares, sampled from the library entropy source.
|
||||
/// @return the two party keys
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
|
|
@ -451,6 +591,8 @@ auto make_dpf_doerner_shelat(InputT r0, InputT r1, const ic_pack<Beta> & spec)
|
|||
std::move(r0), std::move(r1), rng, spec);
|
||||
}
|
||||
|
||||
/// @brief Additive shares, sampled from the library entropy source.
|
||||
/// @return the two party keys
|
||||
template <typename InteriorPRG = dpf::prg::aes128,
|
||||
typename ExteriorPRG = InteriorPRG,
|
||||
typename InputT,
|
||||
|
|
@ -466,7 +608,17 @@ auto make_dpf_doerner_shelat(arith_input_t, InputT r0, InputT r1,
|
|||
arith_input, std::move(r0), std::move(r1), rng, spec);
|
||||
}
|
||||
|
||||
/// Open a wildcard interval payload onto an existing key pair.
|
||||
/// @}
|
||||
|
||||
/// @brief Open a wildcard interval payload onto an existing key pair.
|
||||
/// @tparam Key key type
|
||||
/// @tparam Input input domain type
|
||||
/// @tparam Beta payload type
|
||||
/// @tparam Payload concrete payload type
|
||||
/// @param k0 the `k0`
|
||||
/// @param k1 the `k1`
|
||||
/// @param if_true the payload on a true comparison
|
||||
/// @param if_false the payload on a false comparison
|
||||
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,
|
||||
|
|
@ -474,6 +626,31 @@ void assign_cmp(ic_key<0, Key, Input, Beta> & k0,
|
|||
{
|
||||
static_assert(Key::cmp_is_wildcard,
|
||||
"assign_cmp: interval payload is not a wildcard");
|
||||
if constexpr (detail::cmp_group_info<dpf::concrete_type_t<Beta>>::custom)
|
||||
{
|
||||
using prg = typename Key::interior_prg;
|
||||
const auto layout = detail::group_layout<dpf::concrete_type_t<Beta>>();
|
||||
const auto delta = detail::group_sub(
|
||||
detail::group_from_beta(if_true), detail::group_from_beta(if_false));
|
||||
const auto fval = detail::group_from_beta(if_false);
|
||||
assign_cmp(k0.key, k1.key,
|
||||
detail::group_to_beta<Beta>(delta),
|
||||
detail::group_to_beta<Beta>(detail::group_zero(layout)));
|
||||
k0.delta_share = detail::group_mul(k0.delta_coeff, delta);
|
||||
k1.delta_share = detail::group_mul(k1.delta_coeff, delta);
|
||||
k0.cr_share = detail::group_mul(k0.cr_coeff, delta);
|
||||
k1.cr_share = detail::group_mul(k1.cr_coeff, delta);
|
||||
const auto blind = detail::group_from_node<prg>(
|
||||
dpf::uniform_sample<typename Key::interior_node>(), layout);
|
||||
const auto f1 = detail::group_sub(fval, blind);
|
||||
k0.cr_share = detail::group_add(k0.cr_share, blind);
|
||||
k1.cr_share = detail::group_add(k1.cr_share, f1);
|
||||
k0.assigned = true;
|
||||
k1.assigned = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint64_t mask = k0.group_mask;
|
||||
const uint64_t delta =
|
||||
detail::dcf_impl::beta_delta_u64(if_true, if_false, mask);
|
||||
|
|
@ -492,9 +669,17 @@ void assign_cmp(ic_key<0, Key, Input, Beta> & k0,
|
|||
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.
|
||||
/// @brief Point evaluation. `memo` is a path memoizer for the inner comparison key.
|
||||
/// @tparam IcKey interval-containment key type
|
||||
/// @tparam Query query point type
|
||||
/// @tparam Memo path memoizer type
|
||||
/// @param key the key to evaluate
|
||||
/// @param x the `x`
|
||||
/// @param memo the memoizer reused across queries
|
||||
/// @return Point evaluation
|
||||
template <typename IcKey, typename Query,
|
||||
typename Memo = basic_path_memoizer<typename IcKey::key_type>,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
|
|
@ -504,7 +689,24 @@ 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.
|
||||
/// @name Interval evaluation
|
||||
/// @tparam IcKey interval-containment key type
|
||||
/// @tparam Lane input-domain lane type
|
||||
/// @tparam Buffer output buffer type
|
||||
/// @param key the interval key
|
||||
/// @param from the inclusive start of the range
|
||||
/// @param to the inclusive end of the range
|
||||
/// @param buf the output buffer
|
||||
/// @throws std::invalid_argument if `to < from`
|
||||
/// @{
|
||||
|
||||
/// @brief Inclusive interval `[from, to]` on the input domain.
|
||||
/// @tparam Memo path memoizer type
|
||||
/// @param key the interval key
|
||||
/// @param from the inclusive start of the range
|
||||
/// @param to the inclusive end of the range
|
||||
/// @param buf the output buffer
|
||||
/// @param memo the memoizer reused across queries
|
||||
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,
|
||||
|
|
@ -528,6 +730,7 @@ void eval_interval(ic_fn, const IcKey & key, Lane from, Lane to,
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief Inclusive interval `[from, to]`, with a fresh path memoizer.
|
||||
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)
|
||||
|
|
@ -536,7 +739,25 @@ void eval_interval(ic_fn, const IcKey & key, Lane from, Lane to, Buffer && buf)
|
|||
eval_interval(ic, key, from, to, std::forward<Buffer>(buf), memo);
|
||||
}
|
||||
|
||||
/// Evaluate the points in `[begin, end)`.
|
||||
/// @}
|
||||
|
||||
/// @name Sequence evaluation
|
||||
/// @tparam IcKey interval-containment key type
|
||||
/// @tparam Iter iterator type
|
||||
/// @tparam Buffer output buffer type
|
||||
/// @param key the interval key
|
||||
/// @param begin the iterator to the first query
|
||||
/// @param end the iterator past the last query
|
||||
/// @param buf the output buffer
|
||||
/// @{
|
||||
|
||||
/// @brief Evaluate the points in `[begin, end)`.
|
||||
/// @tparam Memo path memoizer type
|
||||
/// @param key the interval key
|
||||
/// @param begin the iterator to the first query
|
||||
/// @param end the iterator past the last query
|
||||
/// @param buf the output buffer
|
||||
/// @param memo the memoizer reused across queries
|
||||
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,
|
||||
|
|
@ -547,6 +768,7 @@ void eval_sequence(ic_fn, const IcKey & key, Iter begin, Iter end,
|
|||
buf[i] = detail::ic_impl::eval_one(key, *it, memo);
|
||||
}
|
||||
|
||||
/// @brief Evaluate `[begin, end)`, with a fresh path memoizer.
|
||||
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)
|
||||
|
|
@ -555,7 +777,12 @@ void eval_sequence(ic_fn, const IcKey & key, Iter begin, Iter end, Buffer && buf
|
|||
eval_sequence(ic, key, begin, end, std::forward<Buffer>(buf), memo);
|
||||
}
|
||||
|
||||
/// Buffer of `n` interval shares.
|
||||
/// @}
|
||||
|
||||
/// @brief Buffer of `n` interval shares.
|
||||
/// @tparam IcKey interval-containment key type
|
||||
/// @param n the `n`
|
||||
/// @return 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)
|
||||
|
|
@ -565,7 +792,14 @@ auto make_output_buffer(ic_fn, const IcKey &, std::size_t n)
|
|||
return output_buffer<elem>(n);
|
||||
}
|
||||
|
||||
/// Buffer large enough for the inclusive interval `[from, to]`.
|
||||
/// @brief Buffer large enough for the inclusive interval `[from, to]`.
|
||||
/// @tparam IcKey interval-containment key type
|
||||
/// @tparam Lane input-domain lane type
|
||||
/// @param key the `key`
|
||||
/// @param from the inclusive start of the range
|
||||
/// @param to the `to`
|
||||
/// @return Buffer large enough for the inclusive interval `[from, to]`
|
||||
/// @throws std::invalid_argument if `to < from`
|
||||
template <typename IcKey, typename Lane,
|
||||
typename = std::enable_if_t<is_ic_key_v<IcKey>>>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
|
|
@ -580,7 +814,22 @@ auto make_output_buffer(ic_fn, const IcKey & key, Lane from, Lane to)
|
|||
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
|
||||
/// @name Interval geneval
|
||||
/// @tparam InputT input domain type
|
||||
/// @tparam Iter iterator type
|
||||
/// @tparam RootSampler sampler for the Doerner–Shelat root seed
|
||||
/// @tparam PadRng pad stream for the Doerner–Shelat protocol
|
||||
/// @tparam Beta payload type
|
||||
/// @param r0 party 0's share of the mask
|
||||
/// @param r1 party 1's share of the mask
|
||||
/// @param begin the iterator to the first query
|
||||
/// @param end the iterator past the last query
|
||||
/// @param rng the Doerner–Shelat randomness tapes
|
||||
/// @param spec the public bounds and payloads
|
||||
/// @return the opened party shares
|
||||
/// @{
|
||||
|
||||
/// @brief XOR mask. `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>
|
||||
|
|
@ -625,7 +874,7 @@ geneval_cmp_result geneval_ic(InputT r0, InputT r1, Iter begin, Iter end,
|
|||
return out;
|
||||
}
|
||||
|
||||
/// Additive-share geneval_ic. `r0 + r1` is the secret mask.
|
||||
/// @brief Additive mask. `r0 + r1` is the secret mask.
|
||||
template <typename InputT, typename Iter, typename RootSampler, typename PadRng,
|
||||
typename Beta>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
|
|
@ -669,6 +918,8 @@ geneval_cmp_result geneval_ic(arith_input_t, InputT r0, InputT r1, Iter begin,
|
|||
return out;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_INTERVAL_HPP__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue