Record Grotto half-ulp tables and comparison geneval, and factor shared beaver terms before the quotient.

Horner and window evaluation need those tables in the tree. Comparison geneval opens the same value words as a Doerner–Shelat key. A factor common to every polynomial term is multiplied first so that preprocessing stays smaller.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ryan Henry 2026-09-24 15:16:21 -06:00
parent 3f10e05176
commit 875f09fec1
14 changed files with 42668 additions and 184 deletions

View file

@ -371,16 +371,19 @@ struct ds_gen_state
/// When `cmp` is non-null and active for `level`, also opens `value_cw` via
/// the protocol (no second PRG expand outside).
template <typename InteriorPRG, typename CwProtocol, typename NodeT,
typename InputT, typename AdviceT>
typename InputT, typename MaskT, typename AdviceT>
void ds_advance_level(ds_gen_state<NodeT> & st, InputT x0, InputT x1,
InputT mask, std::size_t level, CwProtocol & proto, NodeT & cw_out,
MaskT mask, std::size_t level, CwProtocol & proto, NodeT & cw_out,
AdviceT & advice_out, uint64_t * value_cw_out = nullptr,
ds_cmp_gen_state * cmp = nullptr)
{
// Integral bridge so bit extraction works for `keyword` / `modint` /
// signed / bitstring the same way dealer gen does via `mask & x`.
// `msb_mask` is the unsigned bit pattern; a signed input must not be
// required to have that same type.
constexpr auto to_int = utils::to_integral_type<InputT>{};
const auto mi = to_int(mask);
constexpr auto to_mask = utils::to_integral_type<MaskT>{};
const auto mi = to_mask(mask);
const uint8_t bit0 = static_cast<uint8_t>(!!(mi & to_int(x0)));
const uint8_t bit1 = static_cast<uint8_t>(!!(mi & to_int(x1)));