9#include <gtest/gtest.h>
21 for (
size_t i = 0; i < poly1.size(); ++i) {
23 poly2.at(i) = poly1[i];
27 auto eval1 = poly1.evaluate(challenge);
28 auto eval2 = poly2.evaluate(challenge);
30 EXPECT_EQ(eval1, eval2);
33TEST(polynomials, fft_with_small_degree)
35 constexpr size_t n = 16;
39 for (
size_t i = 0; i < n; ++i) {
45 domain.compute_lookup_table();
51 for (
size_t i = 0; i < n; ++i) {
53 EXPECT_EQ((fft_transform[i] == expected),
true);
54 work_root *= domain.root;
58TEST(polynomials, split_polynomial_fft)
60 constexpr size_t n = 256;
64 for (
size_t i = 0; i < n; ++i) {
69 constexpr size_t num_poly = 4;
70 constexpr size_t n_poly = n / num_poly;
71 fr fft_transform_[num_poly][n_poly];
72 for (
size_t i = 0; i < n; ++i) {
73 fft_transform_[i / n_poly][i % n_poly] = poly[i];
77 domain.compute_lookup_table();
85 for (
size_t i = 0; i < n; ++i) {
87 EXPECT_EQ((fft_transform[i] == expected),
true);
88 EXPECT_EQ(fft_transform_[i / n_poly][i % n_poly], fft_transform[i]);
89 work_root *= domain.root;
93TEST(polynomials, split_polynomial_evaluate)
95 constexpr size_t n = 256;
99 for (
size_t i = 0; i < n; ++i) {
104 constexpr size_t num_poly = 4;
105 constexpr size_t n_poly = n / num_poly;
106 fr fft_transform_[num_poly][n_poly];
107 for (
size_t i = 0; i < n; ++i) {
108 fft_transform_[i / n_poly][i % n_poly] = poly[i];
113 { fft_transform_[0], fft_transform_[1], fft_transform_[2], fft_transform_[3] }, z, n),
119 constexpr size_t n = 1 << 14;
120 fr*
data = (
fr*)aligned_alloc(32,
sizeof(
fr) * n * 2);
123 for (
size_t i = 0; i < n; ++i) {
129 domain.compute_lookup_table();
133 for (
size_t i = 0; i < n; ++i) {
134 EXPECT_EQ((result[i] == expected[i]),
true);
139TEST(polynomials, fft_ifft_consistency)
141 constexpr size_t n = 256;
144 for (
size_t i = 0; i < n; ++i) {
150 domain.compute_lookup_table();
154 for (
size_t i = 0; i < n; ++i) {
155 EXPECT_EQ((result[i] == expected[i]),
true);
159TEST(polynomials, split_polynomial_fft_ifft_consistency)
161 constexpr size_t n = 256;
162 constexpr size_t num_poly = 4;
163 fr result[num_poly][n];
164 fr expected[num_poly][n];
165 for (
size_t j = 0; j < num_poly; j++) {
166 for (
size_t i = 0; i < n; ++i) {
173 domain.compute_lookup_table();
176 for (
size_t j = 0; j < num_poly; j++) {
177 coeffs_vec.push_back(result[j]);
182 for (
size_t j = 0; j < num_poly; j++) {
183 for (
size_t i = 0; i < n; ++i) {
184 EXPECT_EQ((result[j][i] == expected[j][i]),
true);
189TEST(polynomials, fft_coset_ifft_consistency)
191 constexpr size_t n = 256;
194 for (
size_t i = 0; i < n; ++i) {
200 domain.compute_lookup_table();
202 T0 = domain.generator * domain.generator_inverse;
203 EXPECT_EQ((T0 ==
fr::one()),
true);
208 for (
size_t i = 0; i < n; ++i) {
209 EXPECT_EQ((result[i] == expected[i]),
true);
213TEST(polynomials, split_polynomial_fft_coset_ifft_consistency)
215 constexpr size_t n = 256;
216 constexpr size_t num_poly = 4;
217 fr result[num_poly][n];
218 fr expected[num_poly][n];
219 for (
size_t j = 0; j < num_poly; j++) {
220 for (
size_t i = 0; i < n; ++i) {
227 domain.compute_lookup_table();
230 for (
size_t j = 0; j < num_poly; j++) {
231 coeffs_vec.push_back(result[j]);
236 for (
size_t j = 0; j < num_poly; j++) {
237 for (
size_t i = 0; i < n; ++i) {
238 EXPECT_EQ((result[j][i] == expected[j][i]),
true);
243TEST(polynomials, fft_coset_ifft_cross_consistency)
245 constexpr size_t n = 2;
251 for (
size_t i = 0; i < n; ++i) {
255 expected[i] = poly_a[i] + poly_c[i];
256 expected[i] += poly_b[i];
259 for (
size_t i = n; i < 4 * n; ++i) {
267 small_domain.compute_lookup_table();
268 mid_domain.compute_lookup_table();
269 large_domain.compute_lookup_table();
274 for (
size_t i = 0; i < n; ++i) {
275 poly_a[i] = poly_a[i] + poly_c[4 * i];
276 poly_a[i] = poly_a[i] + poly_b[2 * i];
281 for (
size_t i = 0; i < n; ++i) {
282 EXPECT_EQ((poly_a[i] == expected[i]),
true);
286TEST(polynomials, compute_kate_opening_coefficients)
289 constexpr size_t n = 256;
290 fr* coeffs =
static_cast<fr*
>(aligned_alloc(64,
sizeof(
fr) * 2 * n));
291 fr* W =
static_cast<fr*
>(aligned_alloc(64,
sizeof(
fr) * 2 * n));
292 for (
size_t i = 0; i < n; ++i) {
306 fr* multiplicand =
static_cast<fr*
>(aligned_alloc(64,
sizeof(
fr) * 2 * n));
307 multiplicand[0] = -z;
309 for (
size_t i = 2; i < 2 * n; ++i) {
318 domain.compute_lookup_table();
325 for (
size_t i = 0; i < domain.size; ++i) {
326 result = W[i] * multiplicand[i];
327 EXPECT_EQ((result == coeffs[i]),
true);
330 aligned_free(coeffs);
332 aligned_free(multiplicand);
335TEST(polynomials, barycentric_weight_evaluations)
337 constexpr size_t n = 16;
341 std::vector<fr> poly(n);
342 std::vector<fr> barycentric_poly(n);
344 for (
size_t i = 0; i < n / 2; ++i) {
346 barycentric_poly[i] = poly[i];
348 for (
size_t i = n / 2; i < n; ++i) {
350 barycentric_poly[i] = poly[i];
363 EXPECT_EQ((result == expected),
true);
366TEST(polynomials, linear_poly_product)
368 constexpr size_t n = 64;
373 for (
size_t i = 0; i < n; ++i) {
375 expected *= (z - roots[i]);
382 EXPECT_EQ(result, expected);
393 using FF = TypeParam;
394 constexpr size_t n = 256;
397 EXPECT_EQ(domain.size, 256UL);
398 EXPECT_EQ(domain.log2_size, 8UL);
403 using FF = TypeParam;
404 constexpr size_t n = 256;
409 expected = FF::one();
410 result = domain.root.pow(
static_cast<uint64_t
>(n));
412 EXPECT_EQ((result == expected),
true);
417 using FF = TypeParam;
418 constexpr size_t n = 16;
423 FF* roots = root_table[root_table.size() - 1];
424 FF* inverse_roots = inverse_root_table[inverse_root_table.size() - 1];
425 for (
size_t i = 0; i < (n - 1) / 2; ++i) {
426 EXPECT_EQ(roots[i] * domain.
root, roots[i + 1]);
427 EXPECT_EQ(inverse_roots[i] * domain.
root_inverse, inverse_roots[i + 1]);
428 EXPECT_EQ(roots[i] * inverse_roots[i], FF::one());
434 using FF = TypeParam;
435 constexpr size_t n = 100;
436 FF src[n], poly[n], x[n];
438 for (
size_t i = 0; i < n; ++i) {
439 poly[i] = FF::random_element();
442 for (
size_t i = 0; i < n; ++i) {
443 x[i] = FF::random_element();
448 for (
size_t i = 0; i < n; ++i) {
449 EXPECT_EQ(src[i], poly[i]);
455 using FF = TypeParam;
456 constexpr size_t n = 250;
459 for (
size_t i = 0; i < n; ++i) {
460 poly[i] = FF::random_element();
463 for (
size_t i = 0; i < n; ++i) {
464 x[i] = FF::random_element();
469 for (
size_t i = 0; i < n; ++i) {
470 EXPECT_EQ(src[i], poly[i]);
476 using FF = TypeParam;
477 constexpr size_t n = 15;
480 for (
size_t i = 0; i < n; ++i) {
484 for (
size_t i = 0; i < n; ++i) {
490 for (
size_t i = 0; i < n; ++i) {
491 EXPECT_EQ(src[i], poly[i]);
495 for (
size_t i = 0; i < n; ++i) {
496 poly[i] =
FF(i + 54);
499 for (
size_t i = 0; i < n; ++i) {
500 x[i] =
FF(i - n / 2);
505 for (
size_t i = 0; i < n; ++i) {
506 EXPECT_EQ(src[i], poly[i]);
511 for (
size_t i = 0; i < n; ++i) {
512 poly[i] =
FF(i * i + 57);
515 for (
size_t i = 0; i < n; ++i) {
516 x[i] =
FF(i - (n - 1));
521 for (
size_t i = 0; i < n; ++i) {
522 EXPECT_EQ(src[i], poly[i]);
528 using FF = TypeParam;
530 auto root = std::array{
FF(3) };
531 auto eval = std::array{
FF(4) };
533 ASSERT_EQ(t.
size(), 1);
534 ASSERT_EQ(t[0], eval[0]);
539 using FF = TypeParam;
541 constexpr size_t N = 32;
544 for (
size_t i = 0; i < N; ++i) {
545 roots[i] = FF::random_element();
546 evaluations[i] = FF::random_element();
549 auto roots_copy(roots);
550 auto evaluations_copy(evaluations);
554 ASSERT_EQ(interpolated.
size(), N);
555 ASSERT_EQ(roots, roots_copy);
556 ASSERT_EQ(evaluations, evaluations_copy);
558 for (
size_t i = 0; i < N; ++i) {
560 ASSERT_EQ(eval, evaluations[i]);
567 using FF = TypeParam;
569 auto test_case = [](
size_t N) {
572 EXPECT_EQ(N, 1 << m);
574 for (
size_t i = 1; i < N - 1; ++i) {
575 poly.
at(i) = FF::random_element(&
engine);
577 poly.
at(N - 1) = FF::zero();
579 EXPECT_TRUE(poly[0].is_zero());
582 std::vector<FF> u(m);
583 for (
size_t l = 0; l < m; ++l) {
584 u[l] = FF::random_element(&
engine);
587 std::vector<FF> lagrange_evals(N,
FF(1));
588 for (
size_t i = 0; i < N; ++i) {
589 auto& coef = lagrange_evals[i];
590 for (
size_t l = 0; l < m; ++l) {
591 size_t mask = (1 << l);
592 if ((i & mask) == 0) {
593 coef *= (
FF(1) - u[l]);
603 for (
size_t i = 0; i < N; ++i) {
604 real_eval += poly[i] * lagrange_evals[i];
607 EXPECT_EQ(real_eval, computed_eval);
610 FF real_eval_shift(0);
611 for (
size_t i = 1; i < N; ++i) {
612 real_eval_shift += poly[i] * lagrange_evals[i - 1];
615 EXPECT_EQ(real_eval_shift, computed_eval_shift);
629 using FF = TypeParam;
632 for (
size_t i = 0; i < N; i++) {
633 poly.
at(i) = FF::random_element();
637 auto u_0 = FF::random_element();
638 auto u_1 = FF::random_element();
639 auto u_2 = FF::random_element();
640 auto u_3 = FF::random_element();
641 auto u_4 = FF::random_element();
642 std::vector<FF> u_challenge = { u_0, u_1, u_2, u_3, u_4 };
651 std::vector<FF> u_part_1 = { u_0, u_1 };
652 std::vector<FF> u_part_2 = { u_2, u_3, u_4 };
654 auto v_result = partial_evaluated_poly.
evaluate_mle(u_part_1);
656 EXPECT_EQ(v_result, v_expected);
661 using FF = TypeParam;
664 size_t num_coeffs = 64;
666 for (
size_t i = 0; i < num_coeffs; i++) {
667 polynomial_a.
at(i) = FF::random_element();
674 EXPECT_EQ(polynomial_a.
data(),
nullptr);
677 auto polynomial_c =
std::move(polynomial_b);
680 EXPECT_EQ(polynomial_b.
data(),
nullptr);
684 for (
size_t i = 0; i < num_coeffs; i++) {
685 polynomial_d.
at(i) = FF::random_element();
692 EXPECT_EQ(polynomial_c.data(),
nullptr);
697 using FF = TypeParam;
700 size_t num_coeffs = 64;
702 for (
size_t i = 0; i < num_coeffs; i++) {
703 interesting_poly.
at(i) = FF::random_element();
712 poly = interesting_poly;
715 for (
size_t i = 0; i < num_coeffs; ++i) {
716 EXPECT_EQ(poly[i], interesting_poly[i]);
718 EXPECT_EQ(poly.
size(), interesting_poly.
size());
void compute_lookup_table()
const std::vector< FF * > & get_round_roots() const
const std::vector< FF * > & get_inverse_round_roots() const
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
Polynomial partial_evaluate_mle(std::span< const Fr > evaluation_points) const
Partially evaluates in the last k variables a polynomial interpreted as a multilinear extension.
Fr evaluate(const Fr &z, size_t target_size) const
Fr evaluate_mle(std::span< const Fr > evaluation_points, bool shift=false) const
evaluate multi-linear extension p(X_0,…,X_{n-1}) = \sum_i a_i*L_i(X_0,…,X_{n-1}) at u = (u_0,...
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
const std::vector< FF > data
testing::Types< bb::fr > FieldTypes
constexpr T get_msb(const T in)
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
void ifft(Fr *coeffs, const EvaluationDomain< Fr > &domain)
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 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 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)
Entry point for Barretenberg command-line interface.
EvaluationDomain< bb::fr > evaluation_domain
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
TEST(MegaCircuitBuilder, CopyConstructor)
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr field one()
BB_INLINE constexpr field to_montgomery_form() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept
static BB_INLINE void __copy(const field &a, field &r) noexcept
static constexpr field zero()