barretenberg
Loading...
Searching...
No Matches
polynomial.hpp
1#pragma once
2#include "barretenberg/common/mem.hpp"
3#include "barretenberg/crypto/sha256/sha256.hpp"
4#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
5#include "evaluation_domain.hpp"
6#include "polynomial_arithmetic.hpp"
7#include <fstream>
8
9namespace barretenberg {
10enum class DontZeroMemory { FLAG };
11
12template <typename Fr> class Polynomial {
13 public:
17 using value_type = Fr;
18 using difference_type = std::ptrdiff_t;
19 using reference = value_type&;
20 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
21 using pointer = std::shared_ptr<value_type[]>;
22 using const_pointer = pointer;
23 using iterator = Fr*;
24 using const_iterator = Fr const*;
25 using FF = Fr;
26
27 Polynomial(size_t initial_size);
28 // Constructor that does not initialize values, use with caution to save time.
29 Polynomial(size_t initial_size, DontZeroMemory flag);
30 Polynomial(const Polynomial& other);
31 Polynomial(const Polynomial& other, size_t target_size);
32
33 Polynomial(Polynomial&& other) noexcept;
34
35 // Create a polynomial from the given fields.
36 Polynomial(std::span<const Fr> coefficients);
37
38 // Allow polynomials to be entirely reset/dormant
39 Polynomial() = default;
40
48 Polynomial(std::span<const Fr> interpolation_points, std::span<const Fr> evaluations);
49
50 // move assignment
51 Polynomial& operator=(Polynomial&& other) noexcept;
52 Polynomial& operator=(std::span<const Fr> coefficients) noexcept;
53 Polynomial& operator=(const Polynomial& other);
54 ~Polynomial() = default;
55
59 Polynomial share() const;
60
61 std::array<uint8_t, 32> hash() const { return sha256::sha256(byte_span()); }
62
63 void clear()
64 {
65 // to keep the invariant that backing_memory_ can handle capacity() we do NOT reset backing_memory_
66 // backing_memory_.reset();
67 coefficients_ = nullptr;
68 size_ = 0;
69 }
70
71 bool operator==(Polynomial const& rhs) const;
72
73 // Const and non const versions of coefficient accessors
74 Fr const& operator[](const size_t i) const { return coefficients_[i]; }
75
76 Fr& operator[](const size_t i) { return coefficients_[i]; }
77
78 Fr const& at(const size_t i) const
79 {
80 ASSERT(i < capacity());
81 return coefficients_[i];
82 };
83
84 Fr& at(const size_t i)
85 {
86 ASSERT(i < capacity());
87 return coefficients_[i];
88 };
89
90 Fr evaluate(const Fr& z, size_t target_size) const;
91 Fr evaluate(const Fr& z) const;
92
93 Fr compute_barycentric_evaluation(const Fr& z, const EvaluationDomain<Fr>& domain)
94 requires polynomial_arithmetic::SupportsFFT<Fr>;
95 Fr evaluate_from_fft(const EvaluationDomain<Fr>& large_domain,
96 const Fr& z,
97 const EvaluationDomain<Fr>& small_domain)
98 requires polynomial_arithmetic::SupportsFFT<Fr>;
99 void fft(const EvaluationDomain<Fr>& domain)
100 requires polynomial_arithmetic::SupportsFFT<Fr>;
101 void partial_fft(const EvaluationDomain<Fr>& domain, Fr constant = 1, bool is_coset = false)
102 requires polynomial_arithmetic::SupportsFFT<Fr>;
103 void coset_fft(const EvaluationDomain<Fr>& domain)
104 requires polynomial_arithmetic::SupportsFFT<Fr>;
105 void coset_fft(const EvaluationDomain<Fr>& domain,
106 const EvaluationDomain<Fr>& large_domain,
107 size_t domain_extension)
108 requires polynomial_arithmetic::SupportsFFT<Fr>;
109 void coset_fft_with_constant(const EvaluationDomain<Fr>& domain, const Fr& constant)
110 requires polynomial_arithmetic::SupportsFFT<Fr>;
111 void coset_fft_with_generator_shift(const EvaluationDomain<Fr>& domain, const Fr& constant)
112 requires polynomial_arithmetic::SupportsFFT<Fr>;
113 void ifft(const EvaluationDomain<Fr>& domain)
114 requires polynomial_arithmetic::SupportsFFT<Fr>;
115 void ifft_with_constant(const EvaluationDomain<Fr>& domain, const Fr& constant)
116 requires polynomial_arithmetic::SupportsFFT<Fr>;
117 void coset_ifft(const EvaluationDomain<Fr>& domain)
118 requires polynomial_arithmetic::SupportsFFT<Fr>;
119 Fr compute_kate_opening_coefficients(const Fr& z)
120 requires polynomial_arithmetic::SupportsFFT<Fr>;
121
122 bool is_empty() const { return size_ == 0; }
123
130 Polynomial shifted() const;
131
142 void set_to_right_shifted(std::span<Fr> coeffs_in, size_t shift_size = 1);
143
150 void add_scaled(std::span<const Fr> other, Fr scaling_factor);
151
157 Polynomial& operator+=(std::span<const Fr> other);
158
164 Polynomial& operator-=(std::span<const Fr> other);
165
171 Polynomial& operator*=(Fr scaling_factor);
172
183 Fr evaluate_mle(std::span<const Fr> evaluation_points, bool shift = false) const;
184
202 Polynomial<Fr> partial_evaluate_mle(std::span<const Fr> evaluation_points) const;
203
214 void factor_roots(std::span<const Fr> roots) { polynomial_arithmetic::factor_roots(std::span{ *this }, roots); };
215 void factor_roots(const Fr& root) { polynomial_arithmetic::factor_roots(std::span{ *this }, root); };
216
217 iterator begin() { return coefficients_; }
218 iterator end() { return coefficients_ + size_; }
219 pointer data() { return backing_memory_; }
220
221 std::span<uint8_t> byte_span() const
222 {
223 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
224 return { reinterpret_cast<uint8_t*>(coefficients_), size_ * sizeof(Fr) };
225 }
226
227 const_iterator begin() const { return coefficients_; }
228 const_iterator end() const { return coefficients_ + size_; }
229 const_pointer data() const { return backing_memory_; }
230
231 std::size_t size() const { return size_; }
232 std::size_t capacity() const { return size_ + MAXIMUM_COEFFICIENT_SHIFT; }
233
234 private:
235 // allocate a fresh memory pointer for backing memory
236 // DOES NOT initialize memory
237 void allocate_backing_memory(size_t n_elements);
238
239 // safety check for in place operations
240 bool in_place_operation_viable(size_t domain_size = 0) { return (size() >= domain_size); }
241
242 void zero_memory_beyond(size_t start_position);
243 // When a polynomial is instantiated from a size alone, the memory allocated corresponds to
244 // input size + MAXIMUM_COEFFICIENT_SHIFT to support 'shifted' coefficients efficiently.
245 const static size_t MAXIMUM_COEFFICIENT_SHIFT = 1;
246
247 // The memory
248 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
249 std::shared_ptr<Fr[]> backing_memory_;
250 // A pointer into backing_memory_ to support std::span-like functionality. This allows for coefficient subsets
251 // and shifts.
252 Fr* coefficients_ = nullptr;
253 // The size_ effectively represents the 'usable' length of the coefficients array but may be less than the true
254 // 'capacity' of the array. It is not explicitly tied to the degree and is not changed by any operations on the
255 // polynomial.
256 size_t size_ = 0;
257};
258
259template <typename Fr> inline std::ostream& operator<<(std::ostream& os, Polynomial<Fr> const& p)
260{
261 if (p.size() == 0) {
262 return os << "[]";
263 }
264 if (p.size() == 1) {
265 return os << "[ data " << p[0] << "]";
266 }
267 return os << "[ data\n"
268 << " " << p[0] << ",\n"
269 << " " << p[1] << ",\n"
270 << " ... ,\n"
271 << " " << p[p.size() - 2] << ",\n"
272 << " " << p[p.size() - 1] << ",\n"
273 << "]";
274}
275
276extern template class Polynomial<barretenberg::fr>;
277// N.B. grumpkin polynomials don't support fast fourier transforms using roots of unity!
278extern template class Polynomial<grumpkin::fr>;
279
280using polynomial = Polynomial<barretenberg::fr>;
281
282} // namespace barretenberg
283
Definition: polynomial.hpp:12
void set_to_right_shifted(std::span< Fr > coeffs_in, size_t shift_size=1)
Set self to the right shift of input coefficients.
Definition: polynomial.cpp:338
Polynomial< Fr > partial_evaluate_mle(std::span< const Fr > evaluation_points) const
Partially evaluates in the last k variables a polynomial interpreted as a multilinear extension.
Definition: polynomial.cpp:482
void factor_roots(std::span< const Fr > roots)
Divides p(X) by (X-r₁)⋯(X−rₘ) in-place. Assumes that p(rⱼ)=0 for all j.
Definition: polynomial.hpp:214
void fft(const EvaluationDomain< Fr > &domain)
Definition: polynomial.cpp:206
Polynomial & operator-=(std::span< const Fr > other)
subtracts the polynomial q(X) 'other'.
Definition: polynomial.cpp:404
Polynomial shifted() const
Returns an std::span of the left-shift of self.
Definition: polynomial.cpp:323
Polynomial & operator+=(std::span< const Fr > other)
adds the polynomial q(X) 'other'.
Definition: polynomial.cpp:385
Polynomial share() const
Definition: polynomial.cpp:141
void add_scaled(std::span< const Fr > other, Fr scaling_factor)
adds the polynomial q(X) 'other', multiplied by a scaling factor.
Definition: polynomial.cpp:367
Fr evaluate_mle(std::span< const Fr > evaluation_points, bool shift=false) const
evaluates p(X) = ∑ᵢ aᵢ⋅Xⁱ considered as multi-linear extension p(X₀,…,Xₘ₋₁) = ∑ᵢ aᵢ⋅Lᵢ(X₀,...
Definition: polynomial.cpp:441
Polynomial & operator*=(Fr scaling_factor)
sets this = p(X) to s⋅p(X)
Definition: polynomial.cpp:423
constexpr_utils defines some helper methods that perform some stl-equivalent operations but in a cons...
Definition: constexpr_utils.hpp:16