39 auto& circuit_builder,
41 size_t num_pair_elts_in_ROM_table = 0,
43 const size_t read_operations = 0,
44 bool final_arithmetic_gate_and_read =
true)
46 BB_ASSERT_GTE(array_length, 1U,
"The array length should be at least 1");
49 "cannot set the number of 'pairs of elements to add to the ROM table' to be greater than the "
50 "length of the table");
54 std::vector<fr> variables(array_length + 1);
55 std::vector<uint32_t> variable_witnesses(array_length + 1);
56 for (
auto [variable, witness] :
zip_view(variables, variable_witnesses)) {
58 witness = circuit_builder.add_variable(variable);
63 const size_t num_single_elts_in_ROM_table = array_length - num_pair_elts_in_ROM_table;
69 size_t rom_single_id = circuit_builder.create_ROM_array(num_single_elts_in_ROM_table);
70 size_t rom_pair_id = circuit_builder.create_ROM_array(num_pair_elts_in_ROM_table);
73 std::vector<uint32_t> single_index_witnesses(num_single_elts_in_ROM_table);
74 for (
size_t i = 0; i < num_single_elts_in_ROM_table; ++i) {
75 single_index_witnesses[i] = circuit_builder.put_constant_variable(
static_cast<uint64_t
>(i));
77 std::vector<uint32_t> pair_index_witnesses(num_pair_elts_in_ROM_table);
78 for (
size_t i = 0; i < num_pair_elts_in_ROM_table; ++i) {
79 pair_index_witnesses[i] = circuit_builder.put_constant_variable(
static_cast<uint64_t
>(i));
82 for (
size_t i = 0; i < num_single_elts_in_ROM_table; ++i) {
83 circuit_builder.set_ROM_element(rom_single_id, i, variable_witnesses[i]);
84 native_rom_table[i] = std::array{ variables[i],
fr::zero() };
87 for (
size_t i = num_single_elts_in_ROM_table; i < array_length; ++i) {
88 const size_t pair_local = i - num_single_elts_in_ROM_table;
89 circuit_builder.set_ROM_element_pair(
90 rom_pair_id, pair_local, std::array{ variable_witnesses[i], variable_witnesses[i + 1] });
91 native_rom_table[i] = std::array{ variables[i], variables[i + 1] };
96 for (
size_t i = 0; i < read_operations; ++i) {
97 uint32_t random_read_index =
static_cast<uint32_t
>(
100 if (random_read_index < num_single_elts_in_ROM_table) {
101 uint32_t read_witness_index =
102 circuit_builder.read_ROM_array(rom_single_id, single_index_witnesses[random_read_index]);
104 auto actually_read_value = circuit_builder.get_variable(read_witness_index);
105 auto expected_value = native_rom_table[random_read_index][0];
108 const size_t pair_local = random_read_index - num_single_elts_in_ROM_table;
109 auto [read_witness_index_1, read_witness_index_2] =
110 circuit_builder.read_ROM_array_pair(rom_pair_id, pair_index_witnesses[pair_local]);
112 std::array<fr, 2> actually_read_values = { circuit_builder.get_variable(read_witness_index_1),
113 circuit_builder.get_variable(read_witness_index_2) };
114 auto expected_values = native_rom_table[random_read_index];
115 BB_ASSERT_EQ(actually_read_values[0], expected_values[0]);
116 BB_ASSERT_EQ(actually_read_values[1], expected_values[1]);
119 if (final_arithmetic_gate_and_read) {
129 for (
size_t i = 0; i < 3; i++) {
130 uint32_t random_index_to_check_computation =
132 random_indices_to_check_computation[i] = random_index_to_check_computation;
133 native_fr_elts_to_check_computation[i] =
134 native_rom_table[random_index_to_check_computation]
141 for (
size_t i = 0; i < 3; i++) {
142 const auto random_idx = random_indices_to_check_computation[i];
144 if (random_idx < num_single_elts_in_ROM_table) {
145 final_check_read_witnesses[i] =
146 circuit_builder.read_ROM_array(rom_single_id, single_index_witnesses[random_idx]);
149 const size_t pair_local = random_idx - num_single_elts_in_ROM_table;
151 circuit_builder.read_ROM_array_pair(rom_pair_id, pair_index_witnesses[pair_local]);
152 final_check_read_witnesses[i] = first;
157 const fr d_value = std::accumulate(
158 native_fr_elts_to_check_computation.begin(), native_fr_elts_to_check_computation.end(),
fr::zero());
159 uint32_t d_idx = circuit_builder.add_variable(d_value);
160 circuit_builder.create_big_add_gate({
161 final_check_read_witnesses[0],
162 final_check_read_witnesses[1],
163 final_check_read_witnesses[2],
172 if (num_single_elts_in_ROM_table > 0) {
173 uint32_t random_read_index =
static_cast<uint32_t
>(
175 num_single_elts_in_ROM_table);
177 circuit_builder.read_ROM_array(rom_single_id, single_index_witnesses[random_read_index]);
179 uint32_t random_read_index =
static_cast<uint32_t
>(
181 num_pair_elts_in_ROM_table);
183 circuit_builder.read_ROM_array_pair(rom_pair_id, pair_index_witnesses[random_read_index]);
229 const size_t read_write_operations = 0,
230 bool final_arithmetic_gate_and_read =
true)
235 std::vector<fr> variables(array_length);
236 std::vector<uint32_t> variable_witnesses(array_length);
237 for (
auto [variable, witness] :
zip_view(variables, variable_witnesses)) {
239 witness = circuit_builder.add_variable(variable);
244 std::vector<uint32_t> index_witness_indices(array_length);
245 for (
size_t i = 0; i < array_length; ++i) {
246 index_witness_indices[i] = circuit_builder.put_constant_variable(
static_cast<uint64_t
>(i));
249 size_t ram_table_id = circuit_builder.create_RAM_array(array_length);
251 for (
size_t i = 0; i < array_length; ++i) {
252 circuit_builder.init_RAM_element(ram_table_id, i, variable_witnesses[i]);
253 native_ram_table[i] = variables[i];
257 for (
size_t i = 0; i < read_write_operations; ++i) {
261 uint32_t write_variable_witness = circuit_builder.add_variable(random_element);
262 native_ram_table[random_write_index] = random_element;
263 circuit_builder.write_RAM_array(
264 ram_table_id, index_witness_indices[random_write_index], write_variable_witness);
267 uint32_t read_witness =
268 circuit_builder.read_RAM_array(ram_table_id, index_witness_indices[random_read_index]);
269 auto read_value = circuit_builder.get_variable(read_witness);
270 auto expected_value = native_ram_table[random_read_index];
271 BB_ASSERT_EQ(read_value, expected_value,
"the value the RAM table read was not the expected value");
273 if (final_arithmetic_gate_and_read) {
281 for (
size_t i = 0; i < 3; i++) {
282 uint32_t random_index_to_check_computation =
284 random_index_witnesses_to_check_computation[i] =
285 index_witness_indices[random_index_to_check_computation];
286 native_fr_elts_to_check_computation[i] = native_ram_table[random_index_to_check_computation];
290 for (
size_t i = 0; i < 3; i++) {
291 const auto random_idx_witness = random_index_witnesses_to_check_computation[i];
292 final_check_read_witnesses[i] = circuit_builder.read_RAM_array(ram_table_id, random_idx_witness);
296 const fr d_value = std::accumulate(
297 native_fr_elts_to_check_computation.begin(), native_fr_elts_to_check_computation.end(),
fr::zero());
298 uint32_t d_idx = circuit_builder.add_variable(d_value);
299 circuit_builder.create_big_add_gate({
300 final_check_read_witnesses[0],
301 final_check_read_witnesses[1],
302 final_check_read_witnesses[2],
311 uint32_t random_read_index =
313 static_cast<uint32_t
>(array_length);
314 circuit_builder.read_RAM_array(ram_table_id, index_witness_indices[random_read_index]);