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 if (b == 0) {
101 b = 1;
102 }
103 uint256_t q = a / b;
104 uint256_t r = a % b;
105
106 uint256_t c = q * b + r;
107 EXPECT_EQ(c.data[0], a.data[0]);
108 EXPECT_EQ(c.data[1], a.data[1]);
109 EXPECT_EQ(c.data[2], a.data[2]);
110 EXPECT_EQ(c.data[3], a.data[3]);
111 }
112
114 uint256_t b = a;
115 uint256_t q = a / b;
116 uint256_t r = a % b;
117
118 EXPECT_EQ(q, uint256_t(1));
119 EXPECT_EQ(r, uint256_t(0));
120}
121
122TEST(uint256, Sub)
123{
126
127 uint256_t c = (a - b) * (a + b);
128 uint256_t d = (a * a) - (b * b);
129
130 EXPECT_EQ(c.data[0], d.data[0]);
131 EXPECT_EQ(c.data[1], d.data[1]);
132 EXPECT_EQ(c.data[2], d.data[2]);
133 EXPECT_EQ(c.data[3], d.data[3]);
134
135 uint256_t e = 0;
136 e = e - 1;
137
138 EXPECT_EQ(e.data[0], UINT64_MAX);
139 EXPECT_EQ(e.data[1], UINT64_MAX);
140 EXPECT_EQ(e.data[2], UINT64_MAX);
141 EXPECT_EQ(e.data[3], UINT64_MAX);
142}
143
144TEST(uint256, RightShift)
145{
146 constexpr uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
147
148 constexpr uint256_t b = a >> 256;
149 EXPECT_EQ(b, uint256_t(0));
150
151 constexpr uint256_t c = a >> 0;
152 EXPECT_EQ(a, c);
153
154 constexpr uint256_t d = a >> 64;
155 EXPECT_EQ(d, uint256_t(0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd, 0));
156
157 constexpr uint256_t e = a >> 123;
158 constexpr uint256_t f = e * (uint256_t{ 0, 1ULL << 59ULL, 0, 0 });
159 EXPECT_EQ(f, uint256_t(0, 0xb800000000000000, 0xcccccccccccccccc, 0xdddddddddddddddd));
160}
161
162TEST(uint256, LeftShift)
163{
164 uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
165
166 uint256_t b = a << 256;
167 EXPECT_EQ(b, uint256_t(0));
168
169 uint256_t c = a << 0;
170 EXPECT_EQ(a, c);
171
172 uint256_t d = a << 64;
173 EXPECT_EQ(d, uint256_t(0, 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc));
174
175 uint256_t e = a << 123;
176 e = e >> 123;
177 EXPECT_EQ(e, uint256_t(0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xc, 0));
178
179 uint256_t large_shift = uint256_t(1) << 64;
180 uint256_t f = a << large_shift;
181 EXPECT_EQ(f, uint256_t(0));
182}
183
184TEST(uint256, And)
185{
188
189 uint256_t c = a & b;
190
191 EXPECT_EQ(c.data[0], a.data[0] & b.data[0]);
192 EXPECT_EQ(c.data[1], a.data[1] & b.data[1]);
193 EXPECT_EQ(c.data[2], a.data[2] & b.data[2]);
194 EXPECT_EQ(c.data[3], a.data[3] & b.data[3]);
195}
196
197TEST(uint256, Or)
198{
201
202 uint256_t c = a | b;
203
204 EXPECT_EQ(c.data[0], a.data[0] | b.data[0]);
205 EXPECT_EQ(c.data[1], a.data[1] | b.data[1]);
206 EXPECT_EQ(c.data[2], a.data[2] | b.data[2]);
207 EXPECT_EQ(c.data[3], a.data[3] | b.data[3]);
208}
209
210TEST(uint256, Xor)
211{
214
215 uint256_t c = a ^ b;
216
217 EXPECT_EQ(c.data[0], a.data[0] ^ b.data[0]);
218 EXPECT_EQ(c.data[1], a.data[1] ^ b.data[1]);
219 EXPECT_EQ(c.data[2], a.data[2] ^ b.data[2]);
220 EXPECT_EQ(c.data[3], a.data[3] ^ b.data[3]);
221}
222
223TEST(uint256, BitNot)
224{
226
227 uint256_t c = ~a;
228
229 EXPECT_EQ(c.data[0], ~a.data[0]);
230 EXPECT_EQ(c.data[1], ~a.data[1]);
231 EXPECT_EQ(c.data[2], ~a.data[2]);
232 EXPECT_EQ(c.data[3], ~a.data[3]);
233}
234
235TEST(uint256, LogicNot)
236{
237 uint256_t a{ 1, 0, 0, 0 };
238
239 bool b = !a;
240
241 EXPECT_EQ(b, false);
242
243 uint256_t c{ 0, 0, 0, 0 };
244
245 EXPECT_EQ(!c, true);
246}
247
248TEST(uint256, Equality)
249{
250 uint256_t a{ 1, 0, 0, 0 };
251 uint256_t b{ 1, 0, 0, 0 };
252 EXPECT_EQ(a == b, true);
253
254 a = uint256_t{ 0, 1, 0, 0 };
255 EXPECT_EQ(a == b, false);
256
257 a = uint256_t{ 0, 0, 1, 0 };
258 EXPECT_EQ(a == b, false);
259
260 a = uint256_t{ 0, 0, 0, 1 };
261 EXPECT_EQ(a == b, false);
262
263 a = uint256_t{ 555, 0, 0, 1 };
264 b = uint256_t{ 535, 0, 0, 1 };
265 EXPECT_EQ(a == b, false);
266}
267
268TEST(uint256, NotEqual)
269{
270 uint256_t a{ 1, 0, 0, 0 };
271 uint256_t b{ 1, 0, 0, 0 };
272 EXPECT_EQ(a != b, false);
273
274 a = uint256_t{ 0, 1, 0, 0 };
275 EXPECT_EQ(a != b, true);
276
277 a = uint256_t{ 0, 0, 1, 0 };
278 EXPECT_EQ(a != b, true);
279
280 a = uint256_t{ 0, 0, 0, 1 };
281 EXPECT_EQ(a != b, true);
282
283 a = uint256_t{ 555, 0, 0, 1 };
284 b = uint256_t{ 535, 0, 0, 1 };
285 EXPECT_EQ(a != b, true);
286}
287
288TEST(uint256, GreaterThan)
289{
290 constexpr uint256_t a{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
291 constexpr uint256_t b{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
292 EXPECT_EQ(a > b, false);
293
294 constexpr uint256_t c = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX - 1 };
295 EXPECT_EQ(a > c, true);
296
297 constexpr uint256_t d = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX - 1, UINT64_MAX };
298 EXPECT_EQ(a > d, true);
299
300 constexpr uint256_t e = uint256_t{ UINT64_MAX, UINT64_MAX - 1, UINT64_MAX, UINT64_MAX };
301 EXPECT_EQ(a > e, true);
302
303 constexpr uint256_t f = uint256_t{ UINT64_MAX - 1, UINT64_MAX, UINT64_MAX, UINT64_MAX };
304 EXPECT_EQ(a > f, true);
305}
306
307TEST(uint256, GreaterThanOrEqual)
308{
309 uint256_t a{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX - 1 };
310 uint256_t b{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
311 EXPECT_EQ(a >= b, false);
312
313 b = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX - 1 };
314 EXPECT_EQ(a > b, false);
315 EXPECT_EQ(a >= b, true);
316
317 b = uint256_t{ UINT64_MAX, UINT64_MAX, UINT64_MAX - 1, UINT64_MAX };
318 EXPECT_EQ(a >= b, false);
319
320 a = uint256_t{ UINT64_MAX, UINT64_MAX - 1, UINT64_MAX - 1, UINT64_MAX };
321 EXPECT_EQ(a >= b, false);
322
323 b = uint256_t{ UINT64_MAX - 1, UINT64_MAX, UINT64_MAX, UINT64_MAX };
324 EXPECT_EQ(a >= b, false);
325}
326
327TEST(uint256, ToFromBuffer)
328{
329 uint256_t a{ 1, 2, 3, 4 };
330 auto buf = to_buffer(a);
331 auto b = from_buffer<uint256_t>(buf);
332 EXPECT_EQ(a, b);
333}
334
335// operator bool: verify all limbs are checked (not just data[0])
336TEST(uint256, BoolConversion)
337{
338 EXPECT_FALSE(static_cast<bool>(uint256_t(0)));
339 EXPECT_TRUE(static_cast<bool>(uint256_t(1)));
340 // These cases caught the old bug where only data[0] was checked
341 EXPECT_TRUE(static_cast<bool>(uint256_t{ 0, 1, 0, 0 }));
342 EXPECT_TRUE(static_cast<bool>(uint256_t{ 0, 0, 1, 0 }));
343 EXPECT_TRUE(static_cast<bool>(uint256_t{ 0, 0, 0, 1 }));
344}
345
346// operator uint128_t: verify both lower limbs are preserved
347TEST(uint256, Uint128Conversion)
348{
349 constexpr uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
350 auto lo128 = static_cast<uint128_t>(a);
351 EXPECT_EQ(static_cast<uint64_t>(lo128), 0xaaaaaaaaaaaaaaaa);
352 EXPECT_EQ(static_cast<uint64_t>(lo128 >> 64), 0xbbbbbbbbbbbbbbbb);
353
354 // Verify const objects use the correct overload (not the integral template)
355 const uint256_t b{ 0x1111111111111111, 0x2222222222222222, 0, 0 };
356 auto b128 = static_cast<uint128_t>(b);
357 EXPECT_EQ(static_cast<uint64_t>(b128 >> 64), 0x2222222222222222);
358}
359
360// Addition with carry propagation across all limbs
361TEST(uint256, AddCarryPropagation)
362{
363 // Carry from limb 0 to limb 1
364 uint256_t a{ UINT64_MAX, 0, 0, 0 };
365 uint256_t b{ 1, 0, 0, 0 };
366 uint256_t c = a + b;
367 EXPECT_EQ(c, (uint256_t{ 0, 1, 0, 0 }));
368
369 // Carry propagates through all limbs
370 uint256_t d{ UINT64_MAX, UINT64_MAX, UINT64_MAX, 0 };
371 uint256_t e = d + uint256_t(1);
372 EXPECT_EQ(e, (uint256_t{ 0, 0, 0, 1 }));
373
374 // Full overflow wraps to zero
375 uint256_t f{ UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX };
376 uint256_t g = f + uint256_t(1);
377 EXPECT_EQ(g, uint256_t(0));
378}
379
380// mul_extended: verify full 512-bit product is correct
381TEST(uint256, MulExtended)
382{
383 // Simple case: known product
384 uint256_t a{ 0, 0, 0, 1 }; // 2^192
385 uint256_t b{ 0, 0, 0, 1 }; // 2^192
386 auto [lo, hi] = a.mul_extended(b);
387 // 2^192 * 2^192 = 2^384, which is hi.data[2] bit 0
388 EXPECT_EQ(lo, uint256_t(0));
389 EXPECT_EQ(hi, (uint256_t{ 0, 0, 1, 0 }));
390
391 // Verify with random values
394 auto [ab_lo, ab_hi] = a.mul_extended(b);
395
396 // Truncated product should match low half
397 EXPECT_EQ(a * b, ab_lo);
398
399 // Verify commutativity
400 auto [ba_lo, ba_hi] = b.mul_extended(a);
401 EXPECT_EQ(ab_lo, ba_lo);
402 EXPECT_EQ(ab_hi, ba_hi);
403
404 // Verify hi is zero when inputs are small
405 uint256_t small_a{ 0xFFFFFFFF, 0, 0, 0 };
406 uint256_t small_b{ 0xFFFFFFFF, 0, 0, 0 };
407 auto [sm_lo, sm_hi] = small_a.mul_extended(small_b);
408 EXPECT_EQ(sm_hi, uint256_t(0));
409 EXPECT_EQ(sm_lo, small_a * small_b);
410}
411
412// Single-limb divmod
413TEST(uint256, DivModSingleLimb)
414{
415 for (size_t i = 0; i < 64; ++i) {
417 uint64_t b = engine.get_random_uint256().data[0];
418 if (b == 0) {
419 b = 1;
420 }
421 auto [q, r] = a.divmod(b);
422 // Verify roundtrip: q * b + r == a
423 uint256_t reconstructed = q * uint256_t(b) + uint256_t(r);
424 EXPECT_EQ(reconstructed, a);
425 // Remainder must be less than divisor
426 EXPECT_LT(r, b);
427 }
428}
429
430// slice
431TEST(uint256, Slice)
432{
433 constexpr uint256_t a{ 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc, 0xdddddddddddddddd };
434
435 // Slice bottom 64 bits
436 uint256_t bottom = a.slice(0, 64);
437 EXPECT_EQ(bottom, uint256_t(0xaaaaaaaaaaaaaaaa));
438
439 // Slice bits [64, 128)
440 uint256_t mid = a.slice(64, 128);
441 EXPECT_EQ(mid, uint256_t(0xbbbbbbbbbbbbbbbb));
442
443 // Slice across limb boundary [32, 96)
444 uint256_t cross = a.slice(32, 96);
445 uint256_t expected = (a >> 32) & ((uint256_t(1) << 64) - 1);
446 EXPECT_EQ(cross, expected);
447
448 // Full slice
449 uint256_t full = a.slice(0, 256);
450 EXPECT_EQ(full, a);
451}
452
453// pow
454TEST(uint256, Pow)
455{
456 // x^0 = 1
457 uint256_t a{ 12345, 0, 0, 0 };
458 EXPECT_EQ(a.pow(uint256_t(0)), uint256_t(1));
459
460 // x^1 = x
461 EXPECT_EQ(a.pow(uint256_t(1)), a);
462
463 // 0^n = 0 for n > 0
464 EXPECT_EQ(uint256_t(0).pow(uint256_t(5)), uint256_t(0));
465
466 // 2^10 = 1024
467 EXPECT_EQ(uint256_t(2).pow(uint256_t(10)), uint256_t(1024));
468
469 // 3^20 = 3486784401
470 EXPECT_EQ(uint256_t(3).pow(uint256_t(20)), uint256_t(3486784401ULL));
471
472 // Verify a^2 == a * a for random value
474 EXPECT_EQ(b.pow(uint256_t(2)), b * b);
475
476 // Verify a^3 == a * a * a
477 EXPECT_EQ(b.pow(uint256_t(3)), b * b * b);
478}
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
numeric::RNG & engine
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:245
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