40 const MemoryTag a_tag =
event.a.get_tag();
49 switch (
event.operation) {
51 return { { Column::alu_sel_op_add, 1 },
55 { Column::alu_cf,
event.a.as_ff() +
event.b.as_ff() !=
event.c.as_ff() } };
57 return { { Column::alu_sel_op_sub, 1 },
59 { Column::alu_cf,
event.a.as_ff() -
event.b.as_ff() !=
event.c.as_ff() } };
66 { Column::alu_sel_op_mul, 1 },
68 { Column::alu_constant_64, 64 },
69 { Column::alu_sel_is_u128, is_u128 },
77 auto hi_operand =
static_cast<uint256_t>(a_decomp.hi) *
static_cast<uint256_t>(b_decomp.hi);
80 { Column::alu_sel_mul_u128, 1 },
81 { Column::alu_sel_mul_div_u128, 1 },
82 { Column::alu_sel_decompose_a, 1 },
83 { Column::alu_a_lo, a_decomp.lo },
84 { Column::alu_a_lo_bits, 64 },
85 { Column::alu_a_hi, a_decomp.hi },
86 { Column::alu_a_hi_bits, 64 },
87 { Column::alu_b_lo, b_decomp.lo },
88 { Column::alu_b_hi, b_decomp.hi },
89 { Column::alu_c_hi, (((a_int * b_int) >> 128) - hi_operand) % (
uint256_t(1) << 64) },
90 { Column::alu_cf, hi_operand == 0 ? 0 : 1 },
94 res.insert(res.end(), { { Column::alu_c_hi, is_ff ? 0 : (a_int * b_int) >>
get_tag_bits(a_tag) } });
100 auto remainder = no_tag_err && !div_0_error ?
event.a -
event.b *
event.c :
MemoryValue::from_tag(a_tag, 0);
104 { Column::alu_sel_op_div, 1 },
106 { Column::alu_helper1, remainder },
107 { Column::alu_constant_64, 64 },
108 { Column::alu_sel_is_ff, is_ff },
109 { Column::alu_tag_ff_diff_inv,
tag_inverses[
static_cast<uint8_t
>(a_tag)] },
110 { Column::alu_sel_is_u128, is_u128 },
112 { Column::alu_b_inv, div_0_error ? 0 :
event.b.as_ff() },
113 { Column::alu_sel_div_no_0_err, div_0_error ? 0 : 1 },
119 res.insert(res.end(),
121 { Column::alu_sel_mul_div_u128, 1 },
122 { Column::alu_sel_decompose_a, 1 },
123 { Column::alu_a_lo, c_decomp.lo },
124 { Column::alu_a_lo_bits, 64 },
125 { Column::alu_a_hi, c_decomp.hi },
126 { Column::alu_a_hi_bits, 64 },
127 { Column::alu_b_lo, b_decomp.lo },
128 { Column::alu_b_hi, b_decomp.hi },
136 { Column::alu_sel_op_fdiv, 1 },
138 { Column::alu_sel_is_ff, is_ff },
139 { Column::alu_tag_ff_diff_inv,
tag_inverses[
static_cast<uint8_t
>(a_tag)] },
140 { Column::alu_b_inv, div_0_error ? 0 :
event.b.as_ff() },
144 const FF diff =
event.a.as_ff() -
event.b.as_ff();
146 { Column::alu_sel_op_eq, 1 },
148 { Column::alu_ab_diff_inv, diff },
153 { Column::alu_lt_ops_input_a,
event.b },
154 { Column::alu_lt_ops_input_b,
event.a },
155 { Column::alu_lt_ops_result_c,
event.c },
156 { Column::alu_sel_op_lt, 1 },
157 { Column::alu_sel_lt_ops, no_tag_err },
160 { Column::alu_sel_is_ff, is_ff },
161 { Column::alu_sel_ff_lt_ops, is_ff && no_tag_err },
162 { Column::alu_sel_int_lt_ops, !is_ff && no_tag_err },
163 { Column::alu_tag_ff_diff_inv,
tag_inverses[
static_cast<uint8_t
>(a_tag)] },
167 { Column::alu_lt_ops_input_a,
event.a },
168 { Column::alu_lt_ops_input_b,
event.b },
169 { Column::alu_lt_ops_result_c, MemoryValue::from<uint1_t>(
event.c.as_ff() == 0 && no_tag_err ? 1 : 0) },
170 { Column::alu_sel_op_lte, 1 },
171 { Column::alu_sel_lt_ops, no_tag_err },
174 { Column::alu_sel_is_ff, is_ff },
175 { Column::alu_sel_ff_lt_ops, is_ff && no_tag_err },
176 { Column::alu_sel_int_lt_ops, !is_ff && no_tag_err },
177 { Column::alu_tag_ff_diff_inv,
tag_inverses[
static_cast<uint8_t
>(a_tag)] },
181 { Column::alu_sel_op_not, 1 },
183 { Column::alu_sel_is_ff, is_ff },
184 { Column::alu_tag_ff_diff_inv,
tag_inverses[
static_cast<uint8_t
>(a_tag)] },
188 auto a_num =
static_cast<uint128_t>(
event.a.as_ff());
189 auto b_num =
static_cast<uint128_t>(
event.b.as_ff());
192 bool overflow = b_num > tag_bits;
195 auto shift_lo_bits = overflow ? tag_bits : tag_bits - b_num;
198 auto a_lo = overflow ? b_num - tag_bits : a_num % (
static_cast<uint128_t>(1) << shift_lo_bits);
200 { Column::alu_sel_op_shl, 1 },
201 { Column::alu_sel_shift_ops, 1 },
202 { Column::alu_sel_shift_ops_no_overflow, overflow ? 0 : 1 },
203 { Column::alu_sel_decompose_a, is_ff ? 0 : 1 },
204 { Column::alu_a_lo, a_lo },
205 { Column::alu_a_lo_bits, shift_lo_bits },
206 { Column::alu_a_hi, a_num >> shift_lo_bits },
207 { Column::alu_a_hi_bits, overflow ? tag_bits : b_num },
208 { Column::alu_shift_lo_bits, shift_lo_bits },
209 { Column::alu_two_pow_shift_lo_bits,
static_cast<uint128_t>(1) << shift_lo_bits },
210 { Column::alu_sel_is_ff, is_ff },
211 { Column::alu_tag_ff_diff_inv,
tag_inverses[
static_cast<uint8_t
>(a_tag)] },
213 { Column::alu_helper1,
static_cast<uint128_t>(1) << b_num },
217 auto a_num =
static_cast<uint128_t>(
event.a.as_ff());
218 auto b_num =
static_cast<uint128_t>(
event.b.as_ff());
221 bool overflow = b_num > tag_bits;
224 auto shift_lo_bits = overflow ? tag_bits : b_num;
227 auto a_lo = overflow ? b_num - tag_bits : a_num % (
static_cast<uint128_t>(1) << shift_lo_bits);
229 { Column::alu_sel_op_shr, 1 },
230 { Column::alu_sel_shift_ops, 1 },
231 { Column::alu_sel_shift_ops_no_overflow, overflow ? 0 : 1 },
232 { Column::alu_sel_decompose_a, is_ff ? 0 : 1 },
233 { Column::alu_a_lo, a_lo },
234 { Column::alu_a_lo_bits, shift_lo_bits },
235 { Column::alu_a_hi, a_num >> shift_lo_bits },
236 { Column::alu_a_hi_bits, overflow ? tag_bits : tag_bits - b_num },
237 { Column::alu_shift_lo_bits, shift_lo_bits },
238 { Column::alu_two_pow_shift_lo_bits,
static_cast<uint128_t>(1) << shift_lo_bits },
239 { Column::alu_sel_is_ff, is_ff },
240 { Column::alu_tag_ff_diff_inv,
tag_inverses[
static_cast<uint8_t
>(a_tag)] },
248 bool is_lt_128 = !is_trivial && value < (static_cast<uint256_t>(1) << 128);
249 bool is_gte_128 = !is_trivial && !is_lt_128;
252 const uint256_t mid = is_trivial ? 0 : lo_128 >> dst_bits;
255 { Column::alu_sel_op_truncate, 1 },
256 { Column::alu_sel_trunc_trivial, is_trivial },
257 { Column::alu_sel_trunc_lt_128, is_lt_128 },
258 { Column::alu_sel_trunc_gte_128, is_gte_128 },
259 { Column::alu_sel_trunc_non_trivial, !is_trivial },
260 { Column::alu_a_lo, lo_128 },
261 { Column::alu_a_hi, is_gte_128 ?
value >> 128 : 0 },
262 { Column::alu_mid, mid },
264 { Column::alu_mid_bits, is_trivial ? 0 : 128 - dst_bits },
268 throw std::runtime_error(
"Unknown ALU operation");