algebraeon_rings/structure/
ergonomic.rs

1use std::{
2    borrow::Borrow,
3    ops::{Add, Div, Mul, Neg, Sub},
4};
5
6use super::*;
7use algebraeon_sets::structure::*;
8
9use algebraeon_nzq::*;
10
11pub trait IntoErgonomicSignature: SetSignature {
12    fn into_ergonomic(&self, elem: Self::Set) -> StructuredElement<Self> {
13        StructuredElement::new(self.clone(), elem)
14    }
15}
16impl<S: SetSignature> IntoErgonomicSignature for S {}
17
18pub trait IntoErgonomic: MetaType {
19    fn into_ergonomic(self) -> StructuredElement<Self::Signature> {
20        StructuredElement::new(Self::structure(), self)
21    }
22}
23impl<T: MetaType> IntoErgonomic for T {}
24
25fn common_structure<S: Signature>(structure1: impl Borrow<S>, structure2: impl Borrow<S>) -> S {
26    if structure1.borrow() == structure2.borrow() {
27        structure1.borrow().clone()
28    } else {
29        panic!("Unequal ring structures")
30    }
31}
32
33#[derive(Debug, Clone)]
34pub struct StructuredElement<S: SetSignature> {
35    structure: S,
36    elem: S::Set,
37}
38
39impl<S: SetSignature> StructuredElement<S> {
40    pub fn new(structure: S, elem: S::Set) -> Self {
41        Self { structure, elem }
42    }
43
44    pub fn structure(&self) -> S {
45        self.structure.clone()
46    }
47
48    pub fn ref_set(&self) -> &S::Set {
49        &self.elem
50    }
51
52    pub fn into_verbose(self) -> S::Set {
53        self.elem
54    }
55}
56
57impl<S: SetSignature> std::fmt::Display for StructuredElement<S>
58where
59    S::Set: std::fmt::Display,
60{
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        std::fmt::Display::fmt(&self.elem, f)
63    }
64}
65
66impl<RS: RingEqSignature> PartialEq for StructuredElement<RS> {
67    fn eq(&self, other: &Self) -> bool {
68        let structure = common_structure::<RS>(self.structure(), other.structure());
69        structure.equal(self.ref_set(), other.ref_set())
70    }
71}
72
73impl<RS: RingEqSignature> Eq for StructuredElement<RS> {}
74
75impl<RS: RingSignature> Neg for &StructuredElement<RS> {
76    type Output = StructuredElement<RS>;
77
78    fn neg(self) -> Self::Output {
79        StructuredElement::new(
80            self.structure().clone(),
81            self.structure().neg(self.ref_set()),
82        )
83    }
84}
85
86impl<RS: RingSignature> Neg for StructuredElement<RS> {
87    type Output = StructuredElement<RS>;
88
89    fn neg(self) -> Self::Output {
90        (&self).neg()
91    }
92}
93
94impl<RS: RingSignature> Add<&StructuredElement<RS>> for &StructuredElement<RS> {
95    type Output = StructuredElement<RS>;
96
97    fn add(self, rhs: &StructuredElement<RS>) -> Self::Output {
98        StructuredElement::new(
99            self.structure().clone(),
100            self.structure().add(self.ref_set(), rhs.ref_set()),
101        )
102    }
103}
104
105impl<RS: RingSignature> Add<StructuredElement<RS>> for &StructuredElement<RS> {
106    type Output = StructuredElement<RS>;
107
108    fn add(self, rhs: StructuredElement<RS>) -> Self::Output {
109        self + &rhs
110    }
111}
112
113impl<RS: RingSignature> Add<&StructuredElement<RS>> for StructuredElement<RS> {
114    type Output = StructuredElement<RS>;
115
116    fn add(self, rhs: &StructuredElement<RS>) -> Self::Output {
117        &self + rhs
118    }
119}
120
121impl<RS: RingSignature> Add<StructuredElement<RS>> for StructuredElement<RS> {
122    type Output = StructuredElement<RS>;
123
124    fn add(self, rhs: StructuredElement<RS>) -> Self::Output {
125        &self + &rhs
126    }
127}
128
129impl<RS: RingSignature> Sub<&StructuredElement<RS>> for &StructuredElement<RS> {
130    type Output = StructuredElement<RS>;
131
132    fn sub(self, rhs: &StructuredElement<RS>) -> Self::Output {
133        StructuredElement::new(
134            self.structure().clone(),
135            self.structure()
136                .add(self.ref_set(), &self.structure().neg(rhs.ref_set())),
137        )
138    }
139}
140
141impl<RS: RingSignature> Sub<StructuredElement<RS>> for &StructuredElement<RS> {
142    type Output = StructuredElement<RS>;
143
144    fn sub(self, rhs: StructuredElement<RS>) -> Self::Output {
145        self - &rhs
146    }
147}
148
149impl<RS: RingSignature> Sub<&StructuredElement<RS>> for StructuredElement<RS> {
150    type Output = StructuredElement<RS>;
151
152    fn sub(self, rhs: &StructuredElement<RS>) -> Self::Output {
153        &self - rhs
154    }
155}
156
157impl<RS: RingSignature> Sub<StructuredElement<RS>> for StructuredElement<RS> {
158    type Output = StructuredElement<RS>;
159
160    fn sub(self, rhs: StructuredElement<RS>) -> Self::Output {
161        &self - &rhs
162    }
163}
164
165impl<RS: RingSignature> Mul<&StructuredElement<RS>> for &StructuredElement<RS> {
166    type Output = StructuredElement<RS>;
167
168    fn mul(self, rhs: &StructuredElement<RS>) -> Self::Output {
169        StructuredElement::new(
170            self.structure().clone(),
171            self.structure().mul(self.ref_set(), rhs.ref_set()),
172        )
173    }
174}
175
176impl<RS: RingSignature> Mul<StructuredElement<RS>> for &StructuredElement<RS> {
177    type Output = StructuredElement<RS>;
178
179    fn mul(self, rhs: StructuredElement<RS>) -> Self::Output {
180        self * &rhs
181    }
182}
183
184impl<RS: RingSignature> Mul<&StructuredElement<RS>> for StructuredElement<RS> {
185    type Output = StructuredElement<RS>;
186
187    fn mul(self, rhs: &StructuredElement<RS>) -> Self::Output {
188        &self * rhs
189    }
190}
191
192impl<RS: RingSignature> Mul<StructuredElement<RS>> for StructuredElement<RS> {
193    type Output = StructuredElement<RS>;
194
195    fn mul(self, rhs: StructuredElement<RS>) -> Self::Output {
196        &self * &rhs
197    }
198}
199
200impl<RS: IntegralDomainSignature> Div<&StructuredElement<RS>> for &StructuredElement<RS> {
201    type Output = StructuredElement<RS>;
202
203    fn div(self, rhs: &StructuredElement<RS>) -> Self::Output {
204        StructuredElement::new(
205            self.structure().clone(),
206            self.structure()
207                .try_divide(self.ref_set(), rhs.ref_set())
208                .unwrap(),
209        )
210    }
211}
212
213impl<RS: IntegralDomainSignature> Div<StructuredElement<RS>> for &StructuredElement<RS> {
214    type Output = StructuredElement<RS>;
215
216    fn div(self, rhs: StructuredElement<RS>) -> Self::Output {
217        self / &rhs
218    }
219}
220
221impl<RS: IntegralDomainSignature> Div<&StructuredElement<RS>> for StructuredElement<RS> {
222    type Output = StructuredElement<RS>;
223
224    fn div(self, rhs: &StructuredElement<RS>) -> Self::Output {
225        &self / rhs
226    }
227}
228
229impl<RS: IntegralDomainSignature> Div<StructuredElement<RS>> for StructuredElement<RS> {
230    type Output = StructuredElement<RS>;
231
232    fn div(self, rhs: StructuredElement<RS>) -> Self::Output {
233        &self / &rhs
234    }
235}
236
237impl<RS: IntegralDomainSignature> StructuredElement<RS> {
238    pub fn pow(&self, n: i32) -> StructuredElement<RS> {
239        StructuredElement::new(
240            self.structure().clone(),
241            self.structure()
242                .try_int_pow(self.ref_set(), &Integer::from(n))
243                .unwrap(),
244        )
245    }
246}
247
248macro_rules! impl_int_ops {
249    ($I : ty) => {
250        //adding $I
251
252        impl<RS: RingSignature> Add<$I> for StructuredElement<RS> {
253            type Output = StructuredElement<RS>;
254
255            fn add(self, rhs: $I) -> Self::Output {
256                let ring = self.structure().clone();
257                self + StructuredElement::new(ring.clone(), ring.from_int(Integer::from(rhs)))
258            }
259        }
260
261        impl<RS: RingSignature> Add<&$I> for StructuredElement<RS> {
262            type Output = StructuredElement<RS>;
263
264            fn add(self, rhs: &$I) -> Self::Output {
265                let ring = self.structure().clone();
266                self + StructuredElement::new(
267                    ring.clone(),
268                    ring.from_int(Integer::from(rhs.clone())),
269                )
270            }
271        }
272
273        impl<RS: RingSignature> Add<$I> for &StructuredElement<RS> {
274            type Output = StructuredElement<RS>;
275
276            fn add(self, rhs: $I) -> Self::Output {
277                let ring = self.structure().clone();
278                self + StructuredElement::new(ring.clone(), ring.from_int(Integer::from(rhs)))
279            }
280        }
281
282        impl<RS: RingSignature> Add<&$I> for &StructuredElement<RS> {
283            type Output = StructuredElement<RS>;
284
285            fn add(self, rhs: &$I) -> Self::Output {
286                let ring = self.structure();
287                self + StructuredElement::new(
288                    ring.clone(),
289                    ring.from_int(Integer::from(rhs.clone())),
290                )
291            }
292        }
293
294        impl<RS: RingSignature> Add<StructuredElement<RS>> for $I {
295            type Output = StructuredElement<RS>;
296
297            fn add(self, rhs: StructuredElement<RS>) -> Self::Output {
298                let ring = rhs.structure().clone();
299                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self))) + rhs
300            }
301        }
302
303        impl<RS: RingSignature> Add<&StructuredElement<RS>> for $I {
304            type Output = StructuredElement<RS>;
305
306            fn add(self, rhs: &StructuredElement<RS>) -> Self::Output {
307                let ring = rhs.structure().clone();
308                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self))) + rhs
309            }
310        }
311
312        impl<RS: RingSignature> Add<StructuredElement<RS>> for &$I {
313            type Output = StructuredElement<RS>;
314
315            fn add(self, rhs: StructuredElement<RS>) -> Self::Output {
316                let ring = rhs.structure().clone();
317                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self.clone())))
318                    + rhs
319            }
320        }
321
322        impl<RS: RingSignature> Add<&StructuredElement<RS>> for &$I {
323            type Output = StructuredElement<RS>;
324
325            fn add(self, rhs: &StructuredElement<RS>) -> Self::Output {
326                let ring = rhs.structure().clone();
327                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self.clone())))
328                    + rhs
329            }
330        }
331
332        //subbing $I
333        impl<RS: RingSignature> Sub<$I> for StructuredElement<RS> {
334            type Output = StructuredElement<RS>;
335
336            fn sub(self, rhs: $I) -> Self::Output {
337                let ring = self.structure().clone();
338                self - StructuredElement::new(ring.clone(), ring.from_int(Integer::from(rhs)))
339            }
340        }
341
342        impl<RS: RingSignature> Sub<&$I> for StructuredElement<RS> {
343            type Output = StructuredElement<RS>;
344
345            fn sub(self, rhs: &$I) -> Self::Output {
346                let ring = self.structure().clone();
347                self - StructuredElement::new(
348                    ring.clone(),
349                    ring.from_int(Integer::from(rhs.clone())),
350                )
351            }
352        }
353
354        impl<RS: RingSignature> Sub<$I> for &StructuredElement<RS> {
355            type Output = StructuredElement<RS>;
356
357            fn sub(self, rhs: $I) -> Self::Output {
358                let ring = self.structure().clone();
359                self - StructuredElement::new(ring.clone(), ring.from_int(Integer::from(rhs)))
360            }
361        }
362
363        impl<RS: RingSignature> Sub<&$I> for &StructuredElement<RS> {
364            type Output = StructuredElement<RS>;
365
366            fn sub(self, rhs: &$I) -> Self::Output {
367                let ring = self.structure().clone();
368                self - StructuredElement::new(
369                    ring.clone(),
370                    ring.from_int(Integer::from(rhs.clone())),
371                )
372            }
373        }
374
375        impl<RS: RingSignature> Sub<StructuredElement<RS>> for $I {
376            type Output = StructuredElement<RS>;
377
378            fn sub(self, rhs: StructuredElement<RS>) -> Self::Output {
379                let ring = rhs.structure().clone();
380                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self))) - rhs
381            }
382        }
383
384        impl<RS: RingSignature> Sub<&StructuredElement<RS>> for $I {
385            type Output = StructuredElement<RS>;
386
387            fn sub(self, rhs: &StructuredElement<RS>) -> Self::Output {
388                let ring = rhs.structure().clone();
389                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self))) - rhs
390            }
391        }
392
393        impl<RS: RingSignature> Sub<StructuredElement<RS>> for &$I {
394            type Output = StructuredElement<RS>;
395
396            fn sub(self, rhs: StructuredElement<RS>) -> Self::Output {
397                let ring = rhs.structure().clone();
398                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self.clone())))
399                    - rhs
400            }
401        }
402
403        impl<RS: RingSignature> Sub<&StructuredElement<RS>> for &$I {
404            type Output = StructuredElement<RS>;
405
406            fn sub(self, rhs: &StructuredElement<RS>) -> Self::Output {
407                let ring = rhs.structure().clone();
408                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self.clone())))
409                    - rhs
410            }
411        }
412
413        //multiplying $I
414        impl<RS: RingSignature> Mul<$I> for StructuredElement<RS> {
415            type Output = StructuredElement<RS>;
416
417            fn mul(self, rhs: $I) -> Self::Output {
418                let ring = self.structure().clone();
419                self * StructuredElement::new(ring.clone(), ring.from_int(Integer::from(rhs)))
420            }
421        }
422
423        impl<RS: RingSignature> Mul<&$I> for StructuredElement<RS> {
424            type Output = StructuredElement<RS>;
425
426            fn mul(self, rhs: &$I) -> Self::Output {
427                let ring = self.structure().clone();
428                self * StructuredElement::new(
429                    ring.clone(),
430                    ring.from_int(Integer::from(rhs.clone())),
431                )
432            }
433        }
434
435        impl<RS: RingSignature> Mul<$I> for &StructuredElement<RS> {
436            type Output = StructuredElement<RS>;
437
438            fn mul(self, rhs: $I) -> Self::Output {
439                let ring = self.structure().clone();
440                self * StructuredElement::new(ring.clone(), ring.from_int(Integer::from(rhs)))
441            }
442        }
443
444        impl<RS: RingSignature> Mul<&$I> for &StructuredElement<RS> {
445            type Output = StructuredElement<RS>;
446
447            fn mul(self, rhs: &$I) -> Self::Output {
448                let ring = self.structure().clone();
449                self * StructuredElement::new(
450                    ring.clone(),
451                    ring.from_int(Integer::from(rhs.clone())),
452                )
453            }
454        }
455
456        impl<RS: RingSignature> Mul<StructuredElement<RS>> for $I {
457            type Output = StructuredElement<RS>;
458
459            fn mul(self, rhs: StructuredElement<RS>) -> Self::Output {
460                let ring = rhs.structure().clone();
461                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self))) * rhs
462            }
463        }
464
465        impl<RS: RingSignature> Mul<&StructuredElement<RS>> for $I {
466            type Output = StructuredElement<RS>;
467
468            fn mul(self, rhs: &StructuredElement<RS>) -> Self::Output {
469                let ring = rhs.structure().clone();
470                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self))) * rhs
471            }
472        }
473
474        impl<RS: RingSignature> Mul<StructuredElement<RS>> for &$I {
475            type Output = StructuredElement<RS>;
476
477            fn mul(self, rhs: StructuredElement<RS>) -> Self::Output {
478                let ring = rhs.structure().clone();
479                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self.clone())))
480                    * rhs
481            }
482        }
483
484        impl<RS: RingSignature> Mul<&StructuredElement<RS>> for &$I {
485            type Output = StructuredElement<RS>;
486
487            fn mul(self, rhs: &StructuredElement<RS>) -> Self::Output {
488                let ring = rhs.structure().clone();
489                StructuredElement::new(ring.clone(), ring.from_int(Integer::from(self.clone())))
490                    * rhs
491            }
492        }
493    };
494}
495
496// impl_int_ops!(u8);
497// impl_int_ops!(u16);
498// impl_int_ops!(u32);
499// impl_int_ops!(u64);
500// impl_int_ops!(u128);
501
502// impl_int_ops!(i8);
503// impl_int_ops!(i16);
504impl_int_ops!(i32);
505// impl_int_ops!(i64);
506// impl_int_ops!(i128);
507
508impl_int_ops!(Integer);
509
510#[cfg(test)]
511mod tests {
512
513    use crate::polynomial::*;
514
515    use super::*;
516
517    #[test]
518    fn test_poly_elem_operations() {
519        let x = &Polynomial::<Integer>::var().into_ergonomic();
520
521        let f = 4 * x.pow(2) - 1;
522        let g = 2 * x + 1;
523
524        // test operations by value and reference
525        println!("{}", -&f.clone());
526        println!("{}", -f.clone());
527        println!("{}", f.clone() + g.clone());
528        println!("{}", &f + g.clone());
529        println!("{}", f.clone() + &g);
530        println!("{}", &f + &g);
531        println!("{}", f.clone() - g.clone());
532        println!("{}", &f - g.clone());
533        println!("{}", f.clone() - &g);
534        println!("{}", &f - &g);
535        println!("{}", f.clone() * g.clone());
536        println!("{}", &f * g.clone());
537        println!("{}", f.clone() * &g);
538        println!("{}", &f * &g);
539        println!("{}", f.clone() / g.clone());
540        println!("{}", &f / g.clone());
541        println!("{}", f.clone() / &g);
542        println!("{}", &f / &g);
543    }
544}