Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
range_check_trace.cpp
Go to the documentation of this file.
2
3#include <cstddef>
4#include <cstdint>
5
10
11namespace bb::avm2::tracegen {
12
28{
29 using C = Column;
30
31 uint32_t row = 0;
32 for (const auto& event : events) {
33 const uint256_t original_num_bits = event.num_bits;
34 const uint256_t original_value = static_cast<uint256_t>(event.value);
35
36 // Mutable copies used while slicing the value into 16-bit chunks.
37 uint8_t num_bits = event.num_bits;
38 uint256_t value = static_cast<uint256_t>(event.value);
39
40 std::array<uint16_t, 7> fixed_slice_registers{}; // u16_r0..r6
41 size_t index_of_most_sig_16b_chunk = 0;
42 uint16_t dynamic_slice_register = 0; // u16_r7
43 uint8_t dynamic_bits = 0;
44
45 // Decompose the value into 16-bit chunks from LSB to MSB.
46 for (size_t i = 0; i < 8; i++) {
47 // The most significant (possibly partial) chunk goes into the dynamic register.
48 if (num_bits <= 16) {
49 dynamic_slice_register = static_cast<uint16_t>(value);
50 index_of_most_sig_16b_chunk = i;
51 dynamic_bits = num_bits;
52 break;
53 }
54 // Full 16-bit chunk — store in the corresponding fixed register.
55 fixed_slice_registers[i] = static_cast<uint16_t>(value);
56 num_bits -= 16;
57 value >>= 16;
58 }
59
60 // dynamic_diff = (2^dynamic_bits - 1) - dynamic_slice_register, proving the slice fits.
61 auto dynamic_diff = static_cast<uint16_t>((1 << dynamic_bits) - dynamic_slice_register - 1);
62
63 trace.set(row,
64 { {
65 { C::range_check_sel, 1 },
66 // value to range check
67 { C::range_check_value, original_value },
68 // number of bits to check the value against
69 { C::range_check_rng_chk_bits, original_num_bits },
70 // flag indicating which bit size range is active
71 { C::range_check_is_lte_u16, index_of_most_sig_16b_chunk == 0 ? 1 : 0 },
72 { C::range_check_is_lte_u32, index_of_most_sig_16b_chunk == 1 ? 1 : 0 },
73 { C::range_check_is_lte_u48, index_of_most_sig_16b_chunk == 2 ? 1 : 0 },
74 { C::range_check_is_lte_u64, index_of_most_sig_16b_chunk == 3 ? 1 : 0 },
75 { C::range_check_is_lte_u80, index_of_most_sig_16b_chunk == 4 ? 1 : 0 },
76 { C::range_check_is_lte_u96, index_of_most_sig_16b_chunk == 5 ? 1 : 0 },
77 { C::range_check_is_lte_u112, index_of_most_sig_16b_chunk == 6 ? 1 : 0 },
78 { C::range_check_is_lte_u128, index_of_most_sig_16b_chunk == 7 ? 1 : 0 },
79 // slice registers
80 { C::range_check_u16_r0, fixed_slice_registers[0] },
81 { C::range_check_u16_r1, fixed_slice_registers[1] },
82 { C::range_check_u16_r2, fixed_slice_registers[2] },
83 { C::range_check_u16_r3, fixed_slice_registers[3] },
84 { C::range_check_u16_r4, fixed_slice_registers[4] },
85 { C::range_check_u16_r5, fixed_slice_registers[5] },
86 { C::range_check_u16_r6, fixed_slice_registers[6] },
87 { C::range_check_u16_r7, dynamic_slice_register },
88 // computations on dynamic slice register
89 { C::range_check_dyn_rng_chk_bits, dynamic_bits },
90 { C::range_check_dyn_rng_chk_pow_2, 1 << dynamic_bits },
91 { C::range_check_dyn_diff, dynamic_diff },
92 // Lookup selectors
93 { C::range_check_sel_r0_16_bit_rng_lookup, index_of_most_sig_16b_chunk > 0 ? 1 : 0 },
94 { C::range_check_sel_r1_16_bit_rng_lookup, index_of_most_sig_16b_chunk > 1 ? 1 : 0 },
95 { C::range_check_sel_r2_16_bit_rng_lookup, index_of_most_sig_16b_chunk > 2 ? 1 : 0 },
96 { C::range_check_sel_r3_16_bit_rng_lookup, index_of_most_sig_16b_chunk > 3 ? 1 : 0 },
97 { C::range_check_sel_r4_16_bit_rng_lookup, index_of_most_sig_16b_chunk > 4 ? 1 : 0 },
98 { C::range_check_sel_r5_16_bit_rng_lookup, index_of_most_sig_16b_chunk > 5 ? 1 : 0 },
99 { C::range_check_sel_r6_16_bit_rng_lookup, index_of_most_sig_16b_chunk > 6 ? 1 : 0 },
100 } });
101
102 row++;
103 }
104}
105
109 .add<lookup_range_check_dyn_rng_chk_pow_2_settings, InteractionType::LookupIntoIndexedByRow>()
111 .add<lookup_range_check_r1_is_u16_settings, InteractionType::LookupIntoIndexedByRow>()
113 .add<lookup_range_check_r3_is_u16_settings, InteractionType::LookupIntoIndexedByRow>()
115 .add<lookup_range_check_r5_is_u16_settings, InteractionType::LookupIntoIndexedByRow>()
117 .add<lookup_range_check_r7_is_u16_settings, InteractionType::LookupIntoIndexedByRow>();
118
119} // namespace bb::avm2::tracegen
InteractionDefinition & add(auto &&... args)
void process(const simulation::EventEmitterInterface< simulation::RangeCheckEvent >::Container &events, TraceContainer &trace)
Processes range check events and populates the trace with decomposed value columns.
static const InteractionDefinition interactions
TestTraceContainer trace
lookup_settings< lookup_range_check_r4_is_u16_settings_ > lookup_range_check_r4_is_u16_settings
lookup_settings< lookup_range_check_dyn_diff_is_u16_settings_ > lookup_range_check_dyn_diff_is_u16_settings
lookup_settings< lookup_range_check_r2_is_u16_settings_ > lookup_range_check_r2_is_u16_settings
lookup_settings< lookup_range_check_r6_is_u16_settings_ > lookup_range_check_r6_is_u16_settings
lookup_settings< lookup_range_check_r0_is_u16_settings_ > lookup_range_check_r0_is_u16_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
simulation::PublicDataTreeReadWriteEvent event