Skip to main content

sp1_recursion_compiler/ir/
symbolic.rs

1use core::{
2    any::Any,
3    ops::{Add, Div, Mul, Neg, Sub},
4};
5use std::{
6    any::TypeId,
7    iter::{Product, Sum},
8    mem::{self, ManuallyDrop},
9    ops::{AddAssign, DivAssign, MulAssign, SubAssign},
10};
11
12use slop_algebra::{AbstractField, ExtensionField, Field};
13
14use crate::ir::ExtHandle;
15
16use super::{Ext, Felt, Var};
17
18#[derive(Debug, Clone, Copy)]
19pub enum SymbolicVar<N: Field> {
20    Const(N),
21    Val(Var<N>),
22}
23
24#[derive(Debug, Clone, Copy)]
25pub enum SymbolicFelt<F: Field> {
26    Const(F),
27    Val(Felt<F>),
28}
29
30#[derive(Debug, Clone, Copy)]
31pub enum SymbolicExt<F: Field, EF: Field> {
32    Const(EF),
33    Base(SymbolicFelt<F>),
34    Val(Ext<F, EF>),
35}
36
37impl<F: Field, EF: Field> SymbolicExt<F, EF> {
38    pub fn as_ext(&self) -> Option<Ext<F, EF>> {
39        match self {
40            SymbolicExt::Val(e) => Some(*e),
41            _ => None,
42        }
43    }
44}
45
46#[derive(Debug, Clone)]
47pub enum ExtOperand<F: Field, EF: ExtensionField<F>> {
48    Base(F),
49    Const(EF),
50    Felt(Felt<F>),
51    Ext(Ext<F, EF>),
52    SymFelt(SymbolicFelt<F>),
53    Sym(SymbolicExt<F, EF>),
54}
55
56impl<F: Field, EF: ExtensionField<F>> ExtOperand<F, EF> {
57    pub fn symbolic(self) -> SymbolicExt<F, EF> {
58        match self {
59            ExtOperand::Base(f) => SymbolicExt::Base(SymbolicFelt::from(f)),
60            ExtOperand::Const(ef) => SymbolicExt::Const(ef),
61            ExtOperand::Felt(f) => SymbolicExt::Base(SymbolicFelt::from(f)),
62            ExtOperand::Ext(e) => SymbolicExt::Val(e),
63            ExtOperand::SymFelt(f) => SymbolicExt::Base(f),
64            ExtOperand::Sym(e) => e,
65        }
66    }
67}
68
69pub trait ExtConst<F: Field, EF: ExtensionField<F>> {
70    fn cons(self) -> SymbolicExt<F, EF>;
71}
72
73impl<F: Field, EF: ExtensionField<F>> ExtConst<F, EF> for EF {
74    fn cons(self) -> SymbolicExt<F, EF> {
75        SymbolicExt::Const(self)
76    }
77}
78
79pub trait ExtensionOperand<F: Field, EF: ExtensionField<F>> {
80    fn to_operand(self) -> ExtOperand<F, EF>;
81}
82
83impl<N: Field> AbstractField for SymbolicVar<N> {
84    type F = N;
85
86    fn zero() -> Self {
87        SymbolicVar::from(N::zero())
88    }
89
90    fn one() -> Self {
91        SymbolicVar::from(N::one())
92    }
93
94    fn two() -> Self {
95        SymbolicVar::from(N::two())
96    }
97
98    fn neg_one() -> Self {
99        SymbolicVar::from(N::neg_one())
100    }
101
102    fn from_f(f: Self::F) -> Self {
103        SymbolicVar::from(f)
104    }
105    fn from_bool(b: bool) -> Self {
106        SymbolicVar::from(N::from_bool(b))
107    }
108    fn from_canonical_u8(n: u8) -> Self {
109        SymbolicVar::from(N::from_canonical_u8(n))
110    }
111    fn from_canonical_u16(n: u16) -> Self {
112        SymbolicVar::from(N::from_canonical_u16(n))
113    }
114    fn from_canonical_u32(n: u32) -> Self {
115        SymbolicVar::from(N::from_canonical_u32(n))
116    }
117    fn from_canonical_u64(n: u64) -> Self {
118        SymbolicVar::from(N::from_canonical_u64(n))
119    }
120    fn from_canonical_usize(n: usize) -> Self {
121        SymbolicVar::from(N::from_canonical_usize(n))
122    }
123
124    fn from_wrapped_u32(n: u32) -> Self {
125        SymbolicVar::from(N::from_wrapped_u32(n))
126    }
127    fn from_wrapped_u64(n: u64) -> Self {
128        SymbolicVar::from(N::from_wrapped_u64(n))
129    }
130
131    /// A generator of this field's entire multiplicative group.
132    fn generator() -> Self {
133        SymbolicVar::from(N::generator())
134    }
135}
136
137impl<F: Field> AbstractField for SymbolicFelt<F> {
138    type F = F;
139
140    fn zero() -> Self {
141        SymbolicFelt::from(F::zero())
142    }
143
144    fn one() -> Self {
145        SymbolicFelt::from(F::one())
146    }
147
148    fn two() -> Self {
149        SymbolicFelt::from(F::two())
150    }
151
152    fn neg_one() -> Self {
153        SymbolicFelt::from(F::neg_one())
154    }
155
156    fn from_f(f: Self::F) -> Self {
157        SymbolicFelt::from(f)
158    }
159    fn from_bool(b: bool) -> Self {
160        SymbolicFelt::from(F::from_bool(b))
161    }
162    fn from_canonical_u8(n: u8) -> Self {
163        SymbolicFelt::from(F::from_canonical_u8(n))
164    }
165    fn from_canonical_u16(n: u16) -> Self {
166        SymbolicFelt::from(F::from_canonical_u16(n))
167    }
168    fn from_canonical_u32(n: u32) -> Self {
169        SymbolicFelt::from(F::from_canonical_u32(n))
170    }
171    fn from_canonical_u64(n: u64) -> Self {
172        SymbolicFelt::from(F::from_canonical_u64(n))
173    }
174    fn from_canonical_usize(n: usize) -> Self {
175        SymbolicFelt::from(F::from_canonical_usize(n))
176    }
177
178    fn from_wrapped_u32(n: u32) -> Self {
179        SymbolicFelt::from(F::from_wrapped_u32(n))
180    }
181    fn from_wrapped_u64(n: u64) -> Self {
182        SymbolicFelt::from(F::from_wrapped_u64(n))
183    }
184
185    /// A generator of this field's entire multiplicative group.
186    fn generator() -> Self {
187        SymbolicFelt::from(F::generator())
188    }
189}
190
191impl<F: Field, EF: ExtensionField<F>> AbstractField for SymbolicExt<F, EF> {
192    type F = EF;
193
194    fn zero() -> Self {
195        SymbolicExt::from_f(EF::zero())
196    }
197
198    fn one() -> Self {
199        SymbolicExt::from_f(EF::one())
200    }
201
202    fn two() -> Self {
203        SymbolicExt::from_f(EF::two())
204    }
205
206    fn neg_one() -> Self {
207        SymbolicExt::from_f(EF::neg_one())
208    }
209
210    fn from_f(f: Self::F) -> Self {
211        SymbolicExt::Const(f)
212    }
213    fn from_bool(b: bool) -> Self {
214        SymbolicExt::from_f(EF::from_bool(b))
215    }
216    fn from_canonical_u8(n: u8) -> Self {
217        SymbolicExt::from_f(EF::from_canonical_u8(n))
218    }
219    fn from_canonical_u16(n: u16) -> Self {
220        SymbolicExt::from_f(EF::from_canonical_u16(n))
221    }
222    fn from_canonical_u32(n: u32) -> Self {
223        SymbolicExt::from_f(EF::from_canonical_u32(n))
224    }
225    fn from_canonical_u64(n: u64) -> Self {
226        SymbolicExt::from_f(EF::from_canonical_u64(n))
227    }
228    fn from_canonical_usize(n: usize) -> Self {
229        SymbolicExt::from_f(EF::from_canonical_usize(n))
230    }
231
232    fn from_wrapped_u32(n: u32) -> Self {
233        SymbolicExt::from_f(EF::from_wrapped_u32(n))
234    }
235    fn from_wrapped_u64(n: u64) -> Self {
236        SymbolicExt::from_f(EF::from_wrapped_u64(n))
237    }
238
239    /// A generator of this field's entire multiplicative group.
240    fn generator() -> Self {
241        SymbolicExt::from_f(EF::generator())
242    }
243}
244
245// Implement all conversions from constants N, F, EF, to the corresponding symbolic types
246
247impl<N: Field> From<N> for SymbolicVar<N> {
248    fn from(n: N) -> Self {
249        SymbolicVar::Const(n)
250    }
251}
252
253impl<F: Field> From<F> for SymbolicFelt<F> {
254    fn from(f: F) -> Self {
255        SymbolicFelt::Const(f)
256    }
257}
258
259impl<F: Field, EF: ExtensionField<F>> From<F> for SymbolicExt<F, EF> {
260    fn from(f: F) -> Self {
261        f.to_operand().symbolic()
262    }
263}
264
265// Implement all conversions from Var<N>, Felt<F>, Ext<F, EF> to the corresponding symbolic types
266
267impl<N: Field> From<Var<N>> for SymbolicVar<N> {
268    fn from(v: Var<N>) -> Self {
269        SymbolicVar::Val(v)
270    }
271}
272
273impl<F: Field> From<Felt<F>> for SymbolicFelt<F> {
274    fn from(f: Felt<F>) -> Self {
275        SymbolicFelt::Val(f)
276    }
277}
278
279impl<F: Field> From<&Felt<F>> for SymbolicFelt<F> {
280    fn from(f: &Felt<F>) -> Self {
281        SymbolicFelt::Val(*f)
282    }
283}
284
285impl<F: Field, EF: ExtensionField<F>> From<Ext<F, EF>> for SymbolicExt<F, EF> {
286    fn from(e: Ext<F, EF>) -> Self {
287        e.to_operand().symbolic()
288    }
289}
290
291// Implement all operations for SymbolicVar<N>, SymbolicFelt<F>, SymbolicExt<F, EF>
292
293impl<N: Field> Add for SymbolicVar<N> {
294    type Output = Self;
295
296    fn add(self, rhs: Self) -> Self::Output {
297        match (self, rhs) {
298            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs + rhs),
299            (Self::Val(lhs), Self::Const(rhs)) => {
300                let res = unsafe { (*lhs.handle).add_const_v(lhs, rhs) };
301                Self::Val(res)
302            }
303            (Self::Const(lhs), Self::Val(rhs)) => {
304                let res = unsafe { (*rhs.handle).add_v_const(lhs, rhs) };
305                Self::Val(res)
306            }
307            (Self::Val(lhs), Self::Val(rhs)) => {
308                let res = unsafe { (*lhs.handle).add_v(lhs, rhs) };
309                Self::Val(res)
310            }
311        }
312    }
313}
314
315impl<F: Field> Add for SymbolicFelt<F> {
316    type Output = Self;
317
318    fn add(self, rhs: Self) -> Self::Output {
319        match (self, rhs) {
320            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs + rhs),
321            (Self::Val(lhs), Self::Const(rhs)) => {
322                let res = unsafe { (*lhs.handle).add_const_f(lhs, rhs) };
323                Self::Val(res)
324            }
325            (Self::Const(lhs), Self::Val(rhs)) => {
326                let res = unsafe { (*rhs.handle).add_f_const(lhs, rhs) };
327                Self::Val(res)
328            }
329            (Self::Val(lhs), Self::Val(rhs)) => {
330                let res = unsafe { (*lhs.handle).add_f(lhs, rhs) };
331                Self::Val(res)
332            }
333        }
334    }
335}
336
337impl<F: Field, EF: ExtensionField<F>, E: ExtensionOperand<F, EF>> Add<E> for SymbolicExt<F, EF> {
338    type Output = Self;
339
340    fn add(self, rhs: E) -> Self::Output {
341        let rhs = rhs.to_operand().symbolic();
342
343        match (self, rhs) {
344            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs + rhs),
345            (Self::Val(lhs), Self::Const(rhs)) => {
346                let res = unsafe { (*lhs.handle).add_const_e(lhs, rhs) };
347                Self::Val(res)
348            }
349            (Self::Const(lhs), Self::Val(rhs)) => {
350                let res = unsafe { (*rhs.handle).add_e_const(lhs, rhs) };
351                Self::Val(res)
352            }
353            (Self::Const(lhs), Self::Base(rhs)) => match rhs {
354                SymbolicFelt::Const(rhs) => Self::Const(lhs + rhs),
355                SymbolicFelt::Val(rhs) => {
356                    let ext_handle_ptr =
357                        unsafe { (*rhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
358                    let ext_handle: ManuallyDrop<_> =
359                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
360                    let res = ext_handle.add_const_e_f(lhs, rhs, ext_handle_ptr);
361                    Self::Val(res)
362                }
363            },
364            (Self::Base(lhs), Self::Const(rhs)) => match lhs {
365                SymbolicFelt::Const(lhs) => Self::Const(rhs + lhs),
366                SymbolicFelt::Val(lhs) => {
367                    let ext_handle_ptr =
368                        unsafe { (*lhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
369                    let ext_handle: ManuallyDrop<_> =
370                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
371                    let res = ext_handle.add_f_const_e(lhs, rhs, ext_handle_ptr);
372                    Self::Val(res)
373                }
374            },
375
376            (Self::Val(lhs), Self::Val(rhs)) => {
377                let res = unsafe { (*lhs.handle).add_e(lhs, rhs) };
378                Self::Val(res)
379            }
380            (Self::Base(lhs), Self::Base(rhs)) => Self::Base(lhs + rhs),
381            (Self::Base(lhs), Self::Val(rhs)) => match lhs {
382                SymbolicFelt::Const(lhs) => {
383                    let res = unsafe { (*rhs.handle).add_e_const(EF::from_base(lhs), rhs) };
384                    Self::Val(res)
385                }
386                SymbolicFelt::Val(lhs) => {
387                    let res = unsafe { (*rhs.handle).add_f_e(lhs, rhs) };
388                    Self::Val(res)
389                }
390            },
391            (Self::Val(lhs), Self::Base(rhs)) => match rhs {
392                SymbolicFelt::Const(rhs) => {
393                    let res = unsafe { (*lhs.handle).add_const_e(lhs, EF::from_base(rhs)) };
394                    Self::Val(res)
395                }
396                SymbolicFelt::Val(rhs) => {
397                    let res = unsafe { (*lhs.handle).add_e_f(lhs, rhs) };
398                    Self::Val(res)
399                }
400            },
401        }
402    }
403}
404
405impl<N: Field> Mul for SymbolicVar<N> {
406    type Output = Self;
407
408    fn mul(self, rhs: Self) -> Self::Output {
409        match (self, rhs) {
410            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs * rhs),
411            (Self::Val(lhs), Self::Const(rhs)) => {
412                let res = unsafe { (*lhs.handle).mul_const_v(lhs, rhs) };
413                Self::Val(res)
414            }
415            (Self::Const(lhs), Self::Val(rhs)) => {
416                let res = unsafe { (*rhs.handle).mul_v_const(lhs, rhs) };
417                Self::Val(res)
418            }
419            (Self::Val(lhs), Self::Val(rhs)) => {
420                let res = unsafe { (*lhs.handle).mul_v(lhs, rhs) };
421                Self::Val(res)
422            }
423        }
424    }
425}
426
427impl<F: Field> Mul for SymbolicFelt<F> {
428    type Output = Self;
429
430    fn mul(self, rhs: Self) -> Self::Output {
431        match (self, rhs) {
432            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs * rhs),
433            (Self::Val(lhs), Self::Const(rhs)) => {
434                let res = unsafe { (*lhs.handle).mul_const_f(lhs, rhs) };
435                Self::Val(res)
436            }
437            (Self::Const(lhs), Self::Val(rhs)) => {
438                let res = unsafe { (*rhs.handle).mul_f_const(lhs, rhs) };
439                Self::Val(res)
440            }
441            (Self::Val(lhs), Self::Val(rhs)) => {
442                let res = unsafe { (*lhs.handle).mul_f(lhs, rhs) };
443                Self::Val(res)
444            }
445        }
446    }
447}
448
449impl<F: Field, EF: ExtensionField<F>, E: Any> Mul<E> for SymbolicExt<F, EF> {
450    type Output = Self;
451
452    fn mul(self, rhs: E) -> Self::Output {
453        let rhs = rhs.to_operand().symbolic();
454
455        match (self, rhs) {
456            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs * rhs),
457            (Self::Val(lhs), Self::Const(rhs)) => {
458                let res = unsafe { (*lhs.handle).mul_const_e(lhs, rhs) };
459                Self::Val(res)
460            }
461            (Self::Const(lhs), Self::Val(rhs)) => {
462                let res = unsafe { (*rhs.handle).mul_e_const(lhs, rhs) };
463                Self::Val(res)
464            }
465            (Self::Const(lhs), Self::Base(rhs)) => match rhs {
466                SymbolicFelt::Const(rhs) => Self::Const(lhs * rhs),
467                SymbolicFelt::Val(rhs) => {
468                    let ext_handle_ptr =
469                        unsafe { (*rhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
470                    let ext_handle: ManuallyDrop<_> =
471                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
472                    let res = ext_handle.mul_const_e_f(lhs, rhs, ext_handle_ptr);
473                    Self::Val(res)
474                }
475            },
476            (Self::Base(lhs), Self::Const(rhs)) => match lhs {
477                SymbolicFelt::Const(lhs) => Self::Const(EF::from_base(lhs) * rhs),
478                SymbolicFelt::Val(lhs) => {
479                    let ext_handle_ptr =
480                        unsafe { (*lhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
481                    let ext_handle: ManuallyDrop<_> =
482                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
483                    let res = ext_handle.mul_f_const_e(lhs, rhs, ext_handle_ptr);
484                    Self::Val(res)
485                }
486            },
487
488            (Self::Val(lhs), Self::Val(rhs)) => {
489                let res = unsafe { (*lhs.handle).mul_e(lhs, rhs) };
490                Self::Val(res)
491            }
492            (Self::Base(lhs), Self::Base(rhs)) => Self::Base(lhs * rhs),
493            (Self::Base(lhs), Self::Val(rhs)) => match lhs {
494                SymbolicFelt::Const(lhs) => {
495                    let res = unsafe { (*rhs.handle).mul_e_const(EF::from_base(lhs), rhs) };
496                    Self::Val(res)
497                }
498                SymbolicFelt::Val(lhs) => {
499                    let res = unsafe { (*rhs.handle).mul_f_e(lhs, rhs) };
500                    Self::Val(res)
501                }
502            },
503            (Self::Val(lhs), Self::Base(rhs)) => match rhs {
504                SymbolicFelt::Const(rhs) => {
505                    let res = unsafe { (*lhs.handle).mul_const_e(lhs, EF::from_base(rhs)) };
506                    Self::Val(res)
507                }
508                SymbolicFelt::Val(rhs) => {
509                    let res = unsafe { (*lhs.handle).mul_e_f(lhs, rhs) };
510                    Self::Val(res)
511                }
512            },
513        }
514    }
515}
516
517impl<N: Field> Sub for SymbolicVar<N> {
518    type Output = Self;
519
520    fn sub(self, rhs: Self) -> Self::Output {
521        match (self, rhs) {
522            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs - rhs),
523            (Self::Val(lhs), Self::Const(rhs)) => {
524                let res = unsafe { (*lhs.handle).sub_v_const(lhs, rhs) };
525                Self::Val(res)
526            }
527            (Self::Const(lhs), Self::Val(rhs)) => {
528                let res = unsafe { (*rhs.handle).sub_const_v(lhs, rhs) };
529                Self::Val(res)
530            }
531            (Self::Val(lhs), Self::Val(rhs)) => {
532                let res = unsafe { (*lhs.handle).sub_v(lhs, rhs) };
533                Self::Val(res)
534            }
535        }
536    }
537}
538
539impl<F: Field> Sub for SymbolicFelt<F> {
540    type Output = Self;
541
542    fn sub(self, rhs: Self) -> Self::Output {
543        match (self, rhs) {
544            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs - rhs),
545            (Self::Val(lhs), Self::Const(rhs)) => {
546                let res = unsafe { (*lhs.handle).sub_f_const(lhs, rhs) };
547                Self::Val(res)
548            }
549            (Self::Const(lhs), Self::Val(rhs)) => {
550                let res = unsafe { (*rhs.handle).sub_const_f(lhs, rhs) };
551                Self::Val(res)
552            }
553            (Self::Val(lhs), Self::Val(rhs)) => {
554                let res = unsafe { (*lhs.handle).sub_f(lhs, rhs) };
555                Self::Val(res)
556            }
557        }
558    }
559}
560
561impl<F: Field, EF: ExtensionField<F>, E: Any> Sub<E> for SymbolicExt<F, EF> {
562    type Output = Self;
563
564    fn sub(self, rhs: E) -> Self::Output {
565        let rhs = rhs.to_operand().symbolic();
566
567        match (self, rhs) {
568            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs - rhs),
569            (Self::Val(lhs), Self::Const(rhs)) => {
570                let res = unsafe { (*lhs.handle).sub_const_e(lhs, rhs) };
571                Self::Val(res)
572            }
573            (Self::Const(lhs), Self::Val(rhs)) => {
574                let res = unsafe { (*rhs.handle).sub_e_const(lhs, rhs) };
575                Self::Val(res)
576            }
577            (Self::Const(lhs), Self::Base(rhs)) => match rhs {
578                SymbolicFelt::Const(rhs) => Self::Const(lhs - rhs),
579                SymbolicFelt::Val(rhs) => {
580                    let ext_handle_ptr =
581                        unsafe { (*rhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
582                    let ext_handle: ManuallyDrop<_> =
583                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
584                    let res = ext_handle.sub_const_e_f(lhs, rhs, ext_handle_ptr);
585                    Self::Val(res)
586                }
587            },
588            (Self::Base(lhs), Self::Const(rhs)) => match lhs {
589                SymbolicFelt::Const(lhs) => Self::Const(EF::from_base(lhs) - rhs),
590                SymbolicFelt::Val(lhs) => {
591                    let ext_handle_ptr =
592                        unsafe { (*lhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
593                    let ext_handle: ManuallyDrop<_> =
594                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
595                    let res = ext_handle.sub_f_const_e(lhs, rhs, ext_handle_ptr);
596                    Self::Val(res)
597                }
598            },
599
600            (Self::Val(lhs), Self::Val(rhs)) => {
601                let res = unsafe { (*lhs.handle).sub_e(lhs, rhs) };
602                Self::Val(res)
603            }
604            (Self::Base(lhs), Self::Base(rhs)) => Self::Base(lhs - rhs),
605            (Self::Base(lhs), Self::Val(rhs)) => match lhs {
606                SymbolicFelt::Const(lhs) => {
607                    let res = unsafe { (*rhs.handle).sub_e_const(EF::from_base(lhs), rhs) };
608                    Self::Val(res)
609                }
610                SymbolicFelt::Val(lhs) => {
611                    let res = unsafe { (*rhs.handle).sub_f_e(lhs, rhs) };
612                    Self::Val(res)
613                }
614            },
615            (Self::Val(lhs), Self::Base(rhs)) => match rhs {
616                SymbolicFelt::Const(rhs) => {
617                    let res = unsafe { (*lhs.handle).sub_const_e(lhs, EF::from_base(rhs)) };
618                    Self::Val(res)
619                }
620                SymbolicFelt::Val(rhs) => {
621                    let res = unsafe { (*lhs.handle).sub_e_f(lhs, rhs) };
622                    Self::Val(res)
623                }
624            },
625        }
626    }
627}
628
629impl<F: Field> Div for SymbolicFelt<F> {
630    type Output = Self;
631
632    fn div(self, rhs: Self) -> Self::Output {
633        match (self, rhs) {
634            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs / rhs),
635            (Self::Val(lhs), Self::Const(rhs)) => {
636                let res = unsafe { (*lhs.handle).div_f_const(lhs, rhs) };
637                Self::Val(res)
638            }
639            (Self::Const(lhs), Self::Val(rhs)) => {
640                let res = unsafe { (*rhs.handle).div_const_f(lhs, rhs) };
641                Self::Val(res)
642            }
643            (Self::Val(lhs), Self::Val(rhs)) => {
644                let res = unsafe { (*lhs.handle).div_f(lhs, rhs) };
645                Self::Val(res)
646            }
647        }
648    }
649}
650
651impl<F: Field, EF: ExtensionField<F>, E: Any> Div<E> for SymbolicExt<F, EF> {
652    type Output = Self;
653
654    fn div(self, rhs: E) -> Self::Output {
655        let rhs = rhs.to_operand().symbolic();
656
657        match (self, rhs) {
658            (Self::Const(lhs), Self::Const(rhs)) => Self::Const(lhs / rhs),
659            (Self::Val(lhs), Self::Const(rhs)) => {
660                let res = unsafe { (*lhs.handle).div_const_e(lhs, rhs) };
661                Self::Val(res)
662            }
663            (Self::Const(lhs), Self::Val(rhs)) => {
664                let res = unsafe { (*rhs.handle).div_e_const(lhs, rhs) };
665                Self::Val(res)
666            }
667            (Self::Const(lhs), Self::Base(rhs)) => match rhs {
668                SymbolicFelt::Const(rhs) => Self::Const(lhs / EF::from_base(rhs)),
669                SymbolicFelt::Val(rhs) => {
670                    let ext_handle_ptr =
671                        unsafe { (*rhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
672                    let ext_handle: ManuallyDrop<_> =
673                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
674                    let rhs = rhs.inverse();
675                    if let SymbolicFelt::Val(rhs) = rhs {
676                        let res = ext_handle.mul_const_e_f(lhs, rhs, ext_handle_ptr);
677                        Self::Val(res)
678                    } else {
679                        unreachable!()
680                    }
681                }
682            },
683            (Self::Base(lhs), Self::Const(rhs)) => match lhs {
684                SymbolicFelt::Const(lhs) => Self::Const(EF::from_base(lhs) / rhs),
685                SymbolicFelt::Val(lhs) => {
686                    let ext_handle_ptr =
687                        unsafe { (*lhs.handle).ext_handle_ptr as *mut ExtHandle<F, EF> };
688                    let ext_handle: ManuallyDrop<_> =
689                        unsafe { ManuallyDrop::new(Box::from_raw(ext_handle_ptr)) };
690                    let res = ext_handle.div_f_const_e(lhs, rhs, ext_handle_ptr);
691                    Self::Val(res)
692                }
693            },
694
695            (Self::Val(lhs), Self::Val(rhs)) => {
696                let res = unsafe { (*lhs.handle).div_e(lhs, rhs) };
697                Self::Val(res)
698            }
699            (Self::Base(lhs), Self::Base(rhs)) => Self::Base(lhs / rhs),
700            (Self::Base(lhs), Self::Val(rhs)) => match lhs {
701                SymbolicFelt::Const(lhs) => {
702                    let res = unsafe { (*rhs.handle).div_e_const(EF::from_base(lhs), rhs) };
703                    Self::Val(res)
704                }
705                SymbolicFelt::Val(lhs) => {
706                    let res = unsafe { (*rhs.handle).div_f_e(lhs, rhs) };
707                    Self::Val(res)
708                }
709            },
710            (Self::Val(lhs), Self::Base(rhs)) => match rhs {
711                SymbolicFelt::Const(rhs) => {
712                    let res = unsafe { (*lhs.handle).div_const_e(lhs, EF::from_base(rhs)) };
713                    Self::Val(res)
714                }
715                SymbolicFelt::Val(rhs) => {
716                    let res = unsafe { (*lhs.handle).div_e_f(lhs, rhs) };
717                    Self::Val(res)
718                }
719            },
720        }
721    }
722}
723
724impl<N: Field> Neg for SymbolicVar<N> {
725    type Output = Self;
726
727    fn neg(self) -> Self::Output {
728        match self {
729            SymbolicVar::Const(n) => SymbolicVar::Const(-n),
730            SymbolicVar::Val(n) => {
731                let res = unsafe { (*n.handle).neg_v(n) };
732                SymbolicVar::Val(res)
733            }
734        }
735    }
736}
737
738impl<F: Field> Neg for SymbolicFelt<F> {
739    type Output = Self;
740
741    fn neg(self) -> Self::Output {
742        match self {
743            SymbolicFelt::Const(f) => SymbolicFelt::Const(-f),
744            SymbolicFelt::Val(f) => {
745                let res = unsafe { (*f.handle).neg_f(f) };
746                SymbolicFelt::Val(res)
747            }
748        }
749    }
750}
751
752impl<F: Field, EF: ExtensionField<F>> Neg for SymbolicExt<F, EF> {
753    type Output = Self;
754
755    fn neg(self) -> Self::Output {
756        match self {
757            SymbolicExt::Const(ef) => SymbolicExt::Const(-ef),
758            SymbolicExt::Base(f) => SymbolicExt::Base(-f),
759            SymbolicExt::Val(ef) => {
760                let res = unsafe { (*ef.handle).neg_e(ef) };
761                SymbolicExt::Val(res)
762            }
763        }
764    }
765}
766
767// Implement all operations between N, F, EF, and SymbolicVar<N>, SymbolicFelt<F>, SymbolicExt<F,
768// EF>
769
770impl<N: Field> Add<N> for SymbolicVar<N> {
771    type Output = Self;
772
773    fn add(self, rhs: N) -> Self::Output {
774        self + SymbolicVar::from(rhs)
775    }
776}
777
778impl<F: Field> Add<F> for SymbolicFelt<F> {
779    type Output = Self;
780
781    fn add(self, rhs: F) -> Self::Output {
782        self + SymbolicFelt::from(rhs)
783    }
784}
785
786impl<N: Field> Mul<N> for SymbolicVar<N> {
787    type Output = Self;
788
789    fn mul(self, rhs: N) -> Self::Output {
790        self * SymbolicVar::from(rhs)
791    }
792}
793
794impl<F: Field> Mul<F> for SymbolicFelt<F> {
795    type Output = Self;
796
797    fn mul(self, rhs: F) -> Self::Output {
798        self * SymbolicFelt::from(rhs)
799    }
800}
801
802impl<N: Field> Sub<N> for SymbolicVar<N> {
803    type Output = Self;
804
805    fn sub(self, rhs: N) -> Self::Output {
806        self - SymbolicVar::from(rhs)
807    }
808}
809
810impl<F: Field> Sub<F> for SymbolicFelt<F> {
811    type Output = Self;
812
813    fn sub(self, rhs: F) -> Self::Output {
814        self - SymbolicFelt::from(rhs)
815    }
816}
817
818// Implement all operations between SymbolicVar<N>, SymbolicFelt<F>, SymbolicExt<F, EF>, and Var<N>,
819//  Felt<F>, Ext<F, EF>.
820
821impl<N: Field> Add<Var<N>> for SymbolicVar<N> {
822    type Output = SymbolicVar<N>;
823
824    fn add(self, rhs: Var<N>) -> Self::Output {
825        self + SymbolicVar::from(rhs)
826    }
827}
828
829impl<F: Field> Add<Felt<F>> for SymbolicFelt<F> {
830    type Output = SymbolicFelt<F>;
831
832    fn add(self, rhs: Felt<F>) -> Self::Output {
833        self + SymbolicFelt::from(rhs)
834    }
835}
836
837impl<N: Field> Mul<Var<N>> for SymbolicVar<N> {
838    type Output = SymbolicVar<N>;
839
840    fn mul(self, rhs: Var<N>) -> Self::Output {
841        self * SymbolicVar::from(rhs)
842    }
843}
844
845impl<F: Field> Mul<Felt<F>> for SymbolicFelt<F> {
846    type Output = SymbolicFelt<F>;
847
848    fn mul(self, rhs: Felt<F>) -> Self::Output {
849        self * SymbolicFelt::from(rhs)
850    }
851}
852
853impl<N: Field> Sub<Var<N>> for SymbolicVar<N> {
854    type Output = SymbolicVar<N>;
855
856    fn sub(self, rhs: Var<N>) -> Self::Output {
857        self - SymbolicVar::from(rhs)
858    }
859}
860
861impl<F: Field> Sub<Felt<F>> for SymbolicFelt<F> {
862    type Output = SymbolicFelt<F>;
863
864    fn sub(self, rhs: Felt<F>) -> Self::Output {
865        self - SymbolicFelt::from(rhs)
866    }
867}
868
869impl<F: Field> Div<SymbolicFelt<F>> for Felt<F> {
870    type Output = SymbolicFelt<F>;
871
872    fn div(self, rhs: SymbolicFelt<F>) -> Self::Output {
873        SymbolicFelt::<F>::from(self) / rhs
874    }
875}
876
877// Implement operations between constants N, F, EF, and Var<N>, Felt<F>, Ext<F, EF>.
878
879impl<N: Field> Add for Var<N> {
880    type Output = SymbolicVar<N>;
881
882    fn add(self, rhs: Self) -> Self::Output {
883        SymbolicVar::<N>::from(self) + rhs
884    }
885}
886
887impl<N: Field> Add<N> for Var<N> {
888    type Output = SymbolicVar<N>;
889
890    fn add(self, rhs: N) -> Self::Output {
891        SymbolicVar::from(self) + rhs
892    }
893}
894
895impl<F: Field> Add for Felt<F> {
896    type Output = SymbolicFelt<F>;
897
898    fn add(self, rhs: Self) -> Self::Output {
899        SymbolicFelt::<F>::from(self) + rhs
900    }
901}
902
903impl<F: Field> Add<F> for Felt<F> {
904    type Output = SymbolicFelt<F>;
905
906    fn add(self, rhs: F) -> Self::Output {
907        SymbolicFelt::from(self) + rhs
908    }
909}
910
911impl<N: Field> Mul for Var<N> {
912    type Output = SymbolicVar<N>;
913
914    fn mul(self, rhs: Self) -> Self::Output {
915        SymbolicVar::<N>::from(self) * rhs
916    }
917}
918
919impl<N: Field> Mul<N> for Var<N> {
920    type Output = SymbolicVar<N>;
921
922    fn mul(self, rhs: N) -> Self::Output {
923        SymbolicVar::from(self) * rhs
924    }
925}
926
927impl<F: Field> Mul for Felt<F> {
928    type Output = SymbolicFelt<F>;
929
930    fn mul(self, rhs: Self) -> Self::Output {
931        SymbolicFelt::<F>::from(self) * rhs
932    }
933}
934
935impl<F: Field> Mul<F> for Felt<F> {
936    type Output = SymbolicFelt<F>;
937
938    fn mul(self, rhs: F) -> Self::Output {
939        SymbolicFelt::from(self) * rhs
940    }
941}
942
943impl<N: Field> Sub for Var<N> {
944    type Output = SymbolicVar<N>;
945
946    fn sub(self, rhs: Self) -> Self::Output {
947        SymbolicVar::<N>::from(self) - rhs
948    }
949}
950
951impl<N: Field> Sub<N> for Var<N> {
952    type Output = SymbolicVar<N>;
953
954    fn sub(self, rhs: N) -> Self::Output {
955        SymbolicVar::from(self) - rhs
956    }
957}
958
959impl<F: Field> Sub for Felt<F> {
960    type Output = SymbolicFelt<F>;
961
962    fn sub(self, rhs: Self) -> Self::Output {
963        SymbolicFelt::<F>::from(self) - rhs
964    }
965}
966
967impl<F: Field> Sub<F> for Felt<F> {
968    type Output = SymbolicFelt<F>;
969
970    fn sub(self, rhs: F) -> Self::Output {
971        SymbolicFelt::from(self) - rhs
972    }
973}
974
975impl<F: Field, EF: ExtensionField<F>, E: Any> Add<E> for Ext<F, EF> {
976    type Output = SymbolicExt<F, EF>;
977
978    fn add(self, rhs: E) -> Self::Output {
979        let rhs: ExtOperand<F, EF> = rhs.to_operand();
980        let self_sym = self.to_operand().symbolic();
981        self_sym + rhs
982    }
983}
984
985impl<F: Field, EF: ExtensionField<F>, E: Any> Mul<E> for Ext<F, EF> {
986    type Output = SymbolicExt<F, EF>;
987
988    fn mul(self, rhs: E) -> Self::Output {
989        let self_sym = self.to_operand().symbolic();
990        self_sym * rhs
991    }
992}
993
994impl<F: Field, EF: ExtensionField<F>, E: Any> Sub<E> for Ext<F, EF> {
995    type Output = SymbolicExt<F, EF>;
996
997    fn sub(self, rhs: E) -> Self::Output {
998        let self_sym = self.to_operand().symbolic();
999        self_sym - rhs
1000    }
1001}
1002
1003impl<F: Field, EF: ExtensionField<F>, E: Any> Div<E> for Ext<F, EF> {
1004    type Output = SymbolicExt<F, EF>;
1005
1006    fn div(self, rhs: E) -> Self::Output {
1007        let self_sym = self.to_operand().symbolic();
1008        self_sym / rhs
1009    }
1010}
1011
1012impl<F: Field, EF: ExtensionField<F>> Add<SymbolicExt<F, EF>> for Felt<F> {
1013    type Output = SymbolicExt<F, EF>;
1014
1015    fn add(self, rhs: SymbolicExt<F, EF>) -> Self::Output {
1016        let self_sym = self.to_operand().symbolic();
1017        self_sym + rhs
1018    }
1019}
1020
1021impl<F: Field, EF: ExtensionField<F>> Mul<SymbolicExt<F, EF>> for Felt<F> {
1022    type Output = SymbolicExt<F, EF>;
1023
1024    fn mul(self, rhs: SymbolicExt<F, EF>) -> Self::Output {
1025        let self_sym = self.to_operand().symbolic();
1026        self_sym * rhs
1027    }
1028}
1029
1030impl<F: Field, EF: ExtensionField<F>> Sub<SymbolicExt<F, EF>> for Felt<F> {
1031    type Output = SymbolicExt<F, EF>;
1032
1033    fn sub(self, rhs: SymbolicExt<F, EF>) -> Self::Output {
1034        let self_sym = self.to_operand().symbolic();
1035        self_sym - rhs
1036    }
1037}
1038
1039impl<F: Field, EF: ExtensionField<F>> Div<SymbolicExt<F, EF>> for Felt<F> {
1040    type Output = SymbolicExt<F, EF>;
1041
1042    fn div(self, rhs: SymbolicExt<F, EF>) -> Self::Output {
1043        let self_sym = self.to_operand().symbolic();
1044        self_sym / rhs
1045    }
1046}
1047
1048impl<F: Field> Div for Felt<F> {
1049    type Output = SymbolicFelt<F>;
1050
1051    fn div(self, rhs: Self) -> Self::Output {
1052        SymbolicFelt::<F>::from(self) / rhs
1053    }
1054}
1055
1056impl<F: Field> Div<F> for Felt<F> {
1057    type Output = SymbolicFelt<F>;
1058
1059    fn div(self, rhs: F) -> Self::Output {
1060        SymbolicFelt::from(self) / rhs
1061    }
1062}
1063
1064impl<F: Field> Div<Felt<F>> for SymbolicFelt<F> {
1065    type Output = SymbolicFelt<F>;
1066
1067    fn div(self, rhs: Felt<F>) -> Self::Output {
1068        self / SymbolicFelt::from(rhs)
1069    }
1070}
1071
1072impl<F: Field> Div<F> for SymbolicFelt<F> {
1073    type Output = SymbolicFelt<F>;
1074
1075    fn div(self, rhs: F) -> Self::Output {
1076        self / SymbolicFelt::from(rhs)
1077    }
1078}
1079
1080impl<N: Field> Sub<SymbolicVar<N>> for Var<N> {
1081    type Output = SymbolicVar<N>;
1082
1083    fn sub(self, rhs: SymbolicVar<N>) -> Self::Output {
1084        SymbolicVar::<N>::from(self) - rhs
1085    }
1086}
1087
1088impl<N: Field> Add<SymbolicVar<N>> for Var<N> {
1089    type Output = SymbolicVar<N>;
1090
1091    fn add(self, rhs: SymbolicVar<N>) -> Self::Output {
1092        SymbolicVar::<N>::from(self) + rhs
1093    }
1094}
1095
1096impl<N: Field> Product for SymbolicVar<N> {
1097    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
1098        iter.fold(SymbolicVar::one(), |acc, x| acc * x)
1099    }
1100}
1101
1102impl<N: Field> Sum for SymbolicVar<N> {
1103    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1104        iter.fold(SymbolicVar::zero(), |acc, x| acc + x)
1105    }
1106}
1107
1108impl<N: Field> AddAssign for SymbolicVar<N> {
1109    fn add_assign(&mut self, rhs: Self) {
1110        *self = *self + rhs;
1111    }
1112}
1113
1114impl<N: Field> SubAssign for SymbolicVar<N> {
1115    fn sub_assign(&mut self, rhs: Self) {
1116        *self = *self - rhs;
1117    }
1118}
1119
1120impl<N: Field> MulAssign for SymbolicVar<N> {
1121    fn mul_assign(&mut self, rhs: Self) {
1122        *self = *self * rhs;
1123    }
1124}
1125
1126impl<N: Field> Default for SymbolicVar<N> {
1127    fn default() -> Self {
1128        SymbolicVar::zero()
1129    }
1130}
1131
1132impl<F: Field> Sum for SymbolicFelt<F> {
1133    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1134        iter.fold(SymbolicFelt::zero(), |acc, x| acc + x)
1135    }
1136}
1137
1138impl<F: Field> Product for SymbolicFelt<F> {
1139    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
1140        iter.fold(SymbolicFelt::one(), |acc, x| acc * x)
1141    }
1142}
1143
1144impl<F: Field> AddAssign for SymbolicFelt<F> {
1145    fn add_assign(&mut self, rhs: Self) {
1146        *self = *self + rhs;
1147    }
1148}
1149
1150impl<F: Field> SubAssign for SymbolicFelt<F> {
1151    fn sub_assign(&mut self, rhs: Self) {
1152        *self = *self - rhs;
1153    }
1154}
1155
1156impl<F: Field> MulAssign for SymbolicFelt<F> {
1157    fn mul_assign(&mut self, rhs: Self) {
1158        *self = *self * rhs;
1159    }
1160}
1161
1162impl<F: Field> Default for SymbolicFelt<F> {
1163    fn default() -> Self {
1164        SymbolicFelt::zero()
1165    }
1166}
1167
1168impl<F: Field, EF: ExtensionField<F>> Sum for SymbolicExt<F, EF> {
1169    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1170        iter.fold(SymbolicExt::zero(), |acc, x| acc + x)
1171    }
1172}
1173
1174impl<F: Field, EF: ExtensionField<F>> Product for SymbolicExt<F, EF> {
1175    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
1176        iter.fold(SymbolicExt::one(), |acc, x| acc * x)
1177    }
1178}
1179
1180impl<F: Field, EF: ExtensionField<F>> Default for SymbolicExt<F, EF> {
1181    fn default() -> Self {
1182        SymbolicExt::zero()
1183    }
1184}
1185
1186impl<F: Field, EF: ExtensionField<F>, E: Any> AddAssign<E> for SymbolicExt<F, EF> {
1187    fn add_assign(&mut self, rhs: E) {
1188        *self = *self + rhs;
1189    }
1190}
1191
1192impl<F: Field, EF: ExtensionField<F>, E: Any> SubAssign<E> for SymbolicExt<F, EF> {
1193    fn sub_assign(&mut self, rhs: E) {
1194        *self = *self - rhs;
1195    }
1196}
1197
1198impl<F: Field, EF: ExtensionField<F>, E: Any> MulAssign<E> for SymbolicExt<F, EF> {
1199    fn mul_assign(&mut self, rhs: E) {
1200        *self = *self * rhs;
1201    }
1202}
1203
1204impl<F: Field, EF: ExtensionField<F>, E: Any> DivAssign<E> for SymbolicExt<F, EF> {
1205    fn div_assign(&mut self, rhs: E) {
1206        *self = *self / rhs;
1207    }
1208}
1209
1210impl<F: Field, EF: ExtensionField<F>> Mul<SymbolicExt<F, EF>> for SymbolicFelt<F> {
1211    type Output = SymbolicExt<F, EF>;
1212
1213    fn mul(self, rhs: SymbolicExt<F, EF>) -> Self::Output {
1214        rhs * self
1215    }
1216}
1217
1218impl<F: Field, EF: ExtensionField<F>, E: Any> ExtensionOperand<F, EF> for E {
1219    fn to_operand(self) -> ExtOperand<F, EF> {
1220        match self.type_id() {
1221            ty if ty == TypeId::of::<F>() => {
1222                // *Safety*: We know that E is a F and we can transmute it to F which implements
1223                // the Copy trait.
1224                let value = unsafe { mem::transmute_copy::<E, F>(&self) };
1225                ExtOperand::<F, EF>::Base(value)
1226            }
1227            ty if ty == TypeId::of::<EF>() => {
1228                // *Safety*: We know that E is a EF and we can transmute it to EF which implements
1229                // the Copy trait.
1230                let value = unsafe { mem::transmute_copy::<E, EF>(&self) };
1231                ExtOperand::<F, EF>::Const(value)
1232            }
1233            ty if ty == TypeId::of::<Felt<F>>() => {
1234                // *Safety*: We know that E is a Felt<F> and we can transmute it to Felt<F> which
1235                // implements the Copy trait.
1236                let value = unsafe { mem::transmute_copy::<E, Felt<F>>(&self) };
1237                ExtOperand::<F, EF>::Felt(value)
1238            }
1239            ty if ty == TypeId::of::<Ext<F, EF>>() => {
1240                // *Safety*: We know that E is a Ext<F, EF> and we can transmute it to Ext<F, EF>
1241                // which implements the Copy trait.
1242                let value = unsafe { mem::transmute_copy::<E, Ext<F, EF>>(&self) };
1243                ExtOperand::<F, EF>::Ext(value)
1244            }
1245            ty if ty == TypeId::of::<SymbolicFelt<F>>() => {
1246                // *Safety*: We know that E is a Symbolic Felt<F> and we can transmute it to
1247                // SymbolicFelt<F> but we need to clone the pointer.
1248                let value_ref = unsafe { mem::transmute::<&E, &SymbolicFelt<F>>(&self) };
1249                let value = *value_ref;
1250                ExtOperand::<F, EF>::SymFelt(value)
1251            }
1252            ty if ty == TypeId::of::<SymbolicExt<F, EF>>() => {
1253                // *Safety*: We know that E is a SymbolicExt<F, EF> and we can transmute it to
1254                // SymbolicExt<F, EF> but we need to clone the pointer.
1255                let value_ref = unsafe { mem::transmute::<&E, &SymbolicExt<F, EF>>(&self) };
1256                let value = *value_ref;
1257                ExtOperand::<F, EF>::Sym(value)
1258            }
1259            ty if ty == TypeId::of::<ExtOperand<F, EF>>() => {
1260                let value_ref = unsafe { mem::transmute::<&E, &ExtOperand<F, EF>>(&self) };
1261                value_ref.clone()
1262            }
1263            _ => unimplemented!("unsupported type {:?}", self.type_id()),
1264        }
1265    }
1266}
1267
1268impl<F: Field> Add<SymbolicFelt<F>> for Felt<F> {
1269    type Output = SymbolicFelt<F>;
1270
1271    fn add(self, rhs: SymbolicFelt<F>) -> Self::Output {
1272        SymbolicFelt::<F>::from(self) + rhs
1273    }
1274}
1275
1276impl<F: Field, EF: ExtensionField<F>> From<Felt<F>> for SymbolicExt<F, EF> {
1277    fn from(value: Felt<F>) -> Self {
1278        value.to_operand().symbolic()
1279    }
1280}
1281
1282impl<F: Field, EF: ExtensionField<F>> Neg for Ext<F, EF> {
1283    type Output = SymbolicExt<F, EF>;
1284    fn neg(self) -> Self::Output {
1285        -SymbolicExt::from(self)
1286    }
1287}
1288
1289impl<F: Field> Neg for Felt<F> {
1290    type Output = SymbolicFelt<F>;
1291
1292    fn neg(self) -> Self::Output {
1293        -SymbolicFelt::from(self)
1294    }
1295}
1296
1297impl<N: Field> Neg for Var<N> {
1298    type Output = SymbolicVar<N>;
1299
1300    fn neg(self) -> Self::Output {
1301        -SymbolicVar::from(self)
1302    }
1303}
1304
1305impl<F: Field> MulAssign<Felt<F>> for SymbolicFelt<F> {
1306    fn mul_assign(&mut self, rhs: Felt<F>) {
1307        *self = *self * Self::from(rhs);
1308    }
1309}
1310
1311impl<F: Field> Mul<SymbolicFelt<F>> for Felt<F> {
1312    type Output = SymbolicFelt<F>;
1313
1314    fn mul(self, rhs: SymbolicFelt<F>) -> Self::Output {
1315        SymbolicFelt::<F>::from(self) * rhs
1316    }
1317}
1318
1319impl<N: Field> Mul<SymbolicVar<N>> for Var<N> {
1320    type Output = SymbolicVar<N>;
1321
1322    fn mul(self, rhs: SymbolicVar<N>) -> Self::Output {
1323        SymbolicVar::<N>::from(self) * rhs
1324    }
1325}