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
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue