1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
29using ::testing::Return;
30using ::testing::StrictMock;
32using tracegen::ExecutionTraceBuilder;
33using tracegen::GreaterThanTraceBuilder;
34using tracegen::PrecomputedTraceBuilder;
35using tracegen::TestTraceContainer;
36using tracegen::ToRadixTraceBuilder;
42using ToRadixSimulator = simulation::ToRadix;
44using simulation::EventEmitter;
45using simulation::GreaterThan;
46using simulation::GreaterThanEvent;
47using simulation::MockExecutionIdManager;
48using simulation::MockFieldGreaterThan;
49using simulation::NoopEventEmitter;
50using simulation::PureGreaterThan;
51using simulation::RangeCheck;
52using simulation::RangeCheckEvent;
53using simulation::ToRadixEvent;
54using simulation::ToRadixMemoryEvent;
56TEST(ToRadixConstrainingTest, EmptyRow)
61TEST(ToRadixConstrainingTest, ToLeBitsBasicTest)
63 EventEmitter<ToRadixEvent> to_radix_event_emitter;
64 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
68 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
70 auto [bits, truncated] = to_radix_simulator.to_le_bits(FF::one(), 254);
72 EXPECT_EQ(bits.size(), 254);
73 EXPECT_FALSE(truncated);
75 TestTraceContainer
trace({
76 { { C::precomputed_first_row, 1 } },
82 check_relation<to_radix>(
trace);
85TEST(ToRadixConstrainingTest, ToLeBitsPMinusOne)
87 EventEmitter<ToRadixEvent> to_radix_event_emitter;
88 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
92 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
94 auto [bits, truncated] = to_radix_simulator.to_le_bits(FF::neg_one(), 254);
96 EXPECT_EQ(bits.size(), 254);
97 EXPECT_FALSE(truncated);
99 TestTraceContainer
trace({
100 { { C::precomputed_first_row, 1 } },
106 check_relation<to_radix>(
trace);
109TEST(ToRadixConstrainingTest, ToLeBitsShortest)
111 EventEmitter<ToRadixEvent> to_radix_event_emitter;
112 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
116 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
118 auto [bits, truncated] = to_radix_simulator.to_le_bits(FF::one(), 1);
120 EXPECT_EQ(bits.size(), 1);
121 EXPECT_FALSE(truncated);
123 TestTraceContainer
trace({
124 { { C::precomputed_first_row, 1 } },
130 check_relation<to_radix>(
trace);
133TEST(ToRadixConstrainingTest, ToLeBitsPadded)
135 EventEmitter<ToRadixEvent> to_radix_event_emitter;
136 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
140 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
142 auto [bits, truncated] = to_radix_simulator.to_le_bits(FF::one(), 500);
144 EXPECT_EQ(bits.size(), 500);
145 EXPECT_FALSE(truncated);
147 TestTraceContainer
trace({
148 { { C::precomputed_first_row, 1 } },
154 check_relation<to_radix>(
trace);
157TEST(ToRadixConstrainingTest, ToLeRadixBasic)
159 EventEmitter<ToRadixEvent> to_radix_event_emitter;
160 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
164 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
167 auto [bytes, truncated] = to_radix_simulator.to_le_radix(
value, 32, 256);
169 auto expected_bytes =
value.to_buffer();
171 std::reverse(expected_bytes.begin(), expected_bytes.end());
172 EXPECT_EQ(bytes, expected_bytes);
173 EXPECT_FALSE(truncated);
175 TestTraceContainer
trace({
176 { { C::precomputed_first_row, 1 } },
182 check_relation<to_radix>(
trace);
185TEST(ToRadixConstrainingTest, ToLeRadixPMinusOne)
187 EventEmitter<ToRadixEvent> to_radix_event_emitter;
188 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
192 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
195 auto [bytes, truncated] = to_radix_simulator.to_le_radix(
value, 32, 256);
197 auto expected_bytes =
value.to_buffer();
199 std::reverse(expected_bytes.begin(), expected_bytes.end());
200 EXPECT_EQ(bytes, expected_bytes);
201 EXPECT_FALSE(truncated);
203 TestTraceContainer
trace({
204 { { C::precomputed_first_row, 1 } },
210 check_relation<to_radix>(
trace);
213TEST(ToRadixConstrainingTest, ToLeRadixOneByte)
215 EventEmitter<ToRadixEvent> to_radix_event_emitter;
216 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
220 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
222 auto [bytes, truncated] = to_radix_simulator.to_le_radix(FF::one(), 1, 256);
224 std::vector<uint8_t> expected_bytes = { 1 };
225 EXPECT_EQ(bytes, expected_bytes);
226 EXPECT_FALSE(truncated);
228 TestTraceContainer
trace({
229 { { C::precomputed_first_row, 1 } },
235 check_relation<to_radix>(
trace);
238TEST(ToRadixConstrainingTest, ToLeRadixPadded)
240 EventEmitter<ToRadixEvent> to_radix_event_emitter;
241 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
245 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
248 auto [bytes, truncated] = to_radix_simulator.to_le_radix(
value, 64, 256);
250 auto expected_bytes =
value.to_buffer();
252 std::reverse(expected_bytes.begin(), expected_bytes.end());
253 expected_bytes.resize(64);
254 EXPECT_EQ(bytes, expected_bytes);
255 EXPECT_FALSE(truncated);
257 TestTraceContainer
trace({
258 { { C::precomputed_first_row, 1 } },
264 check_relation<to_radix>(
trace);
267TEST(ToRadixConstrainingTest, ToLeBitsInteractions)
269 EventEmitter<ToRadixEvent> to_radix_event_emitter;
270 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
274 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
276 to_radix_simulator.to_le_bits(FF::neg_one(), 254);
278 TestTraceContainer
trace({
279 { { C::precomputed_first_row, 1 } },
282 ToRadixTraceBuilder to_radix_builder;
283 to_radix_builder.process(to_radix_event_emitter.dump_events(),
trace);
297 check_relation<to_radix>(
trace);
300TEST(ToRadixConstrainingTest, ToLeRadixInteractions)
302 EventEmitter<ToRadixEvent> to_radix_event_emitter;
303 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
307 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
309 to_radix_simulator.to_le_radix(FF::neg_one(), 32, 256);
311 TestTraceContainer
trace({
312 { { C::precomputed_first_row, 1 } },
315 ToRadixTraceBuilder to_radix_builder;
316 to_radix_builder.process(to_radix_event_emitter.dump_events(),
trace);
331 check_relation<to_radix>(
trace);
334TEST(ToRadixConstrainingTest, NegativeOverflowCheck)
336 TestTraceContainer
trace({
337 { { C::precomputed_first_row, 1 } },
340 std::vector<uint8_t> modulus_le_bits(256, 0);
341 for (
size_t i = 0; i < 256; i++) {
342 modulus_le_bits[i] =
static_cast<uint8_t
>(FF::modulus.get_bit(i));
345 ToRadixEvent
event = { .value = FF::zero(), .radix = 2, .limbs = modulus_le_bits };
354TEST(ToRadixConstrainingTest, NegativeConsistency)
356 EventEmitter<ToRadixEvent> to_radix_event_emitter;
357 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
361 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
363 to_radix_simulator.to_le_radix(
FF(256), 32, 256);
365 TestTraceContainer
trace({
366 { { C::precomputed_first_row, 1 } },
373 trace.
set(Column::to_radix_sel, 6, 0);
376 "SELECTOR_CONSISTENCY");
379 trace.
set(Column::to_radix_radix, 5, 200);
382 "CONSTANT_CONSISTENCY_RADIX");
385 trace.
set(Column::to_radix_value, 4, 27);
388 "CONSTANT_CONSISTENCY_VALUE");
391 trace.
set(Column::to_radix_safe_limbs, 3, 200);
394 "CONSTANT_CONSISTENCY_SAFE_LIMBS");
401TEST(ToRadixMemoryConstrainingTest, EmptyRow)
406TEST(ToRadixMemoryConstrainingTest, BasicTest)
411 uint32_t num_limbs = 4;
414 TestTraceContainer
trace = TestTraceContainer({
417 { C::precomputed_first_row, 1 },
420 { C::gt_input_a,
dst_addr + num_limbs - 1 },
424 { C::execution_sel, 1 },
425 { C::execution_sel_exec_dispatch_to_radix, 1 },
426 { C::execution_register_0_,
value },
427 { C::execution_register_1_, radix },
428 { C::execution_register_2_, num_limbs },
429 { C::execution_register_3_, 0 },
436 { C::to_radix_mem_sel, 1 },
438 { C::to_radix_mem_two, 2 },
439 { C::to_radix_mem_two_five_six, 256 },
441 { C::to_radix_mem_execution_clk, 0 },
442 { C::to_radix_mem_space_id, 0 },
443 { C::to_radix_mem_dst_addr,
dst_addr },
444 { C::to_radix_mem_max_write_addr,
dst_addr + num_limbs - 1 },
446 { C::to_radix_mem_value_to_decompose,
value },
447 { C::to_radix_mem_radix, radix },
448 { C::to_radix_mem_num_limbs, num_limbs },
449 { C::to_radix_mem_is_output_bits, 0 },
451 { C::to_radix_mem_start, 1 },
452 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
454 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
455 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).invert() },
456 { C::to_radix_mem_sel_value_is_zero, 0 },
457 { C::to_radix_mem_value_inv,
value.invert() },
459 { C::to_radix_mem_limb_value, 1 },
460 { C::to_radix_mem_sel_should_decompose, 1 },
461 { C::to_radix_mem_sel_should_write_mem, 1 },
462 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 1 },
463 { C::to_radix_mem_value_found, 1 },
464 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
468 { C::gt_input_a, 2 },
469 { C::gt_input_b, radix },
474 { C::to_radix_mem_sel, 1 },
476 { C::to_radix_mem_execution_clk, 0 },
477 { C::to_radix_mem_space_id, 0 },
478 { C::to_radix_mem_dst_addr,
dst_addr + 1 },
480 { C::to_radix_mem_value_to_decompose,
value },
481 { C::to_radix_mem_radix, radix },
482 { C::to_radix_mem_num_limbs, num_limbs - 1 },
483 { C::to_radix_mem_is_output_bits, 0 },
486 { C::to_radix_mem_num_limbs_minus_one_inv,
FF(num_limbs - 2).invert() },
488 { C::to_radix_mem_limb_value, 3 },
489 { C::to_radix_mem_sel_should_decompose, 1 },
490 { C::to_radix_mem_sel_should_write_mem, 1 },
491 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 2 },
492 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
495 { C::gt_input_a, radix },
496 { C::gt_input_b, 256 },
501 { C::to_radix_mem_sel, 1 },
503 { C::to_radix_mem_execution_clk, 0 },
504 { C::to_radix_mem_space_id, 0 },
505 { C::to_radix_mem_dst_addr,
dst_addr + 2 },
507 { C::to_radix_mem_value_to_decompose,
value },
508 { C::to_radix_mem_radix, radix },
509 { C::to_radix_mem_num_limbs, num_limbs - 2 },
510 { C::to_radix_mem_is_output_bits, 0 },
513 { C::to_radix_mem_num_limbs_minus_one_inv,
FF(num_limbs - 3).invert() },
515 { C::to_radix_mem_limb_value, 3 },
516 { C::to_radix_mem_sel_should_decompose, 1 },
517 { C::to_radix_mem_sel_should_write_mem, 1 },
518 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 3 },
519 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
523 { C::to_radix_mem_sel, 1 },
525 { C::to_radix_mem_execution_clk, 0 },
526 { C::to_radix_mem_space_id, 0 },
527 { C::to_radix_mem_dst_addr, 13 },
529 { C::to_radix_mem_value_to_decompose,
value },
530 { C::to_radix_mem_radix, radix },
531 { C::to_radix_mem_num_limbs, num_limbs - 3 },
532 { C::to_radix_mem_is_output_bits, 0 },
534 { C::to_radix_mem_last, 1 },
536 { C::to_radix_mem_limb_value, 7 },
537 { C::to_radix_mem_sel_should_decompose, 1 },
538 { C::to_radix_mem_sel_should_write_mem, 1 },
539 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 4 },
540 { C::to_radix_mem_output_tag,
static_cast<uint8_t
>(
MemoryTag::U8) },
551 { value_addr, MemoryValue::from<FF>(
value) },
552 { radix_addr, MemoryValue::from<uint32_t>(radix) },
553 { num_limbs_addr, MemoryValue::from<uint32_t>(num_limbs) },
554 { is_output_bits_addr, MemoryValue::from<uint1_t>(
false) },
555 {
dst_addr, MemoryValue::from<uint8_t>(1) },
556 {
dst_addr + 1, MemoryValue::from<uint8_t>(3) },
557 {
dst_addr + 2, MemoryValue::from<uint8_t>(3) },
558 {
dst_addr + 3, MemoryValue::from<uint8_t>(7) },
561 for (uint32_t i = 0; i < memory_values.size(); ++i) {
562 const auto& [addr,
value] = memory_values[i];
565 { { C::memory_sel, 1 },
566 { C::memory_space_id, 0 },
567 { C::memory_address, addr },
568 { C::memory_value,
value.as_ff() },
569 { C::memory_tag,
static_cast<uint8_t
>(
value.get_tag()) },
570 { C::memory_rw, i > 3 ? 1 : 0 } },
574 EventEmitter<ToRadixEvent> to_radix_event_emitter;
575 NoopEventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
579 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
582 to_radix_simulator.to_le_radix(
value, num_limbs, radix);
585 auto events = to_radix_event_emitter.get_events();
593 check_relation<to_radix_mem>(
trace);
594 check_all_interactions<ToRadixTraceBuilder>(
trace);
597 trace.
set(Column::to_radix_mem_sel_should_write_mem, 2, 0);
599 "SEL_SHOULD_WRITE_MEM_CONTINUITY");
602 trace.
set(Column::to_radix_mem_sel_should_decompose, 2, 0);
604 "SEL_SHOULD_DECOMPOSE_CONTINUITY");
607TEST(ToRadixMemoryConstrainingTest, DstOutOfRange)
612 uint32_t num_limbs = 2;
615 TestTraceContainer
trace = TestTraceContainer({
618 { C::precomputed_first_row, 1 },
621 { C::gt_input_a,
dst_addr + num_limbs - 1 },
628 { C::execution_sel, 1 },
629 { C::execution_sel_exec_dispatch_to_radix, 1 },
630 { C::execution_register_0_,
value },
631 { C::execution_register_1_, radix },
632 { C::execution_register_2_, num_limbs },
633 { C::execution_register_3_, 0 },
635 { C::execution_sel_opcode_error, 1 },
638 { C::to_radix_mem_sel, 1 },
640 { C::to_radix_mem_two, 2 },
641 { C::to_radix_mem_two_five_six, 256 },
643 { C::to_radix_mem_execution_clk, 0 },
644 { C::to_radix_mem_space_id, 0 },
645 { C::to_radix_mem_dst_addr,
dst_addr },
646 { C::to_radix_mem_max_write_addr,
dst_addr + num_limbs - 1 },
648 { C::to_radix_mem_value_to_decompose,
value },
649 { C::to_radix_mem_radix, radix },
650 { C::to_radix_mem_num_limbs, num_limbs },
651 { C::to_radix_mem_is_output_bits, 0 },
653 { C::to_radix_mem_sel_dst_out_of_range_err, 1 },
654 { C::to_radix_mem_input_validation_error, 1 },
655 { C::to_radix_mem_err, 1 },
657 { C::to_radix_mem_start, 1 },
658 { C::to_radix_mem_last, 1 },
659 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
661 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
662 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).invert() },
663 { C::to_radix_mem_sel_value_is_zero, 0 },
664 { C::to_radix_mem_value_inv,
value.invert() },
668 check_relation<to_radix_mem>(
trace);
669 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_dst_addr_in_range_settings>(
trace);
670 check_interaction<ExecutionTraceBuilder, perm_execution_dispatch_to_to_radix_settings>(
trace);
673TEST(ToRadixMemoryConstrainingTest, InvalidRadix)
678 uint32_t num_limbs = 2;
681 TestTraceContainer
trace = TestTraceContainer({
684 { C::precomputed_first_row, 1 },
687 { C::gt_input_a, 2 },
688 { C::gt_input_b, radix },
693 { C::to_radix_mem_sel, 1 },
695 { C::to_radix_mem_two, 2 },
696 { C::to_radix_mem_two_five_six, 256 },
698 { C::to_radix_mem_execution_clk, 0 },
699 { C::to_radix_mem_space_id, 0 },
700 { C::to_radix_mem_dst_addr,
dst_addr },
701 { C::to_radix_mem_max_write_addr,
dst_addr + num_limbs - 1 },
703 { C::to_radix_mem_value_to_decompose,
value },
704 { C::to_radix_mem_radix, radix },
705 { C::to_radix_mem_num_limbs, num_limbs },
706 { C::to_radix_mem_is_output_bits, 0 },
708 { C::to_radix_mem_sel_radix_lt_2_err, 1 },
709 { C::to_radix_mem_input_validation_error, 1 },
710 { C::to_radix_mem_err, 1 },
712 { C::to_radix_mem_start, 1 },
713 { C::to_radix_mem_last, 1 },
714 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
716 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
717 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).invert() },
718 { C::to_radix_mem_sel_value_is_zero, 0 },
719 { C::to_radix_mem_value_inv,
value.invert() },
722 check_relation<to_radix_mem>(
trace);
723 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(
trace);
726TEST(ToRadixMemoryConstrainingTest, InvalidBitwiseRadix)
731 uint32_t num_limbs = 2;
733 bool is_output_bits =
true;
735 TestTraceContainer
trace = TestTraceContainer({
738 { C::precomputed_first_row, 1 },
741 { C::gt_input_a, 2 },
742 { C::gt_input_b, radix },
747 { C::to_radix_mem_sel, 1 },
749 { C::to_radix_mem_two, 2 },
750 { C::to_radix_mem_two_five_six, 256 },
752 { C::to_radix_mem_execution_clk, 0 },
753 { C::to_radix_mem_space_id, 0 },
754 { C::to_radix_mem_dst_addr,
dst_addr },
755 { C::to_radix_mem_max_write_addr,
dst_addr + num_limbs - 1 },
757 { C::to_radix_mem_value_to_decompose,
value },
758 { C::to_radix_mem_radix, radix },
759 { C::to_radix_mem_num_limbs, num_limbs },
760 { C::to_radix_mem_is_output_bits, is_output_bits ? 1 : 0 },
762 { C::to_radix_mem_sel_invalid_bitwise_radix, 1 },
763 { C::to_radix_mem_input_validation_error, 1 },
764 { C::to_radix_mem_err, 1 },
766 { C::to_radix_mem_start, 1 },
767 { C::to_radix_mem_last, 1 },
768 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
770 { C::to_radix_mem_sel_num_limbs_is_zero, 0 },
771 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).invert() },
772 { C::to_radix_mem_sel_value_is_zero, 0 },
773 { C::to_radix_mem_value_inv,
value.invert() },
776 check_relation<to_radix_mem>(
trace);
777 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(
trace);
780TEST(ToRadixMemoryConstrainingTest, InvalidNumLimbsForValue)
785 uint32_t num_limbs = 0;
787 bool is_output_bits =
false;
789 TestTraceContainer
trace = TestTraceContainer({
792 { C::precomputed_first_row, 1 },
795 { C::gt_input_a, 2 },
796 { C::gt_input_b, radix },
801 { C::to_radix_mem_sel, 1 },
803 { C::to_radix_mem_two, 2 },
804 { C::to_radix_mem_two_five_six, 256 },
806 { C::to_radix_mem_execution_clk, 0 },
807 { C::to_radix_mem_space_id, 0 },
808 { C::to_radix_mem_dst_addr,
dst_addr },
809 { C::to_radix_mem_max_write_addr,
dst_addr + num_limbs - 1 },
811 { C::to_radix_mem_value_to_decompose,
value },
812 { C::to_radix_mem_radix, radix },
813 { C::to_radix_mem_num_limbs, num_limbs },
814 { C::to_radix_mem_is_output_bits, is_output_bits ? 1 : 0 },
816 { C::to_radix_mem_sel_invalid_num_limbs_err, 1 },
817 { C::to_radix_mem_input_validation_error, 1 },
818 { C::to_radix_mem_err, 1 },
820 { C::to_radix_mem_start, 1 },
821 { C::to_radix_mem_last, 1 },
822 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
824 { C::to_radix_mem_sel_num_limbs_is_zero, 1 },
825 { C::to_radix_mem_num_limbs_inv, 0 },
826 { C::to_radix_mem_sel_value_is_zero, 0 },
827 { C::to_radix_mem_value_inv,
value.invert() },
830 check_relation<to_radix_mem>(
trace);
831 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(
trace);
834TEST(ToRadixMemoryConstrainingTest, TruncationError)
839 uint32_t num_limbs = 3;
841 bool is_output_bits =
false;
843 TestTraceContainer
trace = TestTraceContainer({
846 { C::precomputed_first_row, 1 },
849 { C::gt_input_a, 2 },
850 { C::gt_input_b, radix },
855 { C::to_radix_mem_sel, 1 },
857 { C::to_radix_mem_two, 2 },
858 { C::to_radix_mem_two_five_six, 256 },
860 { C::to_radix_mem_execution_clk, 0 },
861 { C::to_radix_mem_space_id, 0 },
862 { C::to_radix_mem_dst_addr,
dst_addr },
863 { C::to_radix_mem_max_write_addr,
dst_addr + num_limbs - 1 },
865 { C::to_radix_mem_value_to_decompose,
value },
866 { C::to_radix_mem_radix, radix },
867 { C::to_radix_mem_num_limbs, num_limbs },
868 { C::to_radix_mem_is_output_bits, is_output_bits ? 1 : 0 },
870 { C::to_radix_mem_sel_truncation_error, 1 },
871 { C::to_radix_mem_err, 1 },
873 { C::to_radix_mem_start, 1 },
874 { C::to_radix_mem_last, 1 },
875 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
877 { C::to_radix_mem_sel_should_decompose, 1 },
878 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 1 },
879 { C::to_radix_mem_limb_value, 3 },
880 { C::to_radix_mem_value_found, 0 },
882 { C::to_radix_mem_num_limbs_inv,
FF(num_limbs).invert() },
883 { C::to_radix_mem_sel_value_is_zero, 0 },
884 { C::to_radix_mem_value_inv,
value.invert() },
887 check_relation<to_radix_mem>(
trace);
888 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(
trace);
891 trace.
set(C::to_radix_mem_sel_truncation_error, 1, 0);
894 trace.
set(C::to_radix_mem_sel_truncation_error, 1, 1);
897 trace.
set(C::to_radix_mem_value_found, 1, 1);
902TEST(ToRadixMemoryConstrainingTest, ZeroNumLimbsAndZeroValueIsNoop)
907 uint32_t num_limbs = 0;
909 bool is_output_bits =
false;
911 TestTraceContainer
trace = TestTraceContainer({
914 { C::precomputed_first_row, 1 },
917 { C::gt_input_a, 2 },
918 { C::gt_input_b, radix },
923 { C::to_radix_mem_sel, 1 },
925 { C::to_radix_mem_two, 2 },
926 { C::to_radix_mem_two_five_six, 256 },
928 { C::to_radix_mem_execution_clk, 0 },
929 { C::to_radix_mem_space_id, 0 },
930 { C::to_radix_mem_dst_addr,
dst_addr },
931 { C::to_radix_mem_max_write_addr,
dst_addr + num_limbs - 1 },
933 { C::to_radix_mem_value_to_decompose,
value },
934 { C::to_radix_mem_radix, radix },
935 { C::to_radix_mem_num_limbs, num_limbs },
936 { C::to_radix_mem_is_output_bits, is_output_bits ? 1 : 0 },
938 { C::to_radix_mem_start, 1 },
939 { C::to_radix_mem_last, 1 },
940 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 :
FF(num_limbs - 1).invert() },
942 { C::to_radix_mem_sel_num_limbs_is_zero, 1 },
943 { C::to_radix_mem_num_limbs_inv, 0 },
944 { C::to_radix_mem_sel_value_is_zero, 1 },
945 { C::to_radix_mem_value_inv, 0 },
948 check_relation<to_radix_mem>(
trace);
949 check_interaction<ToRadixTraceBuilder, lookup_to_radix_mem_check_radix_lt_2_settings>(
trace);
952TEST(ToRadixMemoryConstrainingTest, ComplexTest)
954 EventEmitter<ToRadixEvent> to_radix_event_emitter;
955 EventEmitter<ToRadixMemoryEvent> to_radix_mem_event_emitter;
956 EventEmitter<RangeCheckEvent> range_check_emitter;
957 EventEmitter<GreaterThanEvent> gt_emitter;
959 simulation::MemoryStore
memory;
961 StrictMock<MockFieldGreaterThan>
field_gt;
963 GreaterThan
gt(
field_gt, range_check, gt_emitter);
965 ToRadixSimulator to_radix_simulator(
execution_id_manager, gt, to_radix_event_emitter, to_radix_mem_event_emitter);
969 uint32_t num_limbs = 256;
971 bool is_output_bits =
true;
973 to_radix_simulator.to_be_radix(memory,
value, radix, num_limbs, is_output_bits,
dst_addr);
974 to_radix_simulator.to_be_radix(
975 memory,
FF(1337), 10, 6,
false, 0xdeadbeef);
977 TestTraceContainer
trace;
980 builder.process_with_memory(to_radix_mem_event_emitter.dump_events(),
trace);
990 check_relation<to_radix>(
trace);
991 check_relation<to_radix_mem>(
trace);
#define AVM_HIGHEST_MEM_ADDRESS
static constexpr size_t SR_SEL_SHOULD_WRITE_MEM_CONTINUITY
static constexpr size_t SR_SEL_SHOULD_DECOMPOSE_CONTINUITY
static constexpr size_t SR_TRUNCATION_ERROR
static constexpr size_t SR_SELECTOR_CONSISTENCY
static constexpr size_t SR_OVERFLOW_CHECK
static constexpr size_t SR_CONSTANT_CONSISTENCY_SAFE_LIMBS
static constexpr size_t SR_CONSTANT_CONSISTENCY_RADIX
static constexpr size_t SR_CONSTANT_CONSISTENCY_VALUE
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::GreaterThanEvent >::Container &events, TraceContainer &trace)
void process_to_radix_p_decompositions(TraceContainer &trace)
void process_to_radix_safe_limbs(TraceContainer &trace)
void process_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void process_sel_range_8(TraceContainer &trace)
uint32_t get_num_rows() const
void set(Column col, uint32_t row, const FF &value)
PrecomputedTraceBuilder precomputed_builder
GreaterThanTraceBuilder gt_builder
ExecutionIdManager execution_id_manager
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(TxExecutionConstrainingTest, WriteTreeValue)
TestTraceContainer empty_trace()
lookup_settings< lookup_to_radix_limb_less_than_radix_range_settings_ > lookup_to_radix_limb_less_than_radix_range_settings
lookup_settings< lookup_to_radix_limb_p_diff_range_settings_ > lookup_to_radix_limb_p_diff_range_settings
lookup_settings< lookup_to_radix_mem_check_dst_addr_in_range_settings_ > lookup_to_radix_mem_check_dst_addr_in_range_settings
lookup_settings< lookup_to_radix_mem_check_radix_lt_2_settings_ > lookup_to_radix_mem_check_radix_lt_2_settings
lookup_settings< lookup_to_radix_limb_range_settings_ > lookup_to_radix_limb_range_settings
lookup_settings< lookup_to_radix_mem_check_radix_gt_256_settings_ > lookup_to_radix_mem_check_radix_gt_256_settings
lookup_settings< lookup_to_radix_fetch_safe_limbs_settings_ > lookup_to_radix_fetch_safe_limbs_settings
lookup_settings< lookup_to_radix_mem_input_output_to_radix_settings_ > lookup_to_radix_mem_input_output_to_radix_settings
lookup_settings< lookup_to_radix_fetch_p_limb_settings_ > lookup_to_radix_fetch_p_limb_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
FieldGreaterThan field_gt