7#include <gtest/gtest.h>
22constexpr std::array<size_t, 9> kSizes{ 0, 1, 4, 5, 6, 9, 10, 25, 31 };
26TEST(VectorFieldPushSpan, PushReadRoundTrip)
28 constexpr size_t W = PushSpanFq::W;
29 for (
size_t n : kSizes) {
32 v = fq::random_element(&
engine);
36 for (
const auto& v : src) {
40 ASSERT_EQ(span.size(), n);
41 ASSERT_EQ(span.num_full_vectors(), n / W);
42 ASSERT_EQ(span.tail(), n % W);
44 for (
size_t i = 0; i < n; ++i) {
46 if (i < span.num_full_vectors() * W) {
47 got = span[i / W].to_array()[i % W];
49 got = span.tail_data()[i % W];
51 EXPECT_EQ(got, src[i]) <<
"n=" << n <<
" i=" << i;
57TEST(VectorFieldPushSpan, ResetRefill)
59 constexpr size_t W = PushSpanFq::W;
62 for (
size_t i = 0; i < 7; ++i) {
66 EXPECT_EQ(span.size(), 0u);
67 EXPECT_EQ(span.tail(), 0u);
71 v = fq::random_element(&
engine);
73 for (
const auto& v : src) {
76 for (
size_t i = 0; i < src.size(); ++i) {
77 EXPECT_EQ(span[i / W].to_array()[i % W], src[i]);
84TEST(VectorFieldPushSpan, GroupwiseMatchesScalar)
86 constexpr size_t W = PushSpanFq::W;
87 const size_t n = 4 * W;
89 for (
size_t i = 0; i < n; ++i) {
90 a[i] = fq::random_element(&
engine);
91 b[i] = fq::random_element(&
engine);
92 c[i] =
a[i] *
b[i] +
a[i];
99 for (
size_t i = 0; i < n; ++i) {
104 for (
size_t g = 0;
g < sa.num_full_vectors(); ++
g) {
105 sc[
g] = sa[
g] * sb[
g] + sa[
g];
107 for (
size_t i = 0; i < n; ++i) {
108 EXPECT_EQ(sc[i / W].to_array()[i % W], c[i]) <<
"i=" << i;
114TEST(VectorFieldPushSpan, ZipForEach)
116 constexpr size_t W = PushSpanFq::W;
117 const size_t n = 2 * W + 3;
121 for (
size_t i = 0; i < n; ++i) {
122 a[i] = fq::random_element(&
engine);
123 b[i] = fq::random_element(&
engine);
124 ref[i] =
a[i] *
b[i] +
a[i];
132 for (
size_t i = 0; i < n; ++i) {
137 bb::zip_for_each(sa, sb, so, [](
const auto& x,
const auto& y,
auto& o) { o = x * y + x; });
140 ASSERT_EQ(so.size(), n);
141 for (
size_t i = 0; i < n; ++i) {
142 const fq got = (i < so.num_full_vectors() * W) ? so[i / W].to_array()[i % W] : so.tail_data()[i % W];
143 EXPECT_EQ(got, ref[i]) <<
"i=" << i;
148TEST(VectorAffineElementPushSpan, PushPointRoundTrip)
151 constexpr size_t W = PushSpanFq::W;
152 const size_t n = 2 * W + 3;
156 for (
size_t i = 0; i < n; ++i) {
157 xs[i] = fq::random_element(&
engine);
158 ys[i] = fq::random_element(&
engine);
159 packed.push_point(xs[i], ys[i]);
161 ASSERT_EQ(packed.size(), n);
162 for (
size_t i = 0; i < n; ++i) {
163 fq gx_i = (i < packed.num_full_vectors() * W) ? packed.x[i / W].to_array()[i % W] : packed.x.tail_data()[i % W];
164 fq gy_i = (i < packed.num_full_vectors() * W) ? packed.y[i / W].to_array()[i % W] : packed.y.tail_data()[i % W];
165 EXPECT_EQ(gx_i, xs[i]);
166 EXPECT_EQ(gy_i, ys[i]);
171TEST(VectorFieldPushSpan, RoundTripFr)
173 constexpr size_t W = PushSpanFr::W;
174 const size_t n = 3 * W + 2;
175 std::vector<fr> src(n);
178 for (
auto& v : src) {
182 for (
size_t i = 0; i < n; ++i) {
183 fr got = (i < span.num_full_vectors() * W) ? span[i / W].to_array()[i % W] : span.tail_data()[i % W];
184 EXPECT_EQ(got, src[i]);
190TEST(VectorFieldPushSpan, AliasesSelfAtEveryFillLevel)
192 constexpr size_t W = PushSpanFq::W;
193 for (
size_t n : {
size_t{ 0 }, W - 1, W, W + 1 }) {
196 for (
size_t i = 0; i < n; ++i) {
197 span.push(fq::random_element(&
engine));
199 EXPECT_TRUE(span.aliases(span)) <<
"n=" << n;
205TEST(VectorFieldPushSpan, AliasesDistinctSpansSharingBacking)
207 constexpr size_t W = PushSpanFq::W;
212 EXPECT_TRUE(
a.shares_backing(
b));
213 EXPECT_FALSE(
a.aliases(
b));
215 for (
size_t i = 0; i < W - 1; ++i) {
216 a.push(fq::random_element(&
engine));
218 EXPECT_FALSE(
a.aliases(
b));
220 a.push(fq::random_element(&
engine));
221 EXPECT_TRUE(
a.aliases(
b));
224TEST(VectorFieldPushSpan, SharesBackingDisjointVsSameStart)
226 constexpr size_t W = PushSpanFq::W;
232 EXPECT_FALSE(
a.shares_backing(
b));
233 EXPECT_TRUE(
a.shares_backing(a_view));
235 for (
size_t i = 0; i < W; ++i) {
236 a.push(fq::random_element(&
engine));
238 EXPECT_FALSE(
a.aliases(
b));
244TEST(VectorFieldPushSpan, AliasesMissesOffsetOverlap)
246 constexpr size_t W = PushSpanFq::W;
250 for (
size_t i = 0; i < 4 * W; ++i) {
251 a.push(fq::random_element(&
engine));
253 EXPECT_FALSE(
a.shares_backing(
b));
254 EXPECT_FALSE(
a.aliases(
b));
259TEST(VectorFieldPushSpan, ZipForEachAutoAdoptsOutputCursor)
261 constexpr size_t W = PushSpanFq::W;
262 const size_t n = 2 * W + 3;
264 for (
size_t i = 0; i < n; ++i) {
265 a[i] = fq::random_element(&
engine);
266 b[i] = fq::random_element(&
engine);
267 ref[i] =
a[i] *
b[i] +
a[i];
273 for (
size_t i = 0; i < n; ++i) {
278 bb::zip_for_each(sa, sb, so, [](
const auto& x,
const auto& y,
auto& o) { o = x * y + x; });
280 EXPECT_EQ(so.size(), n);
281 EXPECT_EQ(so.num_full_vectors(), n / W);
282 EXPECT_EQ(so.tail(), n % W);
283 for (
size_t i = 0; i < n; ++i) {
284 const fq got = (i < so.num_full_vectors() * W) ? so[i / W].to_array()[i % W] : so.tail_data()[i % W];
285 EXPECT_EQ(got, ref[i]) <<
"i=" << i;
291TEST(VectorFieldPushSpan, MapAccumulateForwardExclusivePrefixProduct)
293 constexpr size_t W = PushSpanFq::W;
294 const size_t n = 2 * W;
299 for (
size_t i = 0; i < n; ++i) {
300 src[i] = fq::random_element(&
engine);
304 auto [bulk_acc, tail_acc] = bb::map_accumulate<bb::Direction::Forward>(
305 in,
out, VecFq::broadcast(fq::one()), fq::one(), [](
auto& acc,
const auto& in_e,
auto& out_e) {
310 ASSERT_EQ(
out.size(), n);
311 ASSERT_EQ(
out.num_full_vectors(), 2u);
312 for (
size_t L = 0; L < W; ++L) {
313 EXPECT_EQ(
out[0].to_array()[L], fq::one()) <<
"L=" << L;
314 EXPECT_EQ(
out[1].to_array()[L], src[L]) <<
"L=" << L;
315 EXPECT_EQ(bulk_acc.to_array()[L], src[L] * src[W + L]) <<
"L=" << L;
317 EXPECT_EQ(tail_acc, fq::one());
321TEST(VectorFieldPushSpan, MapAccumulateReverseExclusivePrefixProduct)
323 constexpr size_t W = PushSpanFq::W;
324 const size_t n = 2 * W;
329 for (
size_t i = 0; i < n; ++i) {
330 src[i] = fq::random_element(&
engine);
334 auto [bulk_acc, tail_acc] = bb::map_accumulate<bb::Direction::Backward>(
335 in,
out, VecFq::broadcast(fq::one()), fq::one(), [](
auto& acc,
const auto& in_e,
auto& out_e) {
340 ASSERT_EQ(
out.size(), n);
341 for (
size_t L = 0; L < W; ++L) {
342 EXPECT_EQ(
out[1].to_array()[L], fq::one()) <<
"L=" << L;
343 EXPECT_EQ(
out[0].to_array()[L], src[W + L]) <<
"L=" << L;
344 EXPECT_EQ(bulk_acc.to_array()[L], src[W + L] * src[L]) <<
"L=" << L;
346 EXPECT_EQ(tail_acc, fq::one());
351TEST(VectorFieldPushSpan, MapAccumulateThreadsTailAccumulator)
353 constexpr size_t W = PushSpanFq::W;
354 const size_t n = W + 2;
359 for (
size_t i = 0; i < n; ++i) {
360 src[i] = fq::random_element(&
engine);
364 auto [bulk_acc, tail_acc] = bb::map_accumulate<bb::Direction::Forward>(
365 in,
out, VecFq::broadcast(fq::one()), fq::one(), [](
auto& acc,
const auto& in_e,
auto& out_e) {
370 ASSERT_EQ(
out.size(), n);
371 ASSERT_EQ(
out.tail(), 2u);
372 for (
size_t L = 0; L < W; ++L) {
373 EXPECT_EQ(
out[0].to_array()[L], fq::one()) <<
"L=" << L;
374 EXPECT_EQ(bulk_acc.to_array()[L], src[L]) <<
"L=" << L;
376 EXPECT_EQ(
out.tail_data()[0], fq::one());
377 EXPECT_EQ(
out.tail_data()[1], src[W]);
378 EXPECT_EQ(tail_acc, src[W] * src[W + 1]);
382TEST(VectorFieldPushSpan, IsMoveOnly)
TEST(acir_formal_proofs, uint_terms_add)
Tests 128-bit unsigned addition Verifies that the ACIR implementation of addition is correct Executio...
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
field< Bn254FqParams > fq
void zip_for_each(Args &&... args)
constexpr void g(state_array &state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
bb::VectorAffineElementPushSpan< BaseParams > out
static field random_element(numeric::RNG *engine=nullptr) noexcept