Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
to_radix.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4
8
9namespace bb::avm2::simulation {
10
22 uint32_t num_limbs,
23 uint32_t radix)
24{
25 BB_ASSERT_LTE(radix, static_cast<decltype(radix)>(256), "Radix is greater than 256");
26 BB_ASSERT_GTE(radix, static_cast<decltype(radix)>(2), "Radix is less than 2");
27
28 std::vector<uint8_t> limbs;
29 uint32_t num_p_limbs = static_cast<uint32_t>(get_p_limbs_per_radix_size(radix));
30 limbs.reserve(std::max(num_limbs, num_p_limbs));
31
32 uint256_t value_integer = static_cast<uint256_t>(value);
33 while (value_integer != 0) {
34 auto [quotient, remainder] = value_integer.divmod(static_cast<uint64_t>(radix));
35 limbs.push_back(static_cast<uint8_t>(remainder)); // Cast is fine by the precondition that radix <= 256.
36 value_integer = quotient;
37 }
38
39 if (num_limbs > limbs.size()) {
40 limbs.insert(limbs.end(), num_limbs - limbs.size(), 0);
41 }
42
43 // The event should never have less limbs than the necessary to perform the decomposition
45 .value = value,
46 .radix = radix,
47 .limbs = limbs,
48 });
49
50 bool truncated = num_limbs < limbs.size();
51 if (truncated) {
52 limbs.erase(limbs.begin() + num_limbs, limbs.end());
53 }
54
55 return { limbs, truncated };
56}
57
66std::pair<std::vector<bool>, /* truncated */ bool> ToRadix::to_le_bits(const FF& value, uint32_t num_limbs)
67{
68 const auto [limbs, truncated] = to_le_radix(value, num_limbs, 2);
69 std::vector<bool> bits;
70 bits.reserve(limbs.size());
71
72 for (uint8_t val : limbs) {
73 bits.push_back(val != 0); // Convert nonzero values to `true`, zero to `false`
74 };
75
76 return { bits, truncated };
77}
78
100 const FF& value,
101 uint32_t radix,
102 uint32_t num_limbs,
103 bool is_output_bits, // Decides if output is U1 or U8
105{
106
107 uint32_t execution_clk = execution_id_manager.get_execution_id();
108 uint16_t space_id = memory.get_space_id();
109
110 // Error handling - check that the maximum write address does not exceed the highest memory address
111 // This subtrace writes in the range { dst_addr, dst_addr + 1, ..., dst_addr + num_limbs - 1 }
112 uint64_t write_addr_upper_bound = static_cast<uint64_t>(dst_addr) + num_limbs;
113 bool dst_out_of_range = gt.gt(write_addr_upper_bound, AVM_MEMORY_SIZE);
114
115 // Error handling - check that the radix value is within the valid range
116 // The valid range is [2, 256]. Therefore, the radix is invalid if (2 > radix) or (radix > 256)
117 // We need to perform both checks explicitly since that is what the circuit would do
118 bool radix_is_lt_2 = gt.gt(2, radix);
119 bool radix_is_gt_256 = gt.gt(radix, 256);
120
121 // Error handling - check that if is_output_bits is true, the radix has to be 2
122 bool invalid_bitwise_radix = is_output_bits && (radix != 2);
123 // Error handling - if num_limbs is zero, value needs to be zero
124 bool invalid_num_limbs = (num_limbs == 0) && (!value.is_zero());
125
126 ToRadixMemoryEvent event = {
127 .execution_clk = execution_clk,
128 .space_id = space_id,
129 .num_limbs = num_limbs,
130 .dst_addr = dst_addr,
131 .value = value,
132 .radix = radix,
133 .is_output_bits = is_output_bits,
134 .limbs = {},
135 };
136
137 if (dst_out_of_range || radix_is_lt_2 || radix_is_gt_256 || invalid_bitwise_radix || invalid_num_limbs) {
139 throw ToRadixException("Error during BE conversion: Invalid parameters for ToRadix");
140 }
141
142 bool truncated = false;
143
144 if (num_limbs > 0) {
145 event.limbs.reserve(num_limbs);
146 if (is_output_bits) {
147 const auto [limbs, truncated_decomposition] = to_le_bits(value, num_limbs);
148 truncated = truncated_decomposition;
149 std::ranges::for_each(limbs.rbegin(), limbs.rend(), [&](bool bit) {
150 event.limbs.push_back(MemoryValue::from<uint1_t>(bit));
151 });
152 } else {
153 const auto [limbs, truncated_decomposition] = to_le_radix(value, num_limbs, radix);
154 truncated = truncated_decomposition;
155 std::ranges::for_each(limbs.rbegin(), limbs.rend(), [&](uint8_t limb) {
156 event.limbs.push_back(MemoryValue::from<uint8_t>(limb));
157 });
158 }
159 }
160
161 if (truncated) {
163 throw ToRadixException("Error during BE conversion: Truncation error");
164 }
165
166 // If we get to this point, we are error free.
167 for (uint32_t i = 0; i < num_limbs; i++) {
168 memory.set(dst_addr + i, event.limbs[i]);
169 }
170
172}
173
174} // namespace bb::avm2::simulation
#define BB_ASSERT_GTE(left, right,...)
Definition assert.hpp:128
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:158
#define AVM_MEMORY_SIZE
virtual uint32_t get_execution_id() const =0
EventEmitterInterface< ToRadixMemoryEvent > & memory_events
Definition to_radix.hpp:44
EventEmitterInterface< ToRadixEvent > & events
Definition to_radix.hpp:43
std::pair< std::vector< bool >, bool > to_le_bits(const FF &value, uint32_t num_limbs) override
Performs a little endian radix decomposition of a field element into bits. This emits a ToRadixEvent.
Definition to_radix.cpp:66
std::pair< std::vector< uint8_t >, bool > to_le_radix(const FF &value, uint32_t num_limbs, uint32_t radix) override
Performs a little endian radix decomposition of a field element into limbs. This emits a ToRadixEvent...
Definition to_radix.cpp:21
void to_be_radix(MemoryInterface &memory, const FF &value, uint32_t radix, uint32_t num_limbs, bool is_output_bits, MemoryAddress dst_addr) override
Performs a big endian radix decomposition of a field element into limbs. This directly emits a ToRadi...
Definition to_radix.cpp:99
ExecutionIdManagerInterface & execution_id_manager
Definition to_radix.hpp:41
constexpr std::pair< uint256_t, uint256_t > divmod(const uint256_t &b) const
uint32_t dst_addr
AVM range check gadget for witness generation.
size_t get_p_limbs_per_radix_size(size_t radix)
Gets the number of limbs that the modulus, p, decomposes into for a given radix.
Definition to_radix.cpp:69
AvmFlavorSettings::FF FF
Definition field.hpp:10
uint32_t MemoryAddress
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
simulation::PublicDataTreeReadWriteEvent event
BB_INLINE constexpr bool is_zero() const noexcept