Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
polynomial_arithmetic.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Nishat], commit: 94f596f8b3bbbc216f9ad7dc33253256141156b2 }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
10
12
13template <typename T>
14concept SupportsFFT = T::Params::has_high_2adicity;
15
16template <typename Fr> struct LagrangeEvaluations {
20};
22
23template <typename Fr> Fr evaluate(const Fr* coeffs, const Fr& z, const size_t n);
24template <typename Fr> Fr evaluate(std::span<const Fr> coeffs, const Fr& z, const size_t n)
25{
26 BB_ASSERT_LTE(n, coeffs.size());
27 return evaluate(coeffs.data(), z, n);
28};
29template <typename Fr> Fr evaluate(std::span<const Fr> coeffs, const Fr& z)
30{
31 return evaluate(coeffs, z, coeffs.size());
32};
33template <typename Fr>
34 requires SupportsFFT<Fr>
36 Fr* coeffs, Fr* target, const EvaluationDomain<Fr>& domain, const Fr&, const std::vector<Fr*>& root_table);
37template <typename Fr>
38 requires SupportsFFT<Fr>
39void ifft(Fr* coeffs, Fr* target, const EvaluationDomain<Fr>& domain);
40
41// This function computes sum of all scalars in a given array.
42template <typename Fr> Fr compute_sum(const Fr* src, const size_t n);
43
44// This function computes the polynomial (x - a)(x - b)(x - c)... given n distinct roots (a, b, c, ...).
45template <typename Fr> void compute_linear_polynomial_product(const Fr* roots, Fr* dest, const size_t n);
46
47// This function interpolates from points {(z_1, f(z_1)), (z_2, f(z_2)), ...}
48// using a single scalar inversion and Lagrange polynomial interpolation.
49// `src` contains {f(z_1), f(z_2), ...}
50template <typename Fr>
51void compute_efficient_interpolation(const Fr* src, Fr* dest, const Fr* evaluation_points, const size_t n);
52
56template <typename Fr> void factor_roots(std::span<Fr> polynomial, const Fr& root)
57{
58 const size_t size = polynomial.size();
59 if (size == 0) {
60 return;
61 }
62 if (root.is_zero()) {
63 // if one of the roots is 0 after having divided by all other roots,
64 // then p(X) = a₁⋅X + ⋯ + aₙ₋₁⋅Xⁿ⁻¹
65 // so we shift the array of coefficients to the left
66 // and the result is p(X) = a₁ + ⋯ + aₙ₋₁⋅Xⁿ⁻² and we subtract 1 from the size.
67 std::copy_n(polynomial.begin() + 1, size - 1, polynomial.begin());
68 } else {
69 // assume
70 // • r != 0
71 // • (X−r) | p(X)
72 // • q(X) = ∑ᵢⁿ⁻² bᵢ⋅Xⁱ
73 // • p(X) = ∑ᵢⁿ⁻¹ aᵢ⋅Xⁱ = (X-r)⋅q(X)
74 //
75 // p(X) 0 1 2 ... n-2 n-1
76 // a₀ a₁ a₂ aₙ₋₂ aₙ₋₁
77 //
78 // q(X) 0 1 2 ... n-2 n-1
79 // b₀ b₁ b₂ bₙ₋₂ 0
80 //
81 // (X-r)⋅q(X) 0 1 2 ... n-2 n-1
82 // -r⋅b₀ b₀-r⋅b₁ b₁-r⋅b₂ bₙ₋₃−r⋅bₙ₋₂ bₙ₋₂
83 //
84 // b₀ = a₀⋅(−r)⁻¹
85 // b₁ = (a₁ - b₀)⋅(−r)⁻¹
86 // b₂ = (a₂ - b₁)⋅(−r)⁻¹
87 // ⋮
88 // bᵢ = (aᵢ − bᵢ₋₁)⋅(−r)⁻¹
89 // ⋮
90 // bₙ₋₂ = (aₙ₋₂ − bₙ₋₃)⋅(−r)⁻¹
91 // bₙ₋₁ = 0
92
93 // For the simple case of one root we compute (−r)⁻¹ and
94 Fr root_inverse = (-root).invert();
95 // set b₋₁ = 0
96 Fr temp = 0;
97 // We start multiplying lower coefficient by the inverse and subtracting those from highter coefficients
98 // Since (x - r) should divide the polynomial cleanly, we can guide division with lower coefficients
99 for (size_t i = 0; i < size - 1; ++i) {
100 // at the start of the loop, temp = bᵢ₋₁
101 // and we can compute bᵢ = (aᵢ − bᵢ₋₁)⋅(−r)⁻¹
102 temp = (polynomial[i] - temp);
103 temp *= root_inverse;
104 polynomial[i] = temp;
105 }
106 // Exact-division precondition: a_{n-1} == b_{n-2} (i.e. polynomial[size-1] == temp).
107 // When violated the quotient is wrong; without this assert the zero-write below hides it.
108 BB_ASSERT(polynomial[size - 1] == temp);
109 }
110 polynomial[size - 1] = Fr::zero();
111}
112
113} // namespace bb::polynomial_arithmetic
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:158
void ifft(Fr *coeffs, Fr *target, const EvaluationDomain< Fr > &domain)
void compute_linear_polynomial_product(const Fr *roots, Fr *dest, const size_t n)
Fr evaluate(const Fr *coeffs, const Fr &z, const size_t n)
void factor_roots(std::span< Fr > polynomial, const Fr &root)
Divides p(X) by (X-r) in-place.
void fft_inner_parallel(Fr *coeffs, Fr *target, const EvaluationDomain< Fr > &domain, const Fr &, const std::vector< Fr * > &root_table)
void compute_efficient_interpolation(const Fr *src, Fr *dest, const Fr *evaluation_points, const size_t n)
Fr compute_sum(const Fr *src, const size_t n)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
BB_INLINE constexpr bool is_zero() const noexcept
static constexpr field zero()