1use alloc::{format, rc::Rc};
2use core::marker::PhantomData;
3use std::{cell::RefCell, collections::HashMap, hash::Hash};
4
5use openvm_stark_backend::p3_field::{
6 BasedVectorSpace, ExtensionField, Field, PrimeCharacteristicRing, PrimeField,
7};
8use serde::{Deserialize, Serialize};
9
10use super::{
11 utils::prime_field_to_usize, Builder, Config, DslIr, ExtConst, FromConstant, MemIndex,
12 MemVariable, Ptr, RVar, SymbolicExt, SymbolicFelt, SymbolicVar, Variable,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
19pub struct Var<N>(pub u32, pub PhantomData<N>);
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub struct Felt<F>(pub u32, pub PhantomData<F>);
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub struct Ext<F, EF>(pub u32, pub PhantomData<(F, EF)>);
32
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35pub enum Usize<N> {
36 Const(Rc<RefCell<N>>),
38 Var(Var<N>),
39}
40
41#[derive(Debug, Clone, Default, Serialize, Deserialize)]
42pub struct Witness<C: Config> {
43 pub vars: Vec<C::N>,
44 pub felts: Vec<C::F>,
45 pub exts: Vec<C::EF>,
46}
47
48impl<C: Config> Witness<C> {
49 pub fn size(&self) -> usize {
50 self.vars.len() + self.felts.len() + self.exts.len() + 2
51 }
52}
53
54#[derive(Debug, Clone, Copy)]
55pub enum WitnessRef {
56 Var(u32),
57 Felt(u32),
58 Ext(u32),
59}
60
61impl<N> From<Var<N>> for WitnessRef {
62 fn from(var: Var<N>) -> Self {
63 Self::Var(var.0)
64 }
65}
66
67impl<F> From<Felt<F>> for WitnessRef {
68 fn from(felt: Felt<F>) -> Self {
69 Self::Felt(felt.0)
70 }
71}
72
73impl<F, EF> From<Ext<F, EF>> for WitnessRef {
74 fn from(ext: Ext<F, EF>) -> Self {
75 Self::Ext(ext.0)
76 }
77}
78
79impl<N> From<WitnessRef> for Var<N> {
80 fn from(witness_ref: WitnessRef) -> Self {
81 match witness_ref {
82 WitnessRef::Var(id) => Var(id, Default::default()),
83 _ => panic!("Type doesn't match!"),
84 }
85 }
86}
87impl<F> From<WitnessRef> for Felt<F> {
88 fn from(witness_ref: WitnessRef) -> Self {
89 match witness_ref {
90 WitnessRef::Felt(id) => Felt(id, Default::default()),
91 _ => panic!("Type doesn't match!"),
92 }
93 }
94}
95
96impl<F, EF> From<WitnessRef> for Ext<F, EF> {
97 fn from(witness_ref: WitnessRef) -> Self {
98 match witness_ref {
99 WitnessRef::Ext(id) => Ext(id, Default::default()),
100 _ => panic!("Type doesn't match!"),
101 }
102 }
103}
104
105impl<N: PrimeField> Usize<N> {
106 pub fn is_const(&self) -> bool {
107 match self {
108 Usize::Const(_) => true,
109 Usize::Var(_) => false,
110 }
111 }
112
113 pub fn value(&self) -> usize {
114 match self {
115 Usize::Const(c) => prime_field_to_usize(*c.borrow()),
116 Usize::Var(_) => panic!("Cannot get the value of a variable"),
117 }
118 }
119
120 pub fn get_var(&self) -> Var<N> {
121 match self {
122 Usize::Const(_) => panic!("Cannot get the variable of a constant"),
123 Usize::Var(v) => *v,
124 }
125 }
126
127 pub fn from_field(value: N) -> Self {
128 Usize::Const(Rc::new(RefCell::new(value)))
129 }
130}
131
132impl<N: PrimeField> From<Var<N>> for Usize<N> {
133 fn from(v: Var<N>) -> Self {
134 Usize::Var(v)
135 }
136}
137
138impl<N: PrimeField> From<usize> for Usize<N> {
139 fn from(c: usize) -> Self {
140 Usize::Const(Rc::new(RefCell::new(N::from_usize(c))))
141 }
142}
143
144impl<N: PrimeField> From<Usize<N>> for RVar<N> {
145 fn from(u: Usize<N>) -> Self {
146 match u {
147 Usize::Const(c) => RVar::Const(*c.borrow()),
148 Usize::Var(v) => RVar::Val(v),
149 }
150 }
151}
152
153impl<N> Var<N> {
154 pub const fn new(id: u32) -> Self {
155 Self(id, PhantomData)
156 }
157
158 pub fn id(&self) -> String {
159 format!("var{}", self.0)
160 }
161
162 pub fn loc(&self) -> String {
163 self.0.to_string()
164 }
165}
166
167impl<F> Felt<F> {
168 pub const fn new(id: u32) -> Self {
169 Self(id, PhantomData)
170 }
171
172 pub fn id(&self) -> String {
173 format!("felt{}", self.0)
174 }
175
176 pub fn loc(&self) -> String {
177 self.0.to_string()
178 }
179
180 pub fn inverse(&self) -> SymbolicFelt<F>
181 where
182 F: Field,
183 {
184 SymbolicFelt::<F>::ONE / *self
185 }
186}
187
188impl<F, EF> Ext<F, EF> {
189 pub const fn new(id: u32) -> Self {
190 Self(id, PhantomData)
191 }
192
193 pub fn id(&self) -> String {
194 format!("ext{}", self.0)
195 }
196
197 pub fn loc(&self) -> String {
198 self.0.to_string()
199 }
200
201 pub fn inverse(&self) -> SymbolicExt<F, EF>
202 where
203 F: PrimeField,
204 EF: ExtensionField<F>,
205 {
206 SymbolicExt::<F, EF>::ONE / *self
207 }
208}
209
210impl<C: Config> Variable<C> for Usize<C::N> {
211 type Expression = SymbolicVar<C::N>;
212
213 fn uninit(builder: &mut Builder<C>) -> Self {
214 if builder.flags.static_only {
215 Usize::Const(Rc::new(RefCell::new(C::N::ZERO)))
216 } else {
217 builder.uninit::<Var<C::N>>().into()
218 }
219 }
220
221 fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
222 match self {
223 Usize::Const(c) => {
224 *c.borrow_mut() = if let SymbolicVar::Const(c, _) = src {
225 if !builder.is_sub_builder {
226 c
227 } else {
228 panic!("cannot assign Usize::Const inside a closure")
229 }
230 } else {
231 panic!("cannot assign Usize::Const with a variable")
232 }
233 }
234 Usize::Var(v) => {
235 builder.assign(v, src);
236 }
237 }
238 }
239
240 fn assert_eq(
241 lhs: impl Into<Self::Expression>,
242 rhs: impl Into<Self::Expression>,
243 builder: &mut Builder<C>,
244 ) {
245 Var::<C::N>::assert_eq(lhs, rhs, builder);
246 }
247
248 fn eval(builder: &mut Builder<C>, expr: impl Into<Self::Expression>) -> Self {
249 let expr = expr.into();
250 match expr {
251 SymbolicVar::Const(c, _) => {
252 if builder.flags.static_only {
254 Usize::from_field(c)
255 } else {
256 Usize::Var(builder.eval(c))
257 }
258 }
259 _ => Usize::Var(builder.eval(expr)),
260 }
261 }
262}
263
264impl<N: Field> Var<N> {
265 fn assign_with_cache<C: Config<N = N>>(
266 &self,
267 src: SymbolicVar<N>,
268 builder: &mut Builder<C>,
269 cache: &mut HashMap<SymbolicVar<N>, Self>,
270 ) {
271 if let Some(v) = cache.get(&src) {
272 builder.operations.push(DslIr::AddVI(*self, *v, C::N::ZERO));
273 return;
274 }
275 match src {
276 SymbolicVar::Const(c, _) => {
277 builder.operations.push(DslIr::ImmV(*self, c));
278 }
279 SymbolicVar::Val(v, _) => {
280 builder.operations.push(DslIr::AddVI(*self, v, C::N::ZERO));
281 }
282 SymbolicVar::Add(lhs, rhs, _) => match (&*lhs, &*rhs) {
283 (SymbolicVar::Const(lhs, _), SymbolicVar::Const(rhs, _)) => {
284 let sum = *lhs + *rhs;
285 builder.operations.push(DslIr::ImmV(*self, sum));
286 }
287 (SymbolicVar::Const(lhs, _), SymbolicVar::Val(rhs, _)) => {
288 builder.operations.push(DslIr::AddVI(*self, *rhs, *lhs));
289 }
290 (SymbolicVar::Const(lhs, _), rhs) => {
291 let rhs_value = Self::uninit(builder);
292 rhs_value.assign(rhs.clone(), builder);
293 builder.push(DslIr::AddVI(*self, rhs_value, *lhs));
294 }
295 (SymbolicVar::Val(lhs, _), SymbolicVar::Const(rhs, _)) => {
296 builder.push(DslIr::AddVI(*self, *lhs, *rhs));
297 }
298 (SymbolicVar::Val(lhs, _), SymbolicVar::Val(rhs, _)) => {
299 builder.push(DslIr::AddV(*self, *lhs, *rhs));
300 }
301 (SymbolicVar::Val(lhs, _), rhs) => {
302 let rhs_value = Self::uninit(builder);
303 rhs_value.assign(rhs.clone(), builder);
304 builder.push(DslIr::AddV(*self, *lhs, rhs_value));
305 }
306 (lhs, SymbolicVar::Const(rhs, _)) => {
307 let lhs_value = Self::uninit(builder);
308 lhs_value.assign(lhs.clone(), builder);
309 builder.push(DslIr::AddVI(*self, lhs_value, *rhs));
310 }
311 (lhs, SymbolicVar::Val(rhs, _)) => {
312 let lhs_value = Self::uninit(builder);
313 lhs_value.assign(lhs.clone(), builder);
314 builder.push(DslIr::AddV(*self, lhs_value, *rhs));
315 }
316 (lhs, rhs) => {
317 let lhs_value = Self::uninit(builder);
318 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
319 cache.insert(lhs.clone(), lhs_value);
320 let rhs_value = Self::uninit(builder);
321 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
322 cache.insert(rhs.clone(), rhs_value);
323 builder.push(DslIr::AddV(*self, lhs_value, rhs_value));
324 }
325 },
326 SymbolicVar::Mul(lhs, rhs, _) => match (&*lhs, &*rhs) {
327 (SymbolicVar::Const(lhs, _), SymbolicVar::Const(rhs, _)) => {
328 let product = *lhs * *rhs;
329 builder.push(DslIr::ImmV(*self, product));
330 }
331 (SymbolicVar::Const(lhs, _), SymbolicVar::Val(rhs, _)) => {
332 builder.push(DslIr::MulVI(*self, *rhs, *lhs));
333 }
334 (SymbolicVar::Const(lhs, _), rhs) => {
335 let rhs_value = Self::uninit(builder);
336 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
337 cache.insert(rhs.clone(), rhs_value);
338 builder.push(DslIr::MulVI(*self, rhs_value, *lhs));
339 }
340 (SymbolicVar::Val(lhs, _), SymbolicVar::Const(rhs, _)) => {
341 builder.push(DslIr::MulVI(*self, *lhs, *rhs));
342 }
343 (SymbolicVar::Val(lhs, _), SymbolicVar::Val(rhs, _)) => {
344 builder.push(DslIr::MulV(*self, *lhs, *rhs));
345 }
346 (SymbolicVar::Val(lhs, _), rhs) => {
347 let rhs_value = Self::uninit(builder);
348 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
349 cache.insert(rhs.clone(), rhs_value);
350 builder.push(DslIr::MulV(*self, *lhs, rhs_value));
351 }
352 (lhs, SymbolicVar::Const(rhs, _)) => {
353 let lhs_value = Self::uninit(builder);
354 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
355 cache.insert(lhs.clone(), lhs_value);
356 builder.push(DslIr::MulVI(*self, lhs_value, *rhs));
357 }
358 (lhs, SymbolicVar::Val(rhs, _)) => {
359 let lhs_value = Self::uninit(builder);
360 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
361 cache.insert(lhs.clone(), lhs_value);
362 builder.push(DslIr::MulV(*self, lhs_value, *rhs));
363 }
364 (lhs, rhs) => {
365 let lhs_value = Self::uninit(builder);
366 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
367 cache.insert(lhs.clone(), lhs_value);
368 let rhs_value = Self::uninit(builder);
369 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
370 cache.insert(rhs.clone(), rhs_value);
371 builder.push(DslIr::MulV(*self, lhs_value, rhs_value));
372 }
373 },
374 SymbolicVar::Sub(lhs, rhs, _) => match (&*lhs, &*rhs) {
375 (SymbolicVar::Const(lhs, _), SymbolicVar::Const(rhs, _)) => {
376 let difference = *lhs - *rhs;
377 builder.push(DslIr::ImmV(*self, difference));
378 }
379 (SymbolicVar::Const(lhs, _), SymbolicVar::Val(rhs, _)) => {
380 builder.push(DslIr::SubVIN(*self, *lhs, *rhs));
381 }
382 (SymbolicVar::Const(lhs, _), rhs) => {
383 let rhs_value = Self::uninit(builder);
384 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
385 cache.insert(rhs.clone(), rhs_value);
386 builder.push(DslIr::SubVIN(*self, *lhs, rhs_value));
387 }
388 (SymbolicVar::Val(lhs, _), SymbolicVar::Const(rhs, _)) => {
389 builder.push(DslIr::SubVI(*self, *lhs, *rhs));
390 }
391 (SymbolicVar::Val(lhs, _), SymbolicVar::Val(rhs, _)) => {
392 builder.push(DslIr::SubV(*self, *lhs, *rhs));
393 }
394 (SymbolicVar::Val(lhs, _), rhs) => {
395 let rhs_value = Self::uninit(builder);
396 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
397 cache.insert(rhs.clone(), rhs_value);
398 builder.push(DslIr::SubV(*self, *lhs, rhs_value));
399 }
400 (lhs, SymbolicVar::Const(rhs, _)) => {
401 let lhs_value = Self::uninit(builder);
402 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
403 cache.insert(lhs.clone(), lhs_value);
404 builder.push(DslIr::SubVI(*self, lhs_value, *rhs));
405 }
406 (lhs, SymbolicVar::Val(rhs, _)) => {
407 let lhs_value = Self::uninit(builder);
408 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
409 cache.insert(lhs.clone(), lhs_value);
410 builder.push(DslIr::SubV(*self, lhs_value, *rhs));
411 }
412 (lhs, rhs) => {
413 let lhs_value = Self::uninit(builder);
414 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
415 cache.insert(lhs.clone(), lhs_value);
416 let rhs_value = Self::uninit(builder);
417 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
418 cache.insert(rhs.clone(), rhs_value);
419 builder.push(DslIr::SubV(*self, lhs_value, rhs_value));
420 }
421 },
422 SymbolicVar::Neg(operand, _) => match &*operand {
423 SymbolicVar::Const(operand, _) => {
424 let negated = -*operand;
425 builder.push(DslIr::ImmV(*self, negated));
426 }
427 SymbolicVar::Val(operand, _) => {
428 builder.push(DslIr::SubVIN(*self, C::N::ZERO, *operand));
429 }
430 operand => {
431 let operand_value = Self::uninit(builder);
432 operand_value.assign_with_cache(operand.clone(), builder, cache);
433 cache.insert(operand.clone(), operand_value);
434 builder.push(DslIr::SubVIN(*self, C::N::ZERO, operand_value));
435 }
436 },
437 }
438 }
439}
440
441impl<C: Config> Variable<C> for Var<C::N> {
442 type Expression = SymbolicVar<C::N>;
443
444 fn uninit(builder: &mut Builder<C>) -> Self {
445 builder.var_count += 1;
446 Var(builder.var_count, PhantomData)
447 }
448
449 fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
450 self.assign_with_cache(src, builder, &mut HashMap::new());
451 }
452
453 fn assert_eq(
454 lhs: impl Into<Self::Expression>,
455 rhs: impl Into<Self::Expression>,
456 builder: &mut Builder<C>,
457 ) {
458 let lhs = lhs.into();
459 let rhs = rhs.into();
460
461 match (lhs, rhs) {
462 (SymbolicVar::Const(lhs, _), SymbolicVar::Const(rhs, _)) => {
463 assert_eq!(lhs, rhs, "Assertion failed at compile time");
464 }
465 (SymbolicVar::Const(lhs, _), SymbolicVar::Val(rhs, _)) => {
466 builder.trace_push(DslIr::AssertEqVI(rhs, lhs));
467 }
468 (SymbolicVar::Const(lhs, _), rhs) => {
469 let rhs_value = Self::uninit(builder);
470 rhs_value.assign(rhs, builder);
471 builder.trace_push(DslIr::AssertEqVI(rhs_value, lhs));
472 }
473 (SymbolicVar::Val(lhs, _), SymbolicVar::Const(rhs, _)) => {
474 builder.trace_push(DslIr::AssertEqVI(lhs, rhs));
475 }
476 (SymbolicVar::Val(lhs, _), SymbolicVar::Val(rhs, _)) => {
477 builder.trace_push(DslIr::AssertEqV(lhs, rhs));
478 }
479 (SymbolicVar::Val(lhs, _), rhs) => {
480 let rhs_value = Self::uninit(builder);
481 rhs_value.assign(rhs, builder);
482 builder.trace_push(DslIr::AssertEqV(lhs, rhs_value));
483 }
484 (lhs, rhs) => {
485 let lhs_value = Self::uninit(builder);
486 lhs_value.assign(lhs, builder);
487 let rhs_value = Self::uninit(builder);
488 rhs_value.assign(rhs, builder);
489 builder.trace_push(DslIr::AssertEqV(lhs_value, rhs_value));
490 }
491 }
492 }
493}
494
495impl<C: Config> MemVariable<C> for Var<C::N> {
496 fn size_of() -> usize {
497 1
498 }
499
500 fn load(&self, ptr: Ptr<C::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
501 builder.push(DslIr::LoadV(*self, ptr, index));
502 }
503
504 fn store(&self, ptr: Ptr<<C as Config>::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
505 builder.push(DslIr::StoreV(*self, ptr, index));
506 }
507}
508
509impl<C: Config> MemVariable<C> for Usize<C::N> {
510 fn size_of() -> usize {
511 1
512 }
513
514 fn load(&self, ptr: Ptr<C::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
515 match self {
516 Usize::Const(_) => {
517 panic!("Usize::Const should not be loaded");
518 }
519 Usize::Var(v) => {
520 builder.push(DslIr::LoadV(*v, ptr, index));
521 }
522 }
523 }
524
525 fn store(&self, ptr: Ptr<<C as Config>::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
526 match self {
527 Usize::Const(_) => {
528 panic!("Usize::Const should not be stored");
529 }
530 Usize::Var(v) => {
531 builder.push(DslIr::StoreV(*v, ptr, index));
532 }
533 }
534 }
535}
536
537impl<F: Field> Felt<F> {
538 fn assign_with_cache<C: Config<F = F>>(
539 &self,
540 src: SymbolicFelt<F>,
541 builder: &mut Builder<C>,
542 cache: &mut HashMap<SymbolicFelt<F>, Self>,
543 ) {
544 if let Some(v) = cache.get(&src) {
545 builder.operations.push(DslIr::AddFI(*self, *v, C::F::ZERO));
546 return;
547 }
548 match src {
549 SymbolicFelt::Const(c, _) => {
550 builder.operations.push(DslIr::ImmF(*self, c));
551 }
552 SymbolicFelt::Val(v, _) => {
553 builder.operations.push(DslIr::AddFI(*self, v, C::F::ZERO));
554 }
555 SymbolicFelt::Add(lhs, rhs, _) => match (&*lhs, &*rhs) {
556 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Const(rhs, _)) => {
557 let sum = *lhs + *rhs;
558 builder.operations.push(DslIr::ImmF(*self, sum));
559 }
560 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Val(rhs, _)) => {
561 builder.operations.push(DslIr::AddFI(*self, *rhs, *lhs));
562 }
563 (SymbolicFelt::Const(lhs, _), rhs) => {
564 let rhs_value = Self::uninit(builder);
565 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
566 cache.insert(rhs.clone(), rhs_value);
567 builder.push(DslIr::AddFI(*self, rhs_value, *lhs));
568 }
569 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Const(rhs, _)) => {
570 builder.push(DslIr::AddFI(*self, *lhs, *rhs));
571 }
572 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Val(rhs, _)) => {
573 builder.push(DslIr::AddF(*self, *lhs, *rhs));
574 }
575 (SymbolicFelt::Val(lhs, _), rhs) => {
576 let rhs_value = Self::uninit(builder);
577 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
578 cache.insert(rhs.clone(), rhs_value);
579 builder.push(DslIr::AddF(*self, *lhs, rhs_value));
580 }
581 (lhs, SymbolicFelt::Const(rhs, _)) => {
582 let lhs_value = Self::uninit(builder);
583 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
584 cache.insert(lhs.clone(), lhs_value);
585 builder.push(DslIr::AddFI(*self, lhs_value, *rhs));
586 }
587 (lhs, SymbolicFelt::Val(rhs, _)) => {
588 let lhs_value = Self::uninit(builder);
589 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
590 cache.insert(lhs.clone(), lhs_value);
591 builder.push(DslIr::AddF(*self, lhs_value, *rhs));
592 }
593 (lhs, rhs) => {
594 let lhs_value = Self::uninit(builder);
595 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
596 cache.insert(lhs.clone(), lhs_value);
597 let rhs_value = Self::uninit(builder);
598 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
599 cache.insert(rhs.clone(), rhs_value);
600 builder.push(DslIr::AddF(*self, lhs_value, rhs_value));
601 }
602 },
603 SymbolicFelt::Mul(lhs, rhs, _) => match (&*lhs, &*rhs) {
604 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Const(rhs, _)) => {
605 let product = *lhs * *rhs;
606 builder.push(DslIr::ImmF(*self, product));
607 }
608 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Val(rhs, _)) => {
609 builder.push(DslIr::MulFI(*self, *rhs, *lhs));
610 }
611 (SymbolicFelt::Const(lhs, _), rhs) => {
612 let rhs_value = Self::uninit(builder);
613 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
614 cache.insert(rhs.clone(), rhs_value);
615 builder.push(DslIr::MulFI(*self, rhs_value, *lhs));
616 }
617 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Const(rhs, _)) => {
618 builder.push(DslIr::MulFI(*self, *lhs, *rhs));
619 }
620 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Val(rhs, _)) => {
621 builder.push(DslIr::MulF(*self, *lhs, *rhs));
622 }
623 (SymbolicFelt::Val(lhs, _), rhs) => {
624 let rhs_value = Self::uninit(builder);
625 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
626 cache.insert(rhs.clone(), rhs_value);
627 builder.push(DslIr::MulF(*self, *lhs, rhs_value));
628 }
629 (lhs, SymbolicFelt::Const(rhs, _)) => {
630 let lhs_value = Self::uninit(builder);
631 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
632 cache.insert(lhs.clone(), lhs_value);
633 builder.push(DslIr::MulFI(*self, lhs_value, *rhs));
634 }
635 (lhs, SymbolicFelt::Val(rhs, _)) => {
636 let lhs_value = Self::uninit(builder);
637 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
638 cache.insert(lhs.clone(), lhs_value);
639 builder.push(DslIr::MulF(*self, lhs_value, *rhs));
640 }
641 (lhs, rhs) => {
642 let lhs_value = Self::uninit(builder);
643 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
644 cache.insert(lhs.clone(), lhs_value);
645 let rhs_value = Self::uninit(builder);
646 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
647 cache.insert(rhs.clone(), rhs_value);
648 builder.push(DslIr::MulF(*self, lhs_value, rhs_value));
649 }
650 },
651 SymbolicFelt::Sub(lhs, rhs, _) => match (&*lhs, &*rhs) {
652 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Const(rhs, _)) => {
653 let difference = *lhs - *rhs;
654 builder.push(DslIr::ImmF(*self, difference));
655 }
656 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Val(rhs, _)) => {
657 builder.push(DslIr::SubFIN(*self, *lhs, *rhs));
658 }
659 (SymbolicFelt::Const(lhs, _), rhs) => {
660 let rhs_value = Self::uninit(builder);
661 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
662 cache.insert(rhs.clone(), rhs_value);
663 builder.push(DslIr::SubFIN(*self, *lhs, rhs_value));
664 }
665 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Const(rhs, _)) => {
666 builder.push(DslIr::SubFI(*self, *lhs, *rhs));
667 }
668 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Val(rhs, _)) => {
669 builder.push(DslIr::SubF(*self, *lhs, *rhs));
670 }
671 (SymbolicFelt::Val(lhs, _), rhs) => {
672 let rhs_value = Self::uninit(builder);
673 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
674 cache.insert(rhs.clone(), rhs_value);
675 builder.push(DslIr::SubF(*self, *lhs, rhs_value));
676 }
677 (lhs, SymbolicFelt::Const(rhs, _)) => {
678 let lhs_value = Self::uninit(builder);
679 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
680 cache.insert(lhs.clone(), lhs_value);
681 builder.push(DslIr::SubFI(*self, lhs_value, *rhs));
682 }
683 (lhs, SymbolicFelt::Val(rhs, _)) => {
684 let lhs_value = Self::uninit(builder);
685 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
686 cache.insert(lhs.clone(), lhs_value);
687 builder.push(DslIr::SubF(*self, lhs_value, *rhs));
688 }
689 (lhs, rhs) => {
690 let lhs_value = Self::uninit(builder);
691 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
692 cache.insert(lhs.clone(), lhs_value);
693 let rhs_value = Self::uninit(builder);
694 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
695 cache.insert(rhs.clone(), rhs_value);
696 builder.push(DslIr::SubF(*self, lhs_value, rhs_value));
697 }
698 },
699 SymbolicFelt::Div(lhs, rhs, _) => match (&*lhs, &*rhs) {
700 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Const(rhs, _)) => {
701 let quotient = *lhs / *rhs;
702 builder.push(DslIr::ImmF(*self, quotient));
703 }
704 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Val(rhs, _)) => {
705 builder.push(DslIr::DivFIN(*self, *lhs, *rhs));
706 }
707 (SymbolicFelt::Const(lhs, _), rhs) => {
708 let rhs_value = Self::uninit(builder);
709 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
710 cache.insert(rhs.clone(), rhs_value);
711 builder.push(DslIr::DivFIN(*self, *lhs, rhs_value));
712 }
713 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Const(rhs, _)) => {
714 builder.push(DslIr::DivFI(*self, *lhs, *rhs));
715 }
716 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Val(rhs, _)) => {
717 builder.push(DslIr::DivF(*self, *lhs, *rhs));
718 }
719 (SymbolicFelt::Val(lhs, _), rhs) => {
720 let rhs_value = Self::uninit(builder);
721 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
722 cache.insert(rhs.clone(), rhs_value);
723 builder.push(DslIr::DivF(*self, *lhs, rhs_value));
724 }
725 (lhs, SymbolicFelt::Const(rhs, _)) => {
726 let lhs_value = Self::uninit(builder);
727 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
728 cache.insert(lhs.clone(), lhs_value);
729 builder.push(DslIr::DivFI(*self, lhs_value, *rhs));
730 }
731 (lhs, SymbolicFelt::Val(rhs, _)) => {
732 let lhs_value = Self::uninit(builder);
733 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
734 cache.insert(lhs.clone(), lhs_value);
735 builder.push(DslIr::DivF(*self, lhs_value, *rhs));
736 }
737 (lhs, rhs) => {
738 let lhs_value = Self::uninit(builder);
739 lhs_value.assign_with_cache(lhs.clone(), builder, cache);
740 cache.insert(lhs.clone(), lhs_value);
741 let rhs_value = Self::uninit(builder);
742 rhs_value.assign_with_cache(rhs.clone(), builder, cache);
743 cache.insert(rhs.clone(), rhs_value);
744 builder.push(DslIr::DivF(*self, lhs_value, rhs_value));
745 }
746 },
747 SymbolicFelt::Neg(operand, _) => match &*operand {
748 SymbolicFelt::Const(operand, _) => {
749 let negated = -*operand;
750 builder.push(DslIr::ImmF(*self, negated));
751 }
752 SymbolicFelt::Val(operand, _) => {
753 builder.push(DslIr::SubFIN(*self, C::F::ZERO, *operand));
754 }
755 operand => {
756 let operand_value = Self::uninit(builder);
757 operand_value.assign_with_cache(operand.clone(), builder, cache);
758 cache.insert(operand.clone(), operand_value);
759 builder.push(DslIr::SubFIN(*self, C::F::ZERO, operand_value));
760 }
761 },
762 }
763 }
764}
765
766impl<C: Config> Variable<C> for Felt<C::F> {
767 type Expression = SymbolicFelt<C::F>;
768
769 fn uninit(builder: &mut Builder<C>) -> Self {
770 builder.felt_count += 1;
771 Felt(builder.felt_count, PhantomData)
772 }
773
774 fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
775 self.assign_with_cache(src, builder, &mut HashMap::new());
776 }
777
778 fn assert_eq(
779 lhs: impl Into<Self::Expression>,
780 rhs: impl Into<Self::Expression>,
781 builder: &mut Builder<C>,
782 ) {
783 let lhs = lhs.into();
784 let rhs = rhs.into();
785
786 match (lhs, rhs) {
787 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Const(rhs, _)) => {
788 assert_eq!(lhs, rhs, "Assertion failed at compile time");
789 }
790 (SymbolicFelt::Const(lhs, _), SymbolicFelt::Val(rhs, _)) => {
791 builder.trace_push(DslIr::AssertEqFI(rhs, lhs));
792 }
793 (SymbolicFelt::Const(lhs, _), rhs) => {
794 let rhs_value = Self::uninit(builder);
795 rhs_value.assign(rhs, builder);
796 builder.trace_push(DslIr::AssertEqFI(rhs_value, lhs));
797 }
798 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Const(rhs, _)) => {
799 builder.trace_push(DslIr::AssertEqFI(lhs, rhs));
800 }
801 (SymbolicFelt::Val(lhs, _), SymbolicFelt::Val(rhs, _)) => {
802 builder.trace_push(DslIr::AssertEqF(lhs, rhs));
803 }
804 (SymbolicFelt::Val(lhs, _), rhs) => {
805 let rhs_value = Self::uninit(builder);
806 rhs_value.assign(rhs, builder);
807 builder.trace_push(DslIr::AssertEqF(lhs, rhs_value));
808 }
809 (lhs, rhs) => {
810 let lhs_value = Self::uninit(builder);
811 lhs_value.assign(lhs, builder);
812 let rhs_value = Self::uninit(builder);
813 rhs_value.assign(rhs, builder);
814 builder.trace_push(DslIr::AssertEqF(lhs_value, rhs_value));
815 }
816 }
817 }
818}
819
820impl<C: Config> MemVariable<C> for Felt<C::F> {
821 fn size_of() -> usize {
822 1
823 }
824
825 fn load(&self, ptr: Ptr<C::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
826 builder.push(DslIr::LoadF(*self, ptr, index));
827 }
828
829 fn store(&self, ptr: Ptr<<C as Config>::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
830 builder.push(DslIr::StoreF(*self, ptr, index));
831 }
832}
833
834impl<F: Field, EF: ExtensionField<F>> Ext<F, EF> {
835 fn assign_with_caches<C: Config<F = F, EF = EF>>(
836 &self,
837 src: SymbolicExt<F, EF>,
838 builder: &mut Builder<C>,
839 ext_cache: &mut HashMap<SymbolicExt<F, EF>, Ext<F, EF>>,
840 base_cache: &mut HashMap<SymbolicFelt<F>, Felt<F>>,
841 ) {
842 if let Some(v) = ext_cache.get(&src) {
843 builder
844 .operations
845 .push(DslIr::AddEI(*self, *v, C::EF::ZERO));
846 return;
847 }
848 match src {
849 SymbolicExt::Base(v, _) => match &*v {
850 SymbolicFelt::Const(c, _) => {
851 builder.operations.push(DslIr::ImmE(*self, (*c).into()));
852 }
853 SymbolicFelt::Val(v, _) => {
854 builder
855 .operations
856 .push(DslIr::AddEFFI(*self, *v, C::EF::ZERO));
857 }
858 v => {
859 let v_value = Felt::uninit(builder);
860 v_value.assign(v.clone(), builder);
861 builder.push(DslIr::AddEFFI(*self, v_value, C::EF::ZERO));
862 }
863 },
864 SymbolicExt::Const(c, _) => {
865 builder.operations.push(DslIr::ImmE(*self, c));
866 }
867 SymbolicExt::Val(v, _) => {
868 builder.operations.push(DslIr::AddEI(*self, v, C::EF::ZERO));
869 }
870 SymbolicExt::Add(lhs, rhs, _) => match (&*lhs, &*rhs) {
871 (SymbolicExt::Const(lhs, _), SymbolicExt::Const(rhs, _)) => {
872 let sum = *lhs + *rhs;
873 builder.operations.push(DslIr::ImmE(*self, sum));
874 }
875 (SymbolicExt::Const(lhs, _), SymbolicExt::Val(rhs, _)) => {
876 builder.operations.push(DslIr::AddEI(*self, *rhs, *lhs));
877 }
878 (SymbolicExt::Const(lhs, _), SymbolicExt::Base(rhs, _)) => match rhs.as_ref() {
879 SymbolicFelt::Const(rhs, _) => {
880 let sum = *lhs + EF::from(*rhs);
881 builder.operations.push(DslIr::ImmE(*self, sum));
882 }
883 SymbolicFelt::Val(rhs, _) => {
884 builder.operations.push(DslIr::AddEFFI(*self, *rhs, *lhs));
885 }
886 rhs => {
887 let rhs_value: Felt<_> = Felt::uninit(builder);
888 rhs_value.assign_with_cache(rhs.clone(), builder, base_cache);
889 base_cache.insert(rhs.clone(), rhs_value);
890 builder
891 .operations
892 .push(DslIr::AddEFFI(*self, rhs_value, *lhs));
893 }
894 },
895 (SymbolicExt::Const(lhs, _), rhs) => {
896 let rhs_value = Self::uninit(builder);
897 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
898 ext_cache.insert(rhs.clone(), rhs_value);
899 builder.push(DslIr::AddEI(*self, rhs_value, *lhs));
900 }
901 (SymbolicExt::Val(lhs, _), SymbolicExt::Const(rhs, _)) => {
902 builder.push(DslIr::AddEI(*self, *lhs, *rhs));
903 }
904 (SymbolicExt::Val(lhs, _), SymbolicExt::Base(rhs, _)) => match rhs.as_ref() {
905 SymbolicFelt::Const(rhs, _) => {
906 builder.push(DslIr::AddEFI(*self, *lhs, *rhs));
907 }
908 SymbolicFelt::Val(rhs, _) => {
909 builder.push(DslIr::AddEF(*self, *lhs, *rhs));
910 }
911 rhs => {
912 let rhs = builder.eval(rhs.clone());
913 builder.push(DslIr::AddEF(*self, *lhs, rhs));
914 }
915 },
916 (SymbolicExt::Val(lhs, _), SymbolicExt::Val(rhs, _)) => {
917 builder.push(DslIr::AddE(*self, *lhs, *rhs));
918 }
919 (SymbolicExt::Val(lhs, _), rhs) => {
920 let rhs_value = Self::uninit(builder);
921 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
922 ext_cache.insert(rhs.clone(), rhs_value);
923 builder.push(DslIr::AddE(*self, *lhs, rhs_value));
924 }
925 (lhs, SymbolicExt::Const(rhs, _)) => {
926 let lhs_value = Self::uninit(builder);
927 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
928 ext_cache.insert(lhs.clone(), lhs_value);
929 builder.push(DslIr::AddEI(*self, lhs_value, *rhs));
930 }
931 (lhs, SymbolicExt::Val(rhs, _)) => {
932 let lhs_value = Self::uninit(builder);
933 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
934 ext_cache.insert(lhs.clone(), lhs_value);
935 builder.push(DslIr::AddE(*self, lhs_value, *rhs));
936 }
937 (lhs, rhs) => {
938 let lhs_value = Self::uninit(builder);
939 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
940 ext_cache.insert(lhs.clone(), lhs_value);
941 let rhs_value = Self::uninit(builder);
942 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
943 ext_cache.insert(rhs.clone(), rhs_value);
944 builder.push(DslIr::AddE(*self, lhs_value, rhs_value));
945 }
946 },
947 SymbolicExt::Mul(lhs, rhs, _) => match (&*lhs, &*rhs) {
948 (SymbolicExt::Const(lhs, _), SymbolicExt::Const(rhs, _)) => {
949 let product = *lhs * *rhs;
950 builder.push(DslIr::ImmE(*self, product));
951 }
952 (SymbolicExt::Const(lhs, _), SymbolicExt::Val(rhs, _)) => {
953 builder.push(DslIr::MulEI(*self, *rhs, *lhs));
954 }
955 (SymbolicExt::Const(lhs, _), rhs) => {
956 let rhs_value = Self::uninit(builder);
957 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
958 ext_cache.insert(rhs.clone(), rhs_value);
959 builder.push(DslIr::MulEI(*self, rhs_value, *lhs));
960 }
961 (SymbolicExt::Val(lhs, _), SymbolicExt::Const(rhs, _)) => {
962 builder.push(DslIr::MulEI(*self, *lhs, *rhs));
963 }
964 (SymbolicExt::Val(lhs, _), SymbolicExt::Val(rhs, _)) => {
965 builder.push(DslIr::MulE(*self, *lhs, *rhs));
966 }
967 (SymbolicExt::Val(lhs, _), SymbolicExt::Base(rhs, _)) => match rhs.as_ref() {
968 SymbolicFelt::Const(rhs, _) => {
969 builder.push(DslIr::MulEFI(*self, *lhs, *rhs));
970 }
971 SymbolicFelt::Val(rhs, _) => {
972 builder.push(DslIr::MulEF(*self, *lhs, *rhs));
973 }
974 rhs => {
975 let rhs = builder.eval(rhs.clone());
976 builder.push(DslIr::MulEF(*self, *lhs, rhs));
977 }
978 },
979 (SymbolicExt::Val(lhs, _), rhs) => {
980 let rhs_value = Self::uninit(builder);
981 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
982 ext_cache.insert(rhs.clone(), rhs_value);
983 builder.push(DslIr::MulE(*self, *lhs, rhs_value));
984 }
985 (lhs, SymbolicExt::Const(rhs, _)) => {
986 let lhs_value = Self::uninit(builder);
987 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
988 ext_cache.insert(lhs.clone(), lhs_value);
989 builder.push(DslIr::MulEI(*self, lhs_value, *rhs));
990 }
991 (lhs, SymbolicExt::Val(rhs, _)) => {
992 let lhs_value = Self::uninit(builder);
993 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
994 ext_cache.insert(lhs.clone(), lhs_value);
995 builder.push(DslIr::MulE(*self, lhs_value, *rhs));
996 }
997 (lhs, rhs) => {
998 let lhs_value = Self::uninit(builder);
999 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
1000 ext_cache.insert(lhs.clone(), lhs_value);
1001 let rhs_value = Self::uninit(builder);
1002 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
1003 ext_cache.insert(rhs.clone(), rhs_value);
1004 builder.push(DslIr::MulE(*self, lhs_value, rhs_value));
1005 }
1006 },
1007 SymbolicExt::Sub(lhs, rhs, _) => match (&*lhs, &*rhs) {
1008 (SymbolicExt::Const(lhs, _), SymbolicExt::Const(rhs, _)) => {
1009 let difference = *lhs - *rhs;
1010 builder.push(DslIr::ImmE(*self, difference));
1011 }
1012 (SymbolicExt::Const(lhs, _), SymbolicExt::Val(rhs, _)) => {
1013 builder.push(DslIr::SubEIN(*self, *lhs, *rhs));
1014 }
1015 (SymbolicExt::Const(lhs, _), rhs) => {
1016 let rhs_value = Self::uninit(builder);
1017 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
1018 ext_cache.insert(rhs.clone(), rhs_value);
1019 builder.push(DslIr::SubEIN(*self, *lhs, rhs_value));
1020 }
1021 (SymbolicExt::Val(lhs, _), SymbolicExt::Const(rhs, _)) => {
1022 builder.push(DslIr::SubEI(*self, *lhs, *rhs));
1023 }
1024 (SymbolicExt::Val(lhs, _), SymbolicExt::Val(rhs, _)) => {
1025 builder.push(DslIr::SubE(*self, *lhs, *rhs));
1026 }
1027 (SymbolicExt::Val(lhs, _), SymbolicExt::Base(rhs, _)) => match rhs.as_ref() {
1028 SymbolicFelt::Const(rhs, _) => {
1029 builder.push(DslIr::SubEFI(*self, *lhs, *rhs));
1030 }
1031 SymbolicFelt::Val(rhs, _) => {
1032 builder.push(DslIr::SubEF(*self, *lhs, *rhs));
1033 }
1034 rhs => {
1035 let rhs = builder.eval(rhs.clone());
1036 builder.push(DslIr::SubEF(*self, *lhs, rhs));
1037 }
1038 },
1039 (SymbolicExt::Val(lhs, _), rhs) => {
1040 let rhs_value = Self::uninit(builder);
1041 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
1042 ext_cache.insert(rhs.clone(), rhs_value);
1043 builder.push(DslIr::SubE(*self, *lhs, rhs_value));
1044 }
1045 (lhs, SymbolicExt::Const(rhs, _)) => {
1046 let lhs_value = Self::uninit(builder);
1047 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
1048 ext_cache.insert(lhs.clone(), lhs_value);
1049 builder.push(DslIr::SubEI(*self, lhs_value, *rhs));
1050 }
1051 (lhs, SymbolicExt::Val(rhs, _)) => {
1052 let lhs_value = Self::uninit(builder);
1053 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
1054 ext_cache.insert(lhs.clone(), lhs_value);
1055 builder.push(DslIr::SubE(*self, lhs_value, *rhs));
1056 }
1057 (lhs, rhs) => {
1058 let lhs_value = Self::uninit(builder);
1059 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
1060 ext_cache.insert(lhs.clone(), lhs_value);
1061 let rhs_value = Self::uninit(builder);
1062 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
1063 builder.push(DslIr::SubE(*self, lhs_value, rhs_value));
1064 }
1065 },
1066 SymbolicExt::Div(lhs, rhs, _) => match (&*lhs, &*rhs) {
1067 (SymbolicExt::Const(lhs, _), SymbolicExt::Const(rhs, _)) => {
1068 let quotient = *lhs / *rhs;
1069 builder.push(DslIr::ImmE(*self, quotient));
1070 }
1071 (SymbolicExt::Const(lhs, _), SymbolicExt::Val(rhs, _)) => {
1072 builder.push(DslIr::DivEIN(*self, *lhs, *rhs));
1073 }
1074 (SymbolicExt::Const(lhs, _), rhs) => {
1075 let rhs_value = Self::uninit(builder);
1076 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
1077 ext_cache.insert(rhs.clone(), rhs_value);
1078 builder.push(DslIr::DivEIN(*self, *lhs, rhs_value));
1079 }
1080 (SymbolicExt::Val(lhs, _), SymbolicExt::Const(rhs, _)) => {
1081 builder.push(DslIr::DivEI(*self, *lhs, *rhs));
1082 }
1083 (SymbolicExt::Val(lhs, _), SymbolicExt::Val(rhs, _)) => {
1084 builder.push(DslIr::DivE(*self, *lhs, *rhs));
1085 }
1086 (SymbolicExt::Val(lhs, _), SymbolicExt::Base(rhs, _)) => match rhs.as_ref() {
1087 SymbolicFelt::Const(rhs, _) => {
1088 builder.push(DslIr::DivEFI(*self, *lhs, *rhs));
1089 }
1090 SymbolicFelt::Val(rhs, _) => {
1091 builder.push(DslIr::DivEF(*self, *lhs, *rhs));
1092 }
1093 rhs => {
1094 let rhs = builder.eval(rhs.clone());
1095 builder.push(DslIr::DivEF(*self, *lhs, rhs));
1096 }
1097 },
1098 (SymbolicExt::Val(lhs, _), rhs) => {
1099 let rhs_value = Self::uninit(builder);
1100 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
1101 ext_cache.insert(rhs.clone(), rhs_value);
1102 builder.push(DslIr::DivE(*self, *lhs, rhs_value));
1103 }
1104 (lhs, SymbolicExt::Const(rhs, _)) => {
1105 let lhs_value = Self::uninit(builder);
1106 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
1107 ext_cache.insert(lhs.clone(), lhs_value);
1108 builder.push(DslIr::DivEI(*self, lhs_value, *rhs));
1109 }
1110 (lhs, SymbolicExt::Val(rhs, _)) => {
1111 let lhs_value = Self::uninit(builder);
1112 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
1113 ext_cache.insert(lhs.clone(), lhs_value);
1114 builder.push(DslIr::DivE(*self, lhs_value, *rhs));
1115 }
1116 (lhs, rhs) => {
1117 let lhs_value = Self::uninit(builder);
1118 lhs_value.assign_with_caches(lhs.clone(), builder, ext_cache, base_cache);
1119 ext_cache.insert(lhs.clone(), lhs_value);
1120 let rhs_value = Self::uninit(builder);
1121 rhs_value.assign_with_caches(rhs.clone(), builder, ext_cache, base_cache);
1122 ext_cache.insert(rhs.clone(), rhs_value);
1123 builder.push(DslIr::DivE(*self, lhs_value, rhs_value));
1124 }
1125 },
1126 SymbolicExt::Neg(operand, _) => match &*operand {
1127 SymbolicExt::Const(operand, _) => {
1128 let negated = -*operand;
1129 builder.push(DslIr::ImmE(*self, negated));
1130 }
1131 SymbolicExt::Val(operand, _) => {
1132 builder.push(DslIr::NegE(*self, *operand));
1133 }
1134 operand => {
1135 let operand_value = Self::uninit(builder);
1136 operand_value.assign_with_caches(
1137 operand.clone(),
1138 builder,
1139 ext_cache,
1140 base_cache,
1141 );
1142 ext_cache.insert(operand.clone(), operand_value);
1143 builder.push(DslIr::NegE(*self, operand_value));
1144 }
1145 },
1146 }
1147 }
1148}
1149
1150impl<C: Config> Variable<C> for Ext<C::F, C::EF> {
1151 type Expression = SymbolicExt<C::F, C::EF>;
1152
1153 fn uninit(builder: &mut Builder<C>) -> Self {
1154 builder.ext_count += 1;
1155 Ext(builder.ext_count, PhantomData)
1156 }
1157
1158 fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
1159 self.assign_with_caches(src, builder, &mut HashMap::new(), &mut HashMap::new());
1160 }
1161
1162 fn assert_eq(
1163 lhs: impl Into<Self::Expression>,
1164 rhs: impl Into<Self::Expression>,
1165 builder: &mut Builder<C>,
1166 ) {
1167 let lhs = lhs.into();
1168 let rhs = rhs.into();
1169
1170 match (lhs, rhs) {
1171 (SymbolicExt::Const(lhs, _), SymbolicExt::Const(rhs, _)) => {
1172 assert_eq!(lhs, rhs, "Assertion failed at compile time");
1173 }
1174 (SymbolicExt::Const(lhs, _), SymbolicExt::Val(rhs, _)) => {
1175 builder.trace_push(DslIr::AssertEqEI(rhs, lhs));
1176 }
1177 (SymbolicExt::Const(lhs, _), rhs) => {
1178 let rhs_value = Self::uninit(builder);
1179 rhs_value.assign(rhs, builder);
1180 builder.trace_push(DslIr::AssertEqEI(rhs_value, lhs));
1181 }
1182 (SymbolicExt::Val(lhs, _), SymbolicExt::Const(rhs, _)) => {
1183 builder.trace_push(DslIr::AssertEqEI(lhs, rhs));
1184 }
1185 (SymbolicExt::Val(lhs, _), SymbolicExt::Val(rhs, _)) => {
1186 builder.trace_push(DslIr::AssertEqE(lhs, rhs));
1187 }
1188 (SymbolicExt::Val(lhs, _), rhs) => {
1189 let rhs_value = Self::uninit(builder);
1190 rhs_value.assign(rhs, builder);
1191 builder.trace_push(DslIr::AssertEqE(lhs, rhs_value));
1192 }
1193 (lhs, rhs) => {
1194 let lhs_value = Self::uninit(builder);
1195 lhs_value.assign(lhs, builder);
1196 let rhs_value = Self::uninit(builder);
1197 rhs_value.assign(rhs, builder);
1198 builder.trace_push(DslIr::AssertEqE(lhs_value, rhs_value));
1199 }
1200 }
1201 }
1202}
1203
1204impl<C: Config> MemVariable<C> for Ext<C::F, C::EF> {
1205 fn size_of() -> usize {
1206 C::EF::DIMENSION
1207 }
1208
1209 fn load(&self, ptr: Ptr<C::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
1210 builder.push(DslIr::LoadE(*self, ptr, index));
1211 }
1212
1213 fn store(&self, ptr: Ptr<<C as Config>::N>, index: MemIndex<C::N>, builder: &mut Builder<C>) {
1214 builder.push(DslIr::StoreE(*self, ptr, index));
1215 }
1216}
1217
1218impl<C: Config> FromConstant<C> for Var<C::N> {
1219 type Constant = C::N;
1220
1221 fn constant(value: Self::Constant, builder: &mut Builder<C>) -> Self {
1222 builder.eval(value)
1223 }
1224}
1225
1226impl<C: Config> FromConstant<C> for Felt<C::F> {
1227 type Constant = C::F;
1228
1229 fn constant(value: Self::Constant, builder: &mut Builder<C>) -> Self {
1230 builder.eval(value)
1231 }
1232}
1233
1234impl<C: Config> FromConstant<C> for Ext<C::F, C::EF> {
1235 type Constant = C::EF;
1236
1237 fn constant(value: Self::Constant, builder: &mut Builder<C>) -> Self {
1238 builder.eval(value.cons())
1239 }
1240}