Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
uint256.test.cpp
Go to the documentation of this file.
1#include "uint256.hpp"
2#include "../random/engine.hpp"
3#include <gtest/gtest.h>
4
5using namespace bb;
6using namespace bb::numeric;
7namespace {
9}
10
11TEST(uint256, TestStringConstructors)
12{
13 std::string input = "9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789";
14 const std::string input4("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789");
15
16 const uint256_t result1(input);
17 constexpr uint256_t result2("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789");
18 const uint256_t result3("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789");
19 const uint256_t result4(input4);
20 constexpr uint256_t expected{
21 0xabcdef0123456789,
22 0xfedcba9876543210,
23 0xa0b1c2d3e4f56789,
24 0x9a807b615c4d3e2f,
25 };
26 EXPECT_EQ(result1, result2);
27 EXPECT_EQ(result1, result3);
28 EXPECT_EQ(result1, result4);
29 EXPECT_EQ(result1, expected);
30}
31
32TEST(uint256, GetBit)
33{
34 constexpr uint256_t a{ 0b0110011001110010011001100111001001100110011100100110011001110011,
35 0b1001011101101010101010100100101101101001001010010101110101010111,
36 0b0101010010010101111100001011011010101010110101110110110111010101,
37 0b0101011010101010100010001000101011010101010101010010000100000000 };
38
39 uint256_t res;
40 for (size_t i = 0; i < 256; ++i) {
41 res += a.get_bit(i) ? (uint256_t(1) << i) : 0;
42 }
43
44 EXPECT_EQ(a, res);
45}
46
47TEST(uint256, Add)
48{
49 constexpr uint256_t a{ 1, 2, 3, 4 };
50 constexpr uint256_t b{ 5, 6, 7, 8 };
51
52 constexpr uint256_t c = a + b;
53 uint256_t d = a;
54 d += b;
55 EXPECT_EQ(c.data[0], 6ULL);
56 EXPECT_EQ(c.data[1], 8ULL);
57 EXPECT_EQ(c.data[2], 10ULL);
58 EXPECT_EQ(c.data[3], 12ULL);
59 EXPECT_EQ(d.data[0], 6ULL);
60 EXPECT_EQ(d.data[1], 8ULL);
61 EXPECT_EQ(d.data[2], 10ULL);
62 EXPECT_EQ(d.data[3], 12ULL);
63}
64
65TEST(uint256, GetMsb)
66{
67 uint256_t a{ 0, 0, 1, 1 };
68 uint256_t b{ 1, 0, 1, 0 };
69 uint256_t c{ 0, 1, 0, 0 };
70 uint256_t d{ 1, 0, 0, 0 };
71
72 EXPECT_EQ(a.get_msb(), 192ULL);
73 EXPECT_EQ(b.get_msb(), 128ULL);
74 EXPECT_EQ(c.get_msb(), 64ULL);
75 EXPECT_EQ(d.get_msb(), 0ULL);
76}
77
78TEST(uint256, Mul)
79{
82
83 uint256_t c = (a + b) * (a + b);
84 uint256_t d = (a * a) + (b * b) + (a * b) + (a * b);
85 EXPECT_EQ(c.data[0], d.data[0]);
86 EXPECT_EQ(c.data[1], d.data[1]);
87 EXPECT_EQ(c.data[2], d.data[2]);
88 EXPECT_EQ(c.data[3], d.data[3]);
89}
90
91TEST(uint256, DivAndMod)
92{
93 for (size_t i = 0; i < 256; ++i) {
96
97 b.data[3] = (i > 0) ? 0 : b.data[3];
98 b.data[2] = (i > 1) ? 0 : b.data[2];
99 b.data[1] = (i > 2) ? 0 : b.data[1];
100 uint256_t q = a / b;
101 uint256_t r = a % b;
102
103 uint256_t c = q * b + r;
104 EXPECT_EQ(c.data[0], a.data[0]);
105 EXPECT_EQ(c.data[1], a.data[1]);
106 EXPECT_EQ(c.data[2], a.data[2]);
107 EXPECT_EQ(c.data[3], a.data[3]);
108 }
109
111 uint256_t b = 0;
112
113 uint256_t q = a / b;
114 uint256_t r = a % b;
115
116 EXPECT_EQ(q, uint256_t(0));
117 EXPECT_EQ(r, uint256_t(0));
118
119 b = a;
120 q = a / b;
121 r = a % b;
122
123 EXPECT_EQ(q, uint256_t(1));
124 EXPECT_EQ(r, uint256_t(0));
125}
126
127TEST(uint256, Sub)
128{
131
132 uint256_t c = (a - b) * (a + b);
133 uint256_t d = (a * a) - (b * b);
134
135 EXPECT_EQ(c.data[0], d.data[0]);
136 EXPECT_EQ(c.data[1], d.data[1]);
137 EXPECT_EQ(c.data[2], d.data[2]);
138 EXPECT_EQ(c.data[3], d.data[3]);
139
140 uint256_t e = 0;
141 e = e - 1;
142
143 EXPECT_EQ(e.data[0], UINT64_MAX);
144 EXPECT_EQ(e.data[1], UINT64_MAX);
145 EXPECT_EQ(e.data[2], UINT64_MAX);
146 EXPECT_EQ(e.data[3], UINT64_MAX);
147}
148
149TEST(uint256, RightShift)
150{
151 constexpr uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
152
153 constexpr uint256_t b = a >> 256;
154 EXPECT_EQ(b, uint256_t(0));
155
156 constexpr uint256_t c = a >> 0;
157 EXPECT_EQ(a, c);
158
159 constexpr uint256_t d = a >> 64;
160 EXPECT_EQ(d, uint256_t(0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd, 0));
161
162 constexpr uint256_t e = a >> 123;
163 constexpr uint256_t f = e * (uint256_t{ 0, 1ULL << 59ULL, 0, 0 });
164 EXPECT_EQ(f, uint256_t(0, 0xb800000000000000, 0xcccccccccccccccc, 0xdddddddddddddddd));
165}
166
167TEST(uint256, LeftShift)
168{
169 uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
170
171 uint256_t b = a << 256;
172 EXPECT_EQ(b, uint256_t(0));
173
174 uint256_t c = a << 0;
175 EXPECT_EQ(a, c);
176
177 uint256_t d = a << 64;
178 EXPECT_EQ(d, uint256_t(0, 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc));
179
180 uint256_t e = a << 123;
181 e = e >> 123;
182 EXPECT_EQ(e, uint256_t(0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xc, 0));
183
184 uint256_t large_shift = uint256_t(1) << 64;
185 uint256_t f = a << large_shift;
186 EXPECT_EQ(f, uint256_t(0));
187}
188
189TEST(uint256, And)
190{
193
194 uint256_t c = a & b;
195
196 EXPECT_EQ(c.data[0], a.data[0] & b.data[0]);
197 EXPECT_EQ(c.data[1], a.data[1] & b.data[1]);
198 EXPECT_EQ(c.data[2], a.data[2] & b.data[2]);
199 EXPECT_EQ(c.data[3], a.data[3] & b.data[3]);
200}
201
202TEST(uint256, Or)
203{
206
207 uint256_t c = a | b;
208
209 EXPECT_EQ(c.data[0], a.data[0] | b.data[0]);
210 EXPECT_EQ(c.data[1], a.data[1] | b.data[1]);
211 EXPECT_EQ(c.data[2], a.data[2] | b.data[2]);
212 EXPECT_EQ(c.data[3], a.data[3] | b.data[3]);
213}
214
215TEST(uint256, Xor)
216{
219
220 uint256_t c = a ^ b;
221
222 EXPECT_EQ(c.data[0], a.data[0] ^ b.data[0]);
223 EXPECT_EQ(c.data[1], a.data[1] ^ b.data[1]);
224 EXPECT_EQ(c.data[2], a.data[2] ^ b.data[2]);
225 EXPECT_EQ(c.data[3], a.data[3] ^ b.data[3]);
226}
227
228TEST(uint256, BitNot)
229{
231
232 uint256_t c = ~a;
233
234 EXPECT_EQ(c.data[0], ~a.data[0]);
235 EXPECT_EQ(c.data[1], ~a.data[1]);
236 EXPECT_EQ(c.data[2], ~a.data[2]);
237 EXPECT_EQ(c.data[3], ~a.data[3]);
238}
239
240TEST(uint256, LogicNot)
241{
242 uint256_t a{ 1, 0, 0, 0 };
243
244 bool b = !a;
245
246 EXPECT_EQ(b, false);
247
248 uint256_t c{ 0, 0, 0, 0 };
249
250 EXPECT_EQ(!c, true);
251}
252
253TEST(uint256, Equality)
254{
255 uint256_t a{ 1, 0, 0, 0 };
256 uint256_t b{ 1, 0, 0, 0 };
257 EXPECT_EQ(a == b, true);
258
259 a = uint256_t{ 0, 1, 0, 0 };
260 EXPECT_EQ(a == b, false);
261
262 a = uint256_t{ 0, 0, 1, 0 };
263 EXPECT_EQ(a == b, false);
264
265 a = uint256_t{ 0, 0, 0, 1 };
266 EXPECT_EQ(a == b, false);
267
268 a = uint256_t{ 555, 0, 0, 1 };
269 b = uint256_t{ 535, 0, 0, 1 };
270 EXPECT_EQ(a == b, false);
271}
272
273TEST(uint256, NotEqual)
274{
275 uint256_t a{ 1, 0, 0, 0 };
276 uint256_t b{ 1, 0, 0, 0 };
277 EXPECT_EQ(a != b, false);
278
279 a = uint256_t{ 0, 1, 0, 0 };
280 EXPECT_EQ(a != b, true);
281
282 a = uint256_t{ 0, 0, 1, 0 };
283 EXPECT_EQ(a != b, true);
284
285 a = uint256_t{ 0, 0, 0, 1 };
286 EXPECT_EQ(a != b, true);
287
288 a = uint256_t{ 555, 0, 0, 1 };
289 b = uint256_t{ 535, 0, 0, 1 };
290 EXPECT_EQ(a != b, true);
291}
292
293TEST(uint256, GreaterThan)
294{
295 constexpr uint256_t a{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
296 constexpr uint256_t b{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
297 EXPECT_EQ(a > b, false);
298
299 constexpr uint256_t c = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX - 1 };
300 EXPECT_EQ(a > c, true);
301
302 constexpr uint256_t d = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX - 1, UINT64_MAX };
303 EXPECT_EQ(a > d, true);
304
305 constexpr uint256_t e = uint256_t{ UINT64_MAX, UINT64_MAX - 1, UINT64_MAX, UINT64_MAX };
306 EXPECT_EQ(a > e, true);
307
308 constexpr uint256_t f = uint256_t{ UINT64_MAX - 1, UINT64_MAX, UINT64_MAX, UINT64_MAX };
309 EXPECT_EQ(a > f, true);
310}
311
312TEST(uint256, GreaterThanOrEqual)
313{
314 uint256_t a{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX - 1 };
315 uint256_t b{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
316 EXPECT_EQ(a >= b, false);
317
318 b = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX - 1 };
319 EXPECT_EQ(a > b, false);
320 EXPECT_EQ(a >= b, true);
321
322 b = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX - 1, UINT64_MAX };
323 EXPECT_EQ(a >= b, false);
324
325 a = uint256_t{ UINT64_MAX, UINT64_MAX - 1, UINT64_MAX - 1, UINT64_MAX };
326 EXPECT_EQ(a >= b, false);
327
328 b = uint256_t{ UINT64_MAX - 1, UINT64_MAX, UINT64_MAX, UINT64_MAX };
329 EXPECT_EQ(a >= b, false);
330}
331
332TEST(uint256, ToFromBuffer)
333{
334 uint256_t a{ 1, 2, 3, 4 };
335 auto buf = to_buffer(a);
336 auto b = from_buffer<uint256_t>(buf);
337 EXPECT_EQ(a, b);
338}
339
340// operator bool: verify all limbs are checked (not just data[0])
341TEST(uint256, BoolConversion)
342{
343 EXPECT_FALSE(static_cast<bool>(uint256_t(0)));
344 EXPECT_TRUE(static_cast<bool>(uint256_t(1)));
345 // These cases caught the old bug where only data[0] was checked
346 EXPECT_TRUE(static_cast<bool>(uint256_t{ 0, 1, 0, 0 }));
347 EXPECT_TRUE(static_cast<bool>(uint256_t{ 0, 0, 1, 0 }));
348 EXPECT_TRUE(static_cast<bool>(uint256_t{ 0, 0, 0, 1 }));
349}
350
351// operator uint128_t: verify both lower limbs are preserved
352TEST(uint256, Uint128Conversion)
353{
354 constexpr uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
355 auto lo128 = static_cast<uint128_t>(a);
356 EXPECT_EQ(static_cast<uint64_t>(lo128), 0xaaaaaaaaaaaaaaaa);
357 EXPECT_EQ(static_cast<uint64_t>(lo128 >> 64), 0xbbbbbbbbbbbbbbbb);
358
359 // Verify const objects use the correct overload (not the integral template)
360 const uint256_t b{ 0x1111111111111111, 0x2222222222222222, 0, 0 };
361 auto b128 = static_cast<uint128_t>(b);
362 EXPECT_EQ(static_cast<uint64_t>(b128 >> 64), 0x2222222222222222);
363}
364
365// Addition with carry propagation across all limbs
366TEST(uint256, AddCarryPropagation)
367{
368 // Carry from limb 0 to limb 1
369 uint256_t a{ UINT64_MAX, 0, 0, 0 };
370 uint256_t b{ 1, 0, 0, 0 };
371 uint256_t c = a + b;
372 EXPECT_EQ(c, (uint256_t{ 0, 1, 0, 0 }));
373
374 // Carry propagates through all limbs
375 uint256_t d{ UINT64_MAX, UINT64_MAX, UINT64_MAX, 0 };
376 uint256_t e = d + uint256_t(1);
377 EXPECT_EQ(e, (uint256_t{ 0, 0, 0, 1 }));
378
379 // Full overflow wraps to zero
380 uint256_t f{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
381 uint256_t g = f + uint256_t(1);
382 EXPECT_EQ(g, uint256_t(0));
383}
384
385// mul_extended: verify full 512-bit product is correct
386TEST(uint256, MulExtended)
387{
388 // Simple case: known product
389 uint256_t a{ 0, 0, 0, 1 }; // 2^192
390 uint256_t b{ 0, 0, 0, 1 }; // 2^192
391 auto [lo, hi] = a.mul_extended(b);
392 // 2^192 * 2^192 = 2^384, which is hi.data[2] bit 0
393 EXPECT_EQ(lo, uint256_t(0));
394 EXPECT_EQ(hi, (uint256_t{ 0, 0, 1, 0 }));
395
396 // Verify with random values
399 auto [ab_lo, ab_hi] = a.mul_extended(b);
400
401 // Truncated product should match low half
402 EXPECT_EQ(a * b, ab_lo);
403
404 // Verify commutativity
405 auto [ba_lo, ba_hi] = b.mul_extended(a);
406 EXPECT_EQ(ab_lo, ba_lo);
407 EXPECT_EQ(ab_hi, ba_hi);
408
409 // Verify hi is zero when inputs are small
410 uint256_t small_a{ 0xFFFFFFFF, 0, 0, 0 };
411 uint256_t small_b{ 0xFFFFFFFF, 0, 0, 0 };
412 auto [sm_lo, sm_hi] = small_a.mul_extended(small_b);
413 EXPECT_EQ(sm_hi, uint256_t(0));
414 EXPECT_EQ(sm_lo, small_a * small_b);
415}
416
417// Single-limb divmod
418TEST(uint256, DivModSingleLimb)
419{
420 for (size_t i = 0; i < 64; ++i) {
422 uint64_t b = engine.get_random_uint256().data[0];
423 if (b == 0) {
424 b = 1;
425 }
426 auto [q, r] = a.divmod(b);
427 // Verify roundtrip: q * b + r == a
428 uint256_t reconstructed = q * uint256_t(b) + uint256_t(r);
429 EXPECT_EQ(reconstructed, a);
430 // Remainder must be less than divisor
431 EXPECT_LT(r, b);
432 }
433}
434
435// slice
436TEST(uint256, Slice)
437{
438 constexpr uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
439
440 // Slice bottom 64 bits
441 uint256_t bottom = a.slice(0, 64);
442 EXPECT_EQ(bottom, uint256_t(0xaaaaaaaaaaaaaaaa));
443
444 // Slice bits [64, 128)
445 uint256_t mid = a.slice(64, 128);
446 EXPECT_EQ(mid, uint256_t(0xbbbbbbbbbbbbbbbb));
447
448 // Slice across limb boundary [32, 96)
449 uint256_t cross = a.slice(32, 96);
450 uint256_t expected = (a >> 32) & ((uint256_t(1) << 64) - 1);
451 EXPECT_EQ(cross, expected);
452
453 // Full slice
454 uint256_t full = a.slice(0, 256);
455 EXPECT_EQ(full, a);
456}
457
458// pow
459TEST(uint256, Pow)
460{
461 // x^0 = 1
462 uint256_t a{ 12345, 0, 0, 0 };
463 EXPECT_EQ(a.pow(uint256_t(0)), uint256_t(1));
464
465 // x^1 = x
466 EXPECT_EQ(a.pow(uint256_t(1)), a);
467
468 // 0^n = 0 for n > 0
469 EXPECT_EQ(uint256_t(0).pow(uint256_t(5)), uint256_t(0));
470
471 // 2^10 = 1024
472 EXPECT_EQ(uint256_t(2).pow(uint256_t(10)), uint256_t(1024));
473
474 // 3^20 = 3486784401
475 EXPECT_EQ(uint256_t(3).pow(uint256_t(20)), uint256_t(3486784401ULL));
476
477 // Verify a^2 == a * a for random value
479 EXPECT_EQ(b.pow(uint256_t(2)), b * b);
480
481 // Verify a^3 == a * a * a
482 EXPECT_EQ(b.pow(uint256_t(3)), b * b * b);
483}
virtual uint256_t get_random_uint256()=0
constexpr std::pair< uint256_t, uint256_t > mul_extended(const uint256_t &other) const
Compute the result of multiplication modulu 2**512.
FF a
FF b
uint8_t const * buf
Definition data_store.hpp:9
numeric::RNG & engine
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:217
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
std::vector< uint8_t > to_buffer(T const &value)
unsigned __int128 uint128_t
Definition serialize.hpp:45
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept