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