algebraeon_rings/structure/
ergonomic.rs1use 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 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 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 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
496impl_int_ops!(i32);
505impl_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 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}