26 #ifndef CRYPTO3_MATH_GEOMETRIC_SEQUENCE_DOMAIN_HPP
27 #define CRYPTO3_MATH_GEOMETRIC_SEQUENCE_DOMAIN_HPP
45 template<
typename FieldType>
46 class evaluation_domain;
48 template<
typename FieldType>
50 typedef typename FieldType::value_type value_type;
60 geometric_sequence = std::vector<value_type>(this->m, value_type::zero());
61 geometric_sequence[0] = value_type::one();
63 geometric_triangular_sequence = std::vector<value_type>(this->m, value_type::zero());
64 geometric_triangular_sequence[0] = value_type::one();
66 for (std::size_t i = 1; i < this->m; i++) {
67 geometric_sequence[i] =
69 geometric_triangular_sequence[i] =
70 geometric_triangular_sequence[i - 1] * geometric_sequence[i - 1];
73 precomputation_sentinel =
true;
78 throw std::invalid_argument(
"geometric(): expected m > 1");
82 throw std::invalid_argument(
83 "geometric(): expected "
84 "value_type(fields::arithmetic_params<FieldType>::geometric_generator).is_zero() != "
88 precomputation_sentinel =
false;
91 void fft(std::vector<value_type> &a) {
92 if (a.size() != this->m) {
93 if (a.size() < this->m) {
94 a.resize(this->m, value_type(0));
96 throw std::invalid_argument(
"geometric: expected a.size() == this->m");
100 if (!precomputation_sentinel)
103 monomial_to_newton_basis_geometric<FieldType>(a, geometric_sequence, geometric_triangular_sequence,
107 std::vector<value_type> T(this->m);
108 T[0] = value_type::one();
110 std::vector<value_type> g(this->m);
113 for (std::size_t i = 1; i < this->m; i++) {
114 T[i] = T[i - 1] * (geometric_sequence[i] - value_type::one()).inversed();
115 g[i] = geometric_triangular_sequence[i] * a[i];
122 #pragma omp parallel for
124 for (std::size_t i = 0; i < this->m; i++) {
125 a[i] *= T[i].inversed();
129 if (a.size() != this->m) {
130 if (a.size() < this->m) {
131 a.resize(this->m, value_type(0));
133 throw std::invalid_argument(
"geometric: expected a.size() == this->m");
137 if (!precomputation_sentinel)
141 std::vector<value_type> T(this->m);
142 T[0] = value_type::one();
144 std::vector<value_type> W(this->m);
147 value_type prev_T = T[0];
148 for (std::size_t i = 1; i < this->m; i++) {
149 prev_T *= (geometric_sequence[i] - value_type::one()).inversed();
151 W[i] = a[i] * prev_T;
152 T[i] = geometric_triangular_sequence[i] * prev_T;
161 #pragma omp parallel for
163 for (std::size_t i = 0; i < this->m; i++) {
164 a[i] *= geometric_triangular_sequence[i].inversed();
167 newton_to_monomial_basis_geometric<FieldType>(a, geometric_sequence, geometric_triangular_sequence,
177 if (!precomputation_sentinel) {
185 for (std::size_t i = 0; i < this->m; ++i) {
186 if (geometric_sequence[i] == t)
188 std::vector<value_type> res(this->m, value_type::zero());
189 res[i] = value_type::one();
198 std::vector<value_type> l(this->m);
199 l[0] = t - geometric_sequence[0];
201 std::vector<value_type> g(this->m);
202 g[0] = value_type::zero();
204 value_type l_vanish = l[0];
205 value_type g_vanish = value_type::one();
206 for (std::size_t i = 1; i < this->m; i++) {
207 l[i] = t - geometric_sequence[i];
208 g[i] = value_type::one() - geometric_sequence[i];
214 value_type r = geometric_sequence[this->m - 1].inversed();
217 std::vector<value_type> g_i(this->m);
218 g_i[0] = g_vanish.inversed();
220 l[0] = l_vanish * l[0].inversed() * g_i[0];
221 for (std::size_t i = 1; i < this->m; i++) {
222 g_i[i] = g_i[i - 1] * g[this->m - i] * -g[i].inversed() * geometric_sequence[i];
223 l[i] = l_vanish * r_i * l[i].inversed() * g_i[i];
230 if (!precomputation_sentinel)
233 return this->geometric_sequence[idx];
236 if (!precomputation_sentinel)
241 value_type Z = value_type::one();
242 for (std::size_t i = 0; i < this->m; i++) {
243 Z *= (t - geometric_sequence[i]);
247 void add_poly_z(
const value_type &coeff, std::vector<value_type> &H) {
248 if (H.size() != this->m + 1)
249 throw std::invalid_argument(
"geometric: expected H.size() == this->m+1");
251 if (!precomputation_sentinel)
254 std::vector<value_type> x(2, value_type::zero());
255 x[0] = -geometric_sequence[0];
256 x[1] = value_type::one();
258 std::vector<value_type> t(2, value_type::zero());
260 for (std::size_t i = 1; i < this->m + 1; i++) {
261 t[0] = -geometric_sequence[i];
262 t[1] = value_type::one();
268 #pragma omp parallel for
270 for (std::size_t i = 0; i < this->m + 1; i++) {
271 H[i] += (x[i] * coeff);
275 const value_type coset = value_type(
278 const value_type Z_inverse_at_coset = compute_vanishing_polynomial(coset).inversed();
279 for (std::size_t i = 0; i < this->m; ++i) {
280 P[i] *= Z_inverse_at_coset;
Definition: evaluation_domain.hpp:41
Definition: geometric_sequence_domain.hpp:49
std::vector< value_type > geometric_triangular_sequence
Definition: geometric_sequence_domain.hpp:57
value_type get_domain_element(const std::size_t idx)
Definition: geometric_sequence_domain.hpp:229
bool precomputation_sentinel
Definition: geometric_sequence_domain.hpp:55
geometric_sequence_domain(const std::size_t m)
Definition: geometric_sequence_domain.hpp:76
void add_poly_z(const value_type &coeff, std::vector< value_type > &H)
Definition: geometric_sequence_domain.hpp:247
void divide_by_z_on_coset(std::vector< value_type > &P)
Definition: geometric_sequence_domain.hpp:274
FieldType field_type
Definition: geometric_sequence_domain.hpp:53
void fft(std::vector< value_type > &a)
Definition: geometric_sequence_domain.hpp:91
void do_precomputation()
Definition: geometric_sequence_domain.hpp:59
std::vector< value_type > evaluate_all_lagrange_polynomials(const value_type &t)
Definition: geometric_sequence_domain.hpp:170
std::vector< value_type > geometric_sequence
Definition: geometric_sequence_domain.hpp:56
value_type compute_vanishing_polynomial(const value_type &t)
Definition: geometric_sequence_domain.hpp:235
void inverse_fft(std::vector< value_type > &a)
Definition: geometric_sequence_domain.hpp:128
void multiplication(Range &c, const Range &a, const Range &b)
Definition: basic_operations.hpp:192
bool is_zero(const Range &a)
Definition: basic_operations.hpp:43
Definition: fields/params.hpp:58