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: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
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> Fr evaluate(const std::vector<Fr*> coeffs, const Fr& z, const size_t large_n);
34
35// 2. Compute a lookup table of the roots of unity, and suffer through cache misses from nonlinear access patterns
36template <typename Fr>
37 requires SupportsFFT<Fr>
38void fft_inner_parallel(std::vector<Fr*> coeffs,
39 const EvaluationDomain<Fr>& domain,
40 const Fr&,
41 const std::vector<Fr*>& root_table);
42
43template <typename Fr>
44 requires SupportsFFT<Fr>
45void fft(Fr* coeffs, const EvaluationDomain<Fr>& domain);
46template <typename Fr>
47 requires SupportsFFT<Fr>
48void fft(Fr* coeffs, Fr* target, const EvaluationDomain<Fr>& domain);
49template <typename Fr>
50 requires SupportsFFT<Fr>
51void fft(std::vector<Fr*> coeffs, const EvaluationDomain<Fr>& domain);
52
53template <typename Fr>
54 requires SupportsFFT<Fr>
55void coset_fft(Fr* coeffs, const EvaluationDomain<Fr>& domain);
56template <typename Fr>
57 requires SupportsFFT<Fr>
58void coset_fft(Fr* coeffs, Fr* target, const EvaluationDomain<Fr>& domain);
59template <typename Fr>
60 requires SupportsFFT<Fr>
61void coset_fft(std::vector<Fr*> coeffs, const EvaluationDomain<Fr>& domain);
62template <typename Fr>
63 requires SupportsFFT<Fr>
64void coset_fft(Fr* coeffs,
65 const EvaluationDomain<Fr>& small_domain,
66 const EvaluationDomain<Fr>& large_domain,
67 const size_t domain_extension);
68
69template <typename Fr>
70 requires SupportsFFT<Fr>
71void ifft(Fr* coeffs, const EvaluationDomain<Fr>& domain);
72template <typename Fr>
73 requires SupportsFFT<Fr>
74void ifft(Fr* coeffs, Fr* target, const EvaluationDomain<Fr>& domain);
75template <typename Fr>
76 requires SupportsFFT<Fr>
77void ifft(std::vector<Fr*> coeffs, const EvaluationDomain<Fr>& domain);
78
79template <typename Fr>
80 requires SupportsFFT<Fr>
81void coset_ifft(Fr* coeffs, const EvaluationDomain<Fr>& domain);
82template <typename Fr>
83 requires SupportsFFT<Fr>
84void coset_ifft(std::vector<Fr*> coeffs, const EvaluationDomain<Fr>& domain);
85
86// void populate_with_vanishing_polynomial(Fr* coeffs, const size_t num_non_zero_entries, const EvaluationDomain<Fr>&
87// src_domain, const EvaluationDomain<Fr>& target_domain);
88
90 unsigned long num_coeffs,
91 const fr& z,
92 const EvaluationDomain<fr>& domain);
93
94// This function computes sum of all scalars in a given array.
95template <typename Fr> Fr compute_sum(const Fr* src, const size_t n);
96
97// This function computes the polynomial (x - a)(x - b)(x - c)... given n distinct roots (a, b, c, ...).
98template <typename Fr> void compute_linear_polynomial_product(const Fr* roots, Fr* dest, const size_t n);
99
100// This function interpolates from points {(z_1, f(z_1)), (z_2, f(z_2)), ...}
101// using a single scalar inversion and Lagrange polynomial interpolation.
102// `src` contains {f(z_1), f(z_2), ...}
103template <typename Fr>
104void compute_efficient_interpolation(const Fr* src, Fr* dest, const Fr* evaluation_points, const size_t n);
105
109template <typename Fr> void factor_roots(std::span<Fr> polynomial, const Fr& root)
110{
111 const size_t size = polynomial.size();
112 if (root.is_zero()) {
113 // if one of the roots is 0 after having divided by all other roots,
114 // then p(X) = a₁⋅X + ⋯ + aₙ₋₁⋅Xⁿ⁻¹
115 // so we shift the array of coefficients to the left
116 // and the result is p(X) = a₁ + ⋯ + aₙ₋₁⋅Xⁿ⁻² and we subtract 1 from the size.
117 std::copy_n(polynomial.begin() + 1, size - 1, polynomial.begin());
118 } else {
119 // assume
120 // • r != 0
121 // • (X−r) | p(X)
122 // • q(X) = ∑ᵢⁿ⁻² bᵢ⋅Xⁱ
123 // • p(X) = ∑ᵢⁿ⁻¹ aᵢ⋅Xⁱ = (X-r)⋅q(X)
124 //
125 // p(X) 0 1 2 ... n-2 n-1
126 // a₀ a₁ a₂ aₙ₋₂ aₙ₋₁
127 //
128 // q(X) 0 1 2 ... n-2 n-1
129 // b₀ b₁ b₂ bₙ₋₂ 0
130 //
131 // (X-r)⋅q(X) 0 1 2 ... n-2 n-1
132 // -r⋅b₀ b₀-r⋅b₁ b₁-r⋅b₂ bₙ₋₃−r⋅bₙ₋₂ bₙ₋₂
133 //
134 // b₀ = a₀⋅(−r)⁻¹
135 // b₁ = (a₁ - b₀)⋅(−r)⁻¹
136 // b₂ = (a₂ - b₁)⋅(−r)⁻¹
137 // ⋮
138 // bᵢ = (aᵢ − bᵢ₋₁)⋅(−r)⁻¹
139 // ⋮
140 // bₙ₋₂ = (aₙ₋₂ − bₙ₋₃)⋅(−r)⁻¹
141 // bₙ₋₁ = 0
142
143 // For the simple case of one root we compute (−r)⁻¹ and
144 Fr root_inverse = (-root).invert();
145 // set b₋₁ = 0
146 Fr temp = 0;
147 // We start multiplying lower coefficient by the inverse and subtracting those from highter coefficients
148 // Since (x - r) should divide the polynomial cleanly, we can guide division with lower coefficients
149 for (size_t i = 0; i < size - 1; ++i) {
150 // at the start of the loop, temp = bᵢ₋₁
151 // and we can compute bᵢ = (aᵢ − bᵢ₋₁)⋅(−r)⁻¹
152 temp = (polynomial[i] - temp);
153 temp *= root_inverse;
154 polynomial[i] = temp;
155 }
156 }
157 polynomial[size - 1] = Fr::zero();
158}
159
160} // namespace bb::polynomial_arithmetic
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:152
void ifft(Fr *coeffs, const EvaluationDomain< Fr > &domain)
void fft_inner_parallel(std::vector< Fr * > coeffs, const EvaluationDomain< Fr > &domain, const Fr &, const std::vector< Fr * > &root_table)
void coset_fft(Fr *coeffs, 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(Fr *coeffs, const EvaluationDomain< Fr > &domain)
fr compute_barycentric_evaluation(const fr *coeffs, const size_t num_coeffs, const fr &z, const EvaluationDomain< fr > &domain)
void coset_ifft(Fr *coeffs, const EvaluationDomain< Fr > &domain)
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()