Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bool.test.cpp
Go to the documentation of this file.
1#include "bool.hpp"
6#include <gtest/gtest.h>
7#include <tuple>
8
9using namespace bb;
10
11#pragma GCC diagnostic ignored "-Wunused-const-variable"
12
13namespace {
15}
17template <class Builder_> class BoolTest : public ::testing::Test {
18 public:
19 using Builder = Builder_;
22
23 // These tree boolean flags cover all possible combinations for a valid input.
24 struct BoolInput {
25 bool is_const; // witness_index = IS_CONSTANT
26 bool value; // w_a
27 bool is_inverted; // i_a
28 };
29
30 // A helper to produce all possible inputs for a given operand.
33 size_t idx = 0;
34 for (bool is_const : { false, true }) {
35 for (bool value : { false, true }) {
36 for (bool is_inverted : { false, true }) {
37 inputs[idx++] = BoolInput{ is_const, value, is_inverted };
38 }
39 }
40 }
41 return inputs;
42 }();
43 // A helper to create a bool_t element from the given flags
45 {
47 return in.is_inverted ? !b : b;
48 };
49
50 void test_binary_op(std::string const& op_name,
51 const std::function<bool_ct(const bool_ct&, const bool_ct&)>& op,
52 const std::function<bool(bool, bool)>& expected_op)
53 {
55
56 for (auto& lhs : all_inputs) {
57 for (auto& rhs : all_inputs) {
60
61 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
62
63 if (!a.is_constant() && !b.is_constant()) {
64 a.set_origin_tag(submitted_value_origin_tag);
65 b.set_origin_tag(challenge_origin_tag);
66 }
67 bool_ct c = op(a, b);
68
69 bool expected = expected_op(lhs.value ^ lhs.is_inverted, rhs.value ^ rhs.is_inverted);
70
71 EXPECT_EQ(c.get_value(), expected)
72 << "Failed on " << op_name << " with inputs: lhs = {const=" << lhs.is_const << ", val=" << lhs.value
73 << ", inv=" << lhs.is_inverted << "}, rhs = {const=" << rhs.is_const << ", val=" << rhs.value
74 << ", inv=" << rhs.is_inverted << "}";
75
76 if (a.is_constant() && b.is_constant()) {
77 EXPECT_TRUE(c.is_constant());
78 }
79
80 if (!a.is_constant() && !b.is_constant()) {
81 // The result of a binary op on two witnesses must be a witness
82 EXPECT_TRUE(!c.is_constant());
83 // Check that the tags are propagated
84 EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag);
85 }
86
87 size_t diff = builder.get_num_finalized_gates_inefficient() - num_gates_start;
88 // An extra gate is created iff both operands are witnesses
89 EXPECT_EQ(diff, static_cast<size_t>(!a.is_constant() && !b.is_constant()));
90 }
91 }
92
93 EXPECT_TRUE(CircuitChecker::check(builder));
94 };
95
97 {
99 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
100 bool_ct a_true(true);
101 bool_ct a_false(false);
102 EXPECT_TRUE(a_true.get_value());
103 EXPECT_FALSE(a_false.get_value());
104 EXPECT_TRUE(a_true.is_constant() && a_false.is_constant());
105 EXPECT_TRUE(!a_true.is_inverted() && !a_false.is_inverted());
106 // No gates have been added
107 EXPECT_TRUE(num_gates_start == builder.get_num_finalized_gates_inefficient());
108 }
109
111 {
113 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
114 const size_t witness_idx_zero = builder.add_variable(bb::fr(0));
115 const size_t witness_idx_one = builder.add_variable(bb::fr(1));
116 const size_t non_bool_witness_idx = builder.add_variable(bb::fr(15));
117
118 bool_ct bool_witness = bool_ct::from_witness_index_unsafe(&builder, witness_idx_zero);
119 EXPECT_EQ(bool_witness.get_value(), false);
120
121 bool_witness = bool_ct::from_witness_index_unsafe(&builder, witness_idx_one);
122 EXPECT_EQ(bool_witness.get_value(), true);
123 // No gates are added.
124 EXPECT_EQ(builder.get_num_finalized_gates_inefficient() - num_gates_start, 0);
125
126 // Out-of-circuit failure when witness points to a non-bool value.
127 EXPECT_THROW_WITH_MESSAGE(bool_witness = bool_ct::from_witness_index_unsafe(&builder, non_bool_witness_idx),
128 "bool_t: creating a witness bool from a non-boolean value");
129 }
131 {
133 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
134
135 bool_ct a_true = witness_ct(&builder, 1);
136 bool_ct a_false = witness_ct(&builder, 0);
137 EXPECT_TRUE(a_true.get_value());
138 EXPECT_FALSE(a_false.get_value());
139 EXPECT_TRUE(!a_true.is_constant() && !a_false.is_constant());
140 EXPECT_TRUE(!a_true.is_inverted() && !a_false.is_inverted());
141 // Each witness bool must be constrained => expect 2 gates being added
142 EXPECT_TRUE(builder.get_num_finalized_gates_inefficient() - num_gates_start == 2);
143 EXPECT_TRUE(CircuitChecker::check(builder));
144
145 // Test failure
146 bool_ct a_incorrect;
147 uint256_t random_value(engine.get_random_uint256());
148
149 if (random_value * random_value - random_value != 0) {
150 EXPECT_THROW_WITH_MESSAGE(a_incorrect = witness_ct(&builder, random_value),
151 "bool_t: witness value is not 0 or 1");
152 };
153 }
154
156 {
157 const bool use_range_constraint = true;
158
159 for (size_t num_inputs = 1; num_inputs < 50; num_inputs++) {
161 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
162
163 std::vector<uint32_t> indices;
164 for (size_t idx = 0; idx < num_inputs; idx++) {
165 indices.push_back(bool_ct(witness_ct(&builder, idx % 2), use_range_constraint).get_witness_index());
166 }
167
168 // Note: +2 comes from entries added in create_range_list for target_range == 1
169 size_t sorted_list_size = num_inputs + 2;
170 // sorted list is padded to minimum size of 8
171 sorted_list_size = std::max(sorted_list_size, 8UL);
172 // +4 for combination of unconstrained gates and add gates for fixing endpoints
173 size_t fixed_additional_gates = 4;
174 // Delta-range mechanism packs 4 values per gate
175 size_t expected = numeric::ceil_div(sorted_list_size, 4UL) + fixed_additional_gates;
176
177 size_t actual = builder.get_num_finalized_gates_inefficient() - num_gates_start;
178
179 EXPECT_EQ(actual, expected);
180
181 builder.create_unconstrained_gates(indices);
182
183 EXPECT_TRUE(CircuitChecker::check(builder));
184 }
185
186 // Failure test
188 EXPECT_THROW_WITH_MESSAGE([[maybe_unused]] auto new_bool =
189 bool_ct(witness_ct(&builder, 2), use_range_constraint),
190 "bool_t: witness value is not 0 or 1");
191 }
192 void test_AND()
193 {
195 "AND", [](const bool_ct& a, const bool_ct& b) { return a & b; }, [](bool a, bool b) { return a && b; });
196 }
197
198 void test_xor()
199 {
201 "XOR", [](const bool_ct& a, const bool_ct& b) { return a ^ b; }, [](bool a, bool b) { return a ^ b; });
202 }
203
204 void test_OR()
205 {
207 "OR", [](const bool_ct& a, const bool_ct& b) { return a || b; }, [](bool a, bool b) { return a || b; });
208 }
209
210 void test_EQ()
211 {
213 "==", [](const bool_ct& a, const bool_ct& b) { return a == b; }, [](bool a, bool b) { return a == b; });
214 }
215
216 void test_NEQ()
217 {
219 "!=", [](const bool_ct& a, const bool_ct& b) { return a != b; }, [](bool a, bool b) { return a != b; });
220 }
221
223 {
225 "=>",
226 [](const bool_ct& a, const bool_ct& b) { return a.implies(b); },
227 [](bool a, bool b) { return !a || b; });
228 }
229
231 {
233 "<=>",
234 [](const bool_ct& a, const bool_ct& b) { return a.implies_both_ways(b); },
235 [](bool a, bool b) { return !(a ^ b); });
236 }
237
239 {
240
241 for (auto& lhs : all_inputs) {
242 for (auto& rhs : all_inputs) {
244 // Prime the constant cache for FF::one() so that assert_equal_constant against `true`
245 // doesn't charge a one-time fix_witness to the diff below. (zero_idx is pre-cached by the
246 // builder constructor; FF::one() is not.)
247 builder.put_constant_variable(bb::fr::one());
248
251
252 if (a.is_constant() && b.is_constant() && !(!a.get_value() || b.get_value())) {
253 EXPECT_THROW_WITH_MESSAGE(a.must_imply(b), "bool_t::assert_equal: constants are not equal");
254 } else {
255 bool result_is_constant = (!a || b).is_constant();
256
257 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
258
259 if (!a.is_constant() && !b.is_constant()) {
260 a.set_origin_tag(submitted_value_origin_tag);
261 b.set_origin_tag(challenge_origin_tag);
262 }
263 a.must_imply(b);
264 // !a || b
265 // b = 1 =>
266 bool expected = !(lhs.value ^ lhs.is_inverted) || rhs.value ^ rhs.is_inverted;
267
268 size_t diff = builder.get_num_finalized_gates_inefficient() - num_gates_start;
269
270 if (!a.is_constant() && !b.is_constant()) {
271 EXPECT_EQ(diff, 1);
272 }
273 // Due to optimizations, the result of a => b can be a constant, in this case, the the assert_equal
274 // reduces to an out-of-circuit ASSERT
275 if (result_is_constant) {
276 EXPECT_EQ(diff, 0);
277 }
278
279 // No gates are added when one operand is constant
280 if (!result_is_constant && a.is_constant() && !b.is_constant()) {
281 EXPECT_EQ(diff, 0);
282 }
283
284 if (!result_is_constant && !a.is_constant() && b.is_constant()) {
285 EXPECT_EQ(diff, 0);
286 }
287 EXPECT_EQ(CircuitChecker::check(builder), expected);
288 }
289 }
290 }
291 }
292
293 // Helper to compute expected gate count for conditional_assign
295 const bool_ct& condition, const bool_ct& a, const bool_ct& b, const BoolInput& lhs, const BoolInput& rhs)
296 {
297 if (condition.is_constant()) {
298 // Branch 1: Constant predicate - select lhs or rhs, then normalize
299 // Adds 1 gate only if selected value is inverted
300 bool_ct selected = condition.get_value() ? a : b;
301 return (selected.is_inverted()) ? 1 : 0;
302 }
303
304 // Check for Branch 2: same witness (both constants with same value)
305 if (a.is_constant() && b.is_constant() && a.get_value() == b.get_value()) {
306 // Branch 2: Same witness - return lhs.normalize()
307 // Adds 1 gate only if lhs is inverted
308 return (a.is_inverted()) ? 1 : 0;
309 }
310
311 // Branch 3: (predicate && lhs) || (!predicate && rhs), then normalize
312 // Key insight: OR of two witnesses creates a NEW normalized witness (no normalization gate needed)
313 // But OR of witness and constant may return the witness directly (may need normalization)
314
315 if (!a.is_constant() && !b.is_constant()) {
316 // All witnesses: AND + AND + OR = 3 gates
317 // OR creates new normalized witness, so normalize() is no-op
318 return 3;
319 } else if (!a.is_constant()) {
320 // lhs witness, rhs constant
321 // predicate && lhs: 1 gate (creates new witness)
322 // !predicate && rhs:
323 // - if rhs true: returns !predicate (inverted witness if pred was inverted)
324 // - if rhs false: returns false (constant)
325 // OR:
326 // - if rhs false: OR(new_witness, const_false) returns new_witness (no gate, already norm)
327 // - if rhs true: OR(new_witness, inverted_witness) adds 1 gate, creates new normalized witness
328 return b.get_value() ? 2 : 1;
329 } else if (!b.is_constant()) {
330 // lhs constant, rhs witness
331 // !predicate && rhs: 1 gate (creates new witness)
332 // predicate && lhs:
333 // - if lhs true: returns predicate (inverted witness if pred was inverted)
334 // - if lhs false: returns false (constant)
335 // OR:
336 // - if lhs false: OR(const_false, new_witness) returns new_witness (no gate, already norm)
337 // - if lhs true: OR(inverted_witness, new_witness) adds 1 gate, creates new normalized witness
338 return a.get_value() ? 2 : 1;
339 } else {
340 // Both constants: fully optimized
341 // Result is predicate, !predicate, or constant - may need normalization
342 if (lhs.value == rhs.value) {
343 // conditional_assign(pred, T, T) = T or conditional_assign(pred, F, F) = F (constant)
344 return 0;
345 } else if (lhs.value) {
346 // conditional_assign(pred, T, F) = pred
347 // Result is predicate (inverted if pred is inverted)
348 // Normalize adds 1 gate if predicate is inverted
349 return condition.is_inverted() ? 1 : 0;
350 } else {
351 // conditional_assign(pred, F, T) = !pred
352 // Result is !predicate (inverted if pred is NOT inverted)
353 // Normalize adds 1 gate if predicate is NOT inverted
354 return condition.is_inverted() ? 0 : 1;
355 }
356 }
357 }
358
360 {
361 for (auto lhs : all_inputs) {
362 for (auto rhs : all_inputs) {
363 for (auto predicate : all_inputs) {
365
368 bool_ct condition = create_bool_ct(predicate, &builder);
369
370 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
371 if (!a.is_constant() && !b.is_constant()) {
372 condition.set_origin_tag(submitted_value_origin_tag);
373 a.set_origin_tag(challenge_origin_tag);
374 b.set_origin_tag(next_challenge_tag);
375 }
376
377 bool_ct result = bool_ct::conditional_assign(condition, a, b);
378 size_t diff = builder.get_num_finalized_gates_inefficient() - num_gates_start;
379 if (!a.is_constant() && !b.is_constant()) {
380 EXPECT_EQ(result.get_origin_tag(), first_second_third_merged_tag);
381 }
382
383 // Verify correctness
384 bool expected = (condition.get_value()) ? a.get_value() : b.get_value();
385 EXPECT_EQ(result.get_value(), expected);
386
387 // Verify result is always normalized
388 EXPECT_FALSE(result.is_inverted());
389
390 // Pin down gate count for simple cases we can predict
391 if (condition.is_constant() ||
392 (a.is_constant() && b.is_constant() && a.get_value() == b.get_value())) {
393 // Branches 1 & 2: Predictable gate counts
394 size_t expected_gates = compute_conditional_assign_gates(condition, a, b, lhs, rhs);
395 EXPECT_EQ(diff, expected_gates);
396 } else if (!a.is_constant() && !b.is_constant()) {
397 // Branch 3, all witnesses: Always 3 gates (AND + AND + OR)
398 EXPECT_EQ(diff, 3UL);
399 }
400 // For mixed witness/constant cases in branch 3, gate count depends on complex
401 // boolean operator optimizations - we verify normalization instead
402
403 EXPECT_TRUE(CircuitChecker::check(builder));
404 }
405 }
406 }
407 }
408
410 {
411 for (auto a_raw : all_inputs) {
412 auto builder = Builder();
413
414 bool_ct a = create_bool_ct(a_raw, &builder);
415
416 size_t num_gates_start = builder.get_num_finalized_gates_inefficient();
417 if (!a.is_constant()) {
418 a.set_origin_tag(submitted_value_origin_tag);
419 }
420 bool_ct c = a.normalize();
421 EXPECT_EQ(c.get_value(), a.get_value());
422 if (!a.is_constant()) {
423 EXPECT_EQ(c.get_origin_tag(), submitted_value_origin_tag);
424 }
425 EXPECT_EQ(c.is_inverted(), false);
426 size_t diff = builder.get_num_finalized_gates_inefficient() - num_gates_start;
427 // Note that although `normalize()` returns value, it flips the `is_inverted()` flag of `a` if it was
428 // `true`.
429 EXPECT_EQ(diff, static_cast<size_t>(!a.is_constant() && a_raw.is_inverted));
430 EXPECT_TRUE(CircuitChecker::check(builder));
431 }
432 }
433
435 {
436
437 for (auto lhs : all_inputs) {
438 for (auto rhs : all_inputs) {
439
441
444
445 bool failed = a.get_value() != b.get_value();
446
447 if (!a.is_constant() && !b.is_constant()) {
448 a.assert_equal(b);
449 // CircuitChecker is not verifying the permutation relation
450 EXPECT_EQ(builder.failed(), failed);
451 } else if (!a.is_constant() || !b.is_constant()) {
452 a.assert_equal(b);
453 EXPECT_EQ(CircuitChecker::check(builder), !failed);
454 } else {
455 if (failed) {
456 EXPECT_THROW_WITH_MESSAGE(a.assert_equal(b), "bool_t::assert_equal: constants are not equal");
457 }
458 }
459 }
460 }
461 }
462
464 {
465 auto builder = Builder();
466
467 auto gates_before = builder.get_num_finalized_gates_inefficient();
468
471
472 a.set_origin_tag(submitted_value_origin_tag);
473 b.set_origin_tag(challenge_origin_tag);
474
475 a = a ^ b; // a = 1
476 EXPECT_EQ(a.get_value(), 1);
477
478 // Tags are merged on XOR
479 EXPECT_EQ(a.get_origin_tag(), first_two_merged_tag);
480
481 b = !b; // b = 1 (witness 0)
482 EXPECT_EQ(b.get_value(), 1);
483
484 // Tag is preserved on NOT
485 EXPECT_EQ(b.get_origin_tag(), challenge_origin_tag);
486
487 a.set_origin_tag(submitted_value_origin_tag);
488
489 bool_ct d = (a == b); //
490 EXPECT_EQ(d.get_value(), 1);
491
492 // Tags are merged on ==
493 EXPECT_EQ(d.get_origin_tag(), first_two_merged_tag);
494
495 d = false; // d = 0
496 d.set_origin_tag(challenge_origin_tag);
497 EXPECT_EQ(d.get_value(), 0);
498
499 bool_ct e = a | d; // e = 1 = a
500 EXPECT_EQ(e.get_value(), 1);
501
502 // Tags are merged on OR
503 EXPECT_EQ(e.get_origin_tag(), first_two_merged_tag);
504
505 bool_ct f = e ^ b; // f = 0
506 EXPECT_EQ(f.get_value(), 0);
507
508 f.set_origin_tag(challenge_origin_tag);
509 d = (!f) & a; // d = 1
510 EXPECT_EQ(d.get_value(), 1);
511
512 // Tags are merged on AND
513 EXPECT_EQ(d.get_origin_tag(), first_two_merged_tag);
514
515 bool result = CircuitChecker::check(builder);
516 EXPECT_EQ(result, true);
517
518 auto gates_after = builder.get_num_finalized_gates_inefficient();
519 EXPECT_EQ(gates_after - gates_before, 6UL);
520 }
521
522 // Check that (a && (b || c)) ^ (d => f) <=> ((a && b) || (a && c)) ^ (!d || f)) for all inputs.
524 {
525 for (const auto& a_input : all_inputs) {
526 for (const auto& b_input : all_inputs) {
527 for (const auto& c_input : all_inputs) {
528 for (const auto& d_input : all_inputs) {
529 for (const auto& f_input : all_inputs) {
531
532 // Construct bool_cts from inputs
533 bool_ct a = create_bool_ct(a_input, &builder);
534 bool_ct b = create_bool_ct(b_input, &builder);
535 bool_ct c = create_bool_ct(c_input, &builder);
536 bool_ct d = create_bool_ct(d_input, &builder);
537 bool_ct f = create_bool_ct(f_input, &builder);
538
539 // === Formula 1 ===
540 bool_ct lhs = (a && (b || c)) ^ (d.implies(f));
541 bool_ct rhs = ((a && b) || (a && c)) ^ (!d || f);
542
543 // Equivalence check
544 bool_ct equivalent = lhs.implies_both_ways(rhs);
545 if (!equivalent.get_value()) {
546 info("FAIL:");
547 info("a: ", a.get_value(), " b: ", b.get_value(), " c: ", c.get_value());
548 info("d: ", d.get_value(), " f: ", f.get_value());
549 }
550
551 EXPECT_EQ(equivalent.get_value(), true);
552 EXPECT_TRUE(CircuitChecker::check(builder));
553 }
554 }
555 }
556 }
557 }
558 }
559};
560
561using CircuitTypes = ::testing::Types<bb::UltraCircuitBuilder>;
562
564TYPED_TEST(BoolTest, ConstructFromConstBool)
565{
566 TestFixture::test_construct_from_const_bool();
567}
568
569TYPED_TEST(BoolTest, ConstructFromWitness)
570{
571 TestFixture::test_construct_from_witness();
572}
573TYPED_TEST(BoolTest, ConstructFromWitnessRangeConstraint)
574{
575 TestFixture::test_construct_from_witness_range_constraint();
576}
577
578TYPED_TEST(BoolTest, Normalization)
579{
580 TestFixture::test_normalize();
581}
583{
584 TestFixture::test_xor();
585}
586
588{
589 TestFixture::test_AND();
590}
591
593{
594 TestFixture::test_OR();
595}
596
598{
599 TestFixture::test_EQ();
600}
601
603{
604 TestFixture::test_NEQ();
605}
606
608{
609 TestFixture::test_implies();
610}
611
612TYPED_TEST(BoolTest, ImpliesBothWays)
613{
614 TestFixture::test_implies_both_ways();
615}
616
618{
619 TestFixture::test_must_imply();
620}
621
622TYPED_TEST(BoolTest, ConditionalAssign)
623{
624 TestFixture::test_conditional_assign();
625}
626
627TYPED_TEST(BoolTest, TestBasicOperationsTags)
628{
629 TestFixture::test_basic_operations_tags();
630}
631
632TYPED_TEST(BoolTest, TestSimpleProof)
633{
634 TestFixture::test_simple_proof();
635}
636TYPED_TEST(BoolTest, AssertEqual)
637{
638 TestFixture::test_assert_equal();
639}
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
void test_xor()
void test_construct_from_witness_index()
void test_implies_both_ways()
void test_normalize()
void test_implies()
void test_NEQ()
void test_conditional_assign()
void test_binary_op(std::string const &op_name, const std::function< bool_ct(const bool_ct &, const bool_ct &)> &op, const std::function< bool(bool, bool)> &expected_op)
Definition bool.test.cpp:50
void test_OR()
void test_AND()
void test_must_imply()
Builder_ Builder
Definition bool.test.cpp:19
void test_basic_operations_tags()
void test_simple_proof()
void test_construct_from_const_bool()
Definition bool.test.cpp:96
static size_t compute_conditional_assign_gates(const bool_ct &condition, const bool_ct &a, const bool_ct &b, const BoolInput &lhs, const BoolInput &rhs)
std::array< BoolInput, 8 > all_inputs
Definition bool.test.cpp:31
void test_EQ()
void test_construct_from_witness_range_constraint()
stdlib::witness_t< Builder > witness_ct
Definition bool.test.cpp:20
void test_construct_from_witness()
static bool_ct create_bool_ct(const BoolInput &in, Builder *builder)
Definition bool.test.cpp:44
void test_assert_equal()
stdlib::bool_t< Builder > bool_ct
Definition bool.test.cpp:21
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
virtual uint256_t get_random_uint256()=0
Implements boolean logic in-circuit.
Definition bool.hpp:60
bool get_value() const
Definition bool.hpp:125
bool is_constant() const
Definition bool.hpp:127
void set_origin_tag(const OriginTag &new_tag) const
Definition bool.hpp:154
bool_t implies(const bool_t &other) const
Implements implication operator in circuit.
Definition bool.cpp:502
bool is_inverted() const
Definition bool.hpp:128
static bool_t conditional_assign(const bool_t< Builder > &predicate, const bool_t &lhs, const bool_t &rhs)
Conditionally assign lhs or rhs based on predicate, always returns normalized result.
Definition bool.cpp:478
static bool_t from_witness_index_unsafe(Builder *ctx, uint32_t witness_index)
Create a bool_t from a witness index that is known to contain a constrained bool value.
Definition bool.cpp:104
bool_t implies_both_ways(const bool_t &other) const
Implements a "double-implication" (<=>), a.k.a "iff", a.k.a. "biconditional".
Definition bool.cpp:519
OriginTag get_origin_tag() const
Definition bool.hpp:155
#define info(...)
Definition log.hpp:93
AluTraceBuilder builder
Definition alu.test.cpp:124
FF a
FF b
numeric::RNG & engine
AvmProvingInputs inputs
constexpr T ceil_div(const T &numerator, const T &denominator)
Computes the ceiling of the division of two integral types.
Definition general.hpp:23
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
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
#define STANDARD_TESTING_TAGS
testing::Types< bb::MegaCircuitBuilder, bb::UltraCircuitBuilder > CircuitTypes
static constexpr field one()
static constexpr field zero()