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