Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
polynomial.test.cpp
Go to the documentation of this file.
1#include <cstddef>
2#include <gtest/gtest.h>
3
6
7// Simple test/demonstration of shifted functionality
8TEST(Polynomial, Shifted)
9{
10 using FF = bb::fr;
12 const size_t SIZE = 10;
13 auto poly = Polynomial::random(SIZE, /*shiftable*/ 1);
14
15 // Instantiate the shift via the shited method
16 auto poly_shifted = poly.shifted();
17
18 EXPECT_EQ(poly_shifted.size(), poly.size());
19
20 // The shift is indeed the shift
21 for (size_t i = 0; i < poly_shifted.size() - 1; ++i) {
22 EXPECT_EQ(poly_shifted.get(i), poly.get(i + 1));
23 }
24
25 // If I change the original polynomial, the shift is updated accordingly
26 poly.at(3) = 25;
27 for (size_t i = 0; i < poly_shifted.size() - 1; ++i) {
28 EXPECT_EQ(poly_shifted.get(i), poly.get(i + 1));
29 }
30}
31
32// Simple test/demonstration of right_shifted functionality
33TEST(Polynomial, RightShifted)
34{
35 using FF = bb::fr;
37 const size_t SIZE = 10;
38 const size_t VIRTUAL_SIZE = 20;
39 const size_t START_IDX = 2;
40 const size_t END_IDX = SIZE + START_IDX;
41 const size_t SHIFT_MAGNITUDE = 5;
42 auto poly = Polynomial::random(SIZE, VIRTUAL_SIZE, START_IDX);
43
44 // Instantiate the shift via the right_shifted method
45 auto poly_shifted = poly.right_shifted(SHIFT_MAGNITUDE);
46
47 EXPECT_EQ(poly_shifted.size(), poly.size());
48 EXPECT_EQ(poly_shifted.virtual_size(), poly.virtual_size());
49
50 // The shift is indeed the shift
51 for (size_t i = 0; i < END_IDX; ++i) {
52 EXPECT_EQ(poly_shifted.get(i + SHIFT_MAGNITUDE), poly.get(i));
53 }
54
55 // If I change the original polynomial, the shift is updated accordingly
56 poly.at(3) = 25;
57 for (size_t i = 0; i < END_IDX; ++i) {
58 EXPECT_EQ(poly_shifted.get(i + SHIFT_MAGNITUDE), poly.get(i));
59 }
60}
61
62// Simple test/demonstration of reverse functionality
63TEST(Polynomial, Reversed)
64{
65 using FF = bb::fr;
67 const size_t SIZE = 10;
68 const size_t VIRTUAL_SIZE = 20;
69 const size_t START_IDX = 2;
70 const size_t END_IDX = SIZE + START_IDX;
71 auto poly = Polynomial::random(SIZE, VIRTUAL_SIZE, START_IDX);
72
73 // Instantiate the shift via the right_shifted method
74 auto poly_reversed = poly.reverse();
75
76 EXPECT_EQ(poly_reversed.size(), poly.size());
77 EXPECT_EQ(poly_reversed.virtual_size(), poly.end_index());
78
79 // The reversed is indeed the reversed
80 for (size_t i = 0; i < END_IDX; ++i) {
81 EXPECT_EQ(poly_reversed.get(END_IDX - 1 - i), poly.get(i));
82 }
83
84 // If I change the original polynomial, the reversed polynomial is not updated
85 FF initial_value = poly.at(3);
86 poly.at(3) = 25;
87 EXPECT_EQ(poly_reversed.at(END_IDX - 4), initial_value);
88}
89
90// Simple test/demonstration of share functionality
92{
93 using FF = bb::fr;
95 const size_t SIZE = 10;
96 auto poly = Polynomial::random(SIZE);
97
98 // "clone" the poly via the share method
99 auto poly_clone = poly.share();
100
101 // The two are indeed equal
102 EXPECT_EQ(poly_clone, poly);
103
104 // Changing one changes the other
105 poly.at(3) = 25;
106 EXPECT_EQ(poly_clone, poly);
107
108 poly_clone.at(2) = 13;
109 EXPECT_EQ(poly_clone, poly);
110
111 // If reset the original poly, it will no longer be equal to the clone made earlier
112 // Note: if we had not made a clone, the memory from the original poly would be leaked
113 auto poly2 = Polynomial::random(SIZE);
114 poly = poly2.share();
115
116 EXPECT_NE(poly_clone, poly);
117}
118
119// Simple test/demonstration of various edge conditions
121{
122 auto poly = bb::Polynomial<bb::fr>::random(100, /*offset*/ 1);
123 EXPECT_EQ(poly.start_index(), 1);
124 EXPECT_EQ((*poly.indices().begin()), poly.start_index());
125 EXPECT_EQ(std::get<0>(*poly.indexed_values().begin()), poly.start_index());
126 EXPECT_EQ(std::get<1>(*poly.indexed_values().begin()), poly[poly.start_index()]);
127}
128
129#ifndef NDEBUG
130// Only run in an assert-enabled test suite.
131TEST(Polynomial, AddScaledEdgeConditions)
132{
133 // Suppress warnings about fork(), we're OK with the edge cases.
134 GTEST_FLAG_SET(death_test_style, "threadsafe");
135 using FF = bb::fr;
136 auto test_subset_good = []() {
137 // Contained within poly
138 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 0);
139 poly.add_scaled(bb::Polynomial<FF>::random(4, /*start index*/ 1), 1);
140 };
141 ASSERT_NO_FATAL_FAILURE(test_subset_good());
142 auto test_subset_bad1 = []() {
143 // Not contained within poly
144 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 1);
145 poly.add_scaled(bb::Polynomial<FF>::random(4, /*start index*/ 0), 1);
146 };
147 ASSERT_THROW_OR_ABORT(test_subset_bad1(), ".*start_index.*other.start_index.*");
148 auto test_subset_bad2 = []() {
149 // Not contained within poly
150 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 0);
151 poly.add_scaled(bb::Polynomial<FF>::random(5, /*start index*/ 0), 1);
152 };
153 ASSERT_THROW_OR_ABORT(test_subset_bad2(), ".*end_index.*other.end_index.*");
154}
155
156TEST(Polynomial, OperatorAddEdgeConditions)
157{
158 // Suppress warnings about fork(), we're OK with the edge cases.
159 GTEST_FLAG_SET(death_test_style, "threadsafe");
160 using FF = bb::fr;
161 auto test_subset_good = []() {
162 // Contained within poly
163 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 0);
164 poly += bb::Polynomial<FF>::random(4, /*start index*/ 1);
165 };
166 ASSERT_NO_FATAL_FAILURE(test_subset_good());
167 auto test_subset_bad1 = []() {
168 // Not contained within poly
169 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 1);
170 poly += bb::Polynomial<FF>::random(4, /*start index*/ 0);
171 };
172 ASSERT_THROW_OR_ABORT(test_subset_bad1(), ".*start_index.*other.start_index.*");
173 auto test_subset_bad2 = []() {
174 // Not contained within poly
175 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 0);
176 poly += bb::Polynomial<FF>::random(5, /*start index*/ 0);
177 };
178 ASSERT_THROW_OR_ABORT(test_subset_bad2(), ".*end_index.*other.end_index.*");
179}
180
181TEST(Polynomial, OperatorSubtractEdgeConditions)
182{
183 // Suppress warnings about fork(), we're OK with the edge cases.
184 GTEST_FLAG_SET(death_test_style, "threadsafe");
185 using FF = bb::fr;
186 auto test_subset_good = []() {
187 // Contained within poly
188 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 0);
189 poly -= bb::Polynomial<FF>::random(4, /*start index*/ 1);
190 };
191 ASSERT_NO_FATAL_FAILURE(test_subset_good());
192 auto test_subset_bad1 = []() {
193 // Not contained within poly
194 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 1);
195 poly -= bb::Polynomial<FF>::random(4, /*start index*/ 0);
196 };
197 ASSERT_THROW_OR_ABORT(test_subset_bad1(), ".*start_index.*other.start_index.*");
198 auto test_subset_bad2 = []() {
199 // Not contained within poly
200 auto poly = bb::Polynomial<FF>::random(4, /*start index*/ 0);
201 poly -= bb::Polynomial<FF>::random(5, /*start index*/ 0);
202 };
203 ASSERT_THROW_OR_ABORT(test_subset_bad2(), ".*end_index.*other.end_index.*");
204}
205
206// Makes a vector fully of the virtual_size aka degree + 1
208{
209 // Suppress warnings about fork(), we're OK with the edge cases.
210 GTEST_FLAG_SET(death_test_style, "threadsafe");
211 using FF = bb::fr;
212 size_t degree_plus_1 = 10;
213 auto full_good = [=]() {
214 auto poly = bb::Polynomial<FF>::random(1, degree_plus_1, /*start index*/ degree_plus_1 - 1);
215 poly = poly.full();
216 poly -= bb::Polynomial<FF>::random(degree_plus_1, /*start index*/ 0);
217 };
218 ASSERT_NO_FATAL_FAILURE(full_good());
219 auto no_full_bad = [=]() {
220 auto poly = bb::Polynomial<FF>::random(1, degree_plus_1, /*start index*/ degree_plus_1 - 1);
221 poly -= bb::Polynomial<FF>::random(degree_plus_1, /*start index*/ 0);
222 };
223 ASSERT_THROW_OR_ABORT(no_full_bad(), ".*start_index.*other.start_index.*");
224}
225
226// TODO(https://github.com/AztecProtocol/barretenberg/issues/1113): Optimizing based on actual sizes would involve using
227// expand, but it is currently unused.
229{
230 // Suppress warnings about fork(), we're OK with the edge cases.
231 GTEST_FLAG_SET(death_test_style, "threadsafe");
232 using FF = bb::fr;
233 auto test_subset_good = []() {
234 // Expand legally within poly
235 auto poly = bb::Polynomial<FF>::random(4, 10, /*start index*/ 1);
236 poly.expand(1, 6);
237 poly.expand(0, 9);
238 poly.expand(0, 10);
239 };
240 ASSERT_NO_FATAL_FAILURE(test_subset_good());
241
242 auto test_subset_bad1 = []() {
243 auto poly = bb::Polynomial<FF>::random(4, 10, /*start index*/ 1);
244 // Expand beyond virtual size
245 poly.expand(1, 11);
246 };
247 ASSERT_THROW_OR_ABORT(test_subset_bad1(), ".*new_end_index.*virtual_size.*");
248
249 auto test_subset_bad2 = []() {
250 auto poly = bb::Polynomial<FF>::random(5, 10, /*start index*/ 1);
251 // Expand illegally on start_index
252 poly.expand(2, 7);
253 };
254 ASSERT_THROW_OR_ABORT(test_subset_bad2(), ".*new_start_index.*start_index.*");
255
256 auto test_subset_bad3 = []() {
257 auto poly = bb::Polynomial<FF>::random(5, 10, /*start_index*/ 1);
258 // Expand illegally on end_index
259 poly.expand(1, 3);
260 };
261 ASSERT_THROW_OR_ABORT(test_subset_bad3(), ".*new_end_index.*end_index.*");
262}
263
264#endif
#define ASSERT_THROW_OR_ABORT(statement, matcher)
Definition assert.hpp:149
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
typename Flavor::Polynomial Polynomial
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
TEST(Polynomial, Shifted)