#include #include #include #include "grotto.hpp" namespace { std::uint64_t pow_u64(std::uint64_t base, std::uint64_t exp) { std::uint64_t acc = 1; while (exp != 0) { if (exp & 1u) acc *= base; base *= base; exp >>= 1; } return acc; } } // namespace /// Representation shift (Fibonacci / geometric / CRC) and twisted monomials. int main() { //! [repr-and-twist] // --- Representation shift: Fibonacci checkpoint ---------------------- // Dealer keys S_c = (F_{c+1}, F_c). After eta opens, each party applies // the public companion-matrix power M^kappa to its share of S_c. const std::uint8_t center = 10; const std::uint8_t eta = 5; const std::uint8_t point = static_cast(center + eta); // 15 const auto fib_state = grotto::offset_repr_fibonacci_state(center); const auto M = grotto::offset_repr_fibonacci_matrix(); auto fib_keys = grotto::make_offset_repr_keys(center, fib_state); const std::vector knots{0}; const auto f0 = grotto::offset_repr_eval<0>(fib_keys, M, knots, eta); const auto f1 = grotto::offset_repr_eval<1>(fib_keys, M, knots, eta); const std::vector S{f0[0] + f1[0], f0[1] + f1[1]}; // Geometric twin: 1x1 matrix [lambda] advances lambda^c by lambda^kappa. const std::uint64_t lambda_geo = 3; const auto G = grotto::offset_repr_geometric_matrix(lambda_geo); auto geo_keys = grotto::make_offset_repr_keys( center, {pow_u64(lambda_geo, center)}); const auto g0 = grotto::offset_repr_eval<0>(geo_keys, G, knots, eta); const auto g1 = grotto::offset_repr_eval<1>(geo_keys, G, knots, eta); const std::uint64_t geo = g0[0] + g1[0]; // Clear CRC-32 jump documents the GF(2) twin (XOR shares, not additive). const std::uint32_t crc_seed = 0x12345678u; const std::uint32_t crc_jumped = grotto::offset_repr_crc32_jump(crc_seed, 64); // --- Twisted monomials: (a0 + a1 x + a2 x^2) * lambda^x ------------- const std::uint64_t lambda = 3; const std::size_t degree = 2; auto twist_keys = grotto::make_offset_twist_keys( center, degree, lambda); // h(x) = (2 + 5x + x^2) * 3^x const std::vector coeff{2, 5, 1}; const std::uint64_t twisted = grotto::offset_twist_eval<0>(twist_keys, knots, coeff, eta) + grotto::offset_twist_eval<1>(twist_keys, knots, coeff, eta); // Dyadic decay: masked carry shift. The sum of the shares is the shifted value. auto half_keys = grotto::make_offset_twist_keys( center, degree, grotto::twist_half); const std::uint64_t half = grotto::offset_twist_eval<0>(half_keys, knots, coeff, eta) + grotto::offset_twist_eval<1>(half_keys, knots, coeff, eta); // Closed form sum_{k=1}^n k * lambda^k from the same twisted table. const std::uint64_t ag = grotto::offset_twist_arithmetico_geometric(point, lambda); //! [repr-and-twist] const auto expect_S = grotto::offset_repr_fibonacci_state(point); if (S != expect_S) { std::cerr << "fibonacci state\n"; return 1; } if (geo != pow_u64(lambda_geo, point)) { std::cerr << "geometric\n"; return 1; } std::uint64_t expect_t = 0; std::uint64_t xp = 1; for (std::uint64_t c : coeff) { expect_t += c * xp; xp *= point; } expect_t *= pow_u64(lambda, point); if (twisted != expect_t) { std::cerr << "twisted poly\n"; return 1; } std::uint64_t expect_h = 0; xp = 1; for (std::uint64_t c : coeff) { expect_h += c * xp; xp *= point; } expect_h >>= point; if (half != expect_h) { std::cerr << "twist half\n"; return 1; } std::uint64_t expect_ag = 0; for (std::uint64_t k = 1; k <= point; ++k) expect_ag += k * pow_u64(lambda, k); if (ag != expect_ag) { std::cerr << "arithmetico-geometric\n"; return 1; } if (crc_jumped == 0 && crc_seed != 0) { // Jump can legally land on zero; only used as a smoke output. } std::cout << S[1] << " " << geo << " " << twisted << " " << half << " " << ag << " " << crc_jumped << "\n"; return 0; }