ring_algorithm/
ring_traits.rs

1use num_traits::{One, Zero};
2use std::ops::{Add, Div, Mul, Rem, Sub};
3pub trait RingOperation: Sized + Add + Sub + Mul {}
4impl<T> RingOperation for T where T: Sized + Add + Sub + Mul {}
5pub trait RingOperationFrom:
6    Sized
7    + for<'x> From<<&'x Self as Add>::Output>
8    + for<'x> From<<&'x Self as Sub>::Output>
9    + for<'x> From<<&'x Self as Mul>::Output>
10where
11    for<'x> &'x Self: RingOperation,
12{
13}
14impl<T> RingOperationFrom for T
15where
16    T: Sized
17        + for<'x> From<<&'x T as Add>::Output>
18        + for<'x> From<<&'x T as Sub>::Output>
19        + for<'x> From<<&'x T as Mul>::Output>,
20    for<'x> &'x T: RingOperation,
21{
22}
23pub trait EuclideanRingOperation: RingOperation + Div + Rem {}
24impl<T> EuclideanRingOperation for T where T: RingOperation + Div + Rem {}
25pub trait EuclideanRingOperationFrom:
26    RingOperationFrom
27    + for<'x> From<<&'x Self as Div>::Output>
28    + for<'x> From<<&'x Self as Rem>::Output>
29where
30    for<'x> &'x Self: EuclideanRingOperation,
31{
32}
33impl<T> EuclideanRingOperationFrom for T
34where
35    T: RingOperationFrom
36        + for<'x> From<<&'x T as Div>::Output>
37        + for<'x> From<<&'x T as Rem>::Output>,
38    for<'x> &'x T: EuclideanRingOperation,
39{
40}
41/** Normarize ring element
42
43`abs(a)` in $`\mathbb{Z}`$.
44`a/lc(a)` in $`R[x]`$ (`lc(x)` is leading coefficent of x).
45*/
46pub trait RingNormalize {
47    #[must_use]
48    fn leading_unit(&self) -> Self;
49    fn normalize_mut(&mut self);
50    #[must_use]
51    fn into_normalize(mut self) -> Self
52    where
53        Self: Sized,
54    {
55        self.normalize_mut();
56        self
57    }
58    #[must_use]
59    fn normalize(&self) -> Self
60    where
61        Self: Clone,
62    {
63        self.clone().into_normalize()
64    }
65    fn is_similar(&self, other: &Self) -> bool
66    where
67        Self: Clone + Eq,
68    {
69        self.normalize() == other.normalize()
70    }
71}
72
73macro_rules! ring_normalize {
74    ($t:ty) => {
75        impl RingNormalize for $t {
76            fn leading_unit(&self) -> Self {
77                if self >= &Self::zero() {
78                    Self::one()
79                } else {
80                    -Self::one()
81                }
82            }
83            fn normalize_mut(&mut self) {
84                *self = self.abs();
85            }
86        }
87    };
88}
89macro_rules! ring_normalize_unsigned {
90    ($t:ty) => {
91        impl RingNormalize for $t {
92            fn leading_unit(&self) -> Self {
93                Self::one()
94            }
95            fn normalize_mut(&mut self) {}
96        }
97    };
98}
99
100ring_normalize!(i8);
101ring_normalize!(i16);
102ring_normalize!(i32);
103ring_normalize!(i64);
104ring_normalize!(i128);
105ring_normalize!(isize);
106ring_normalize_unsigned!(u8);
107ring_normalize_unsigned!(u16);
108ring_normalize_unsigned!(u32);
109ring_normalize_unsigned!(u64);
110ring_normalize_unsigned!(u128);
111ring_normalize_unsigned!(usize);
112
113#[cfg(feature = "num-bigint")]
114impl RingNormalize for num_bigint::BigInt {
115    fn leading_unit(&self) -> Self {
116        if self.sign() == num_bigint::Sign::Minus {
117            -Self::one()
118        } else {
119            Self::one()
120        }
121    }
122    fn normalize_mut(&mut self) {
123        if self.sign() == num_bigint::Sign::Minus {
124            *self = -&*self
125        }
126    }
127}
128#[cfg(feature = "num-bigint")]
129impl RingNormalize for num_bigint::BigUint {
130    fn leading_unit(&self) -> Self {
131        Self::one()
132    }
133    fn normalize_mut(&mut self) {}
134}
135#[cfg(feature = "rug")]
136impl RingNormalize for rug::Integer {
137    fn leading_unit(&self) -> Self {
138        if self < &Self::zero() {
139            -Self::one()
140        } else {
141            Self::one()
142        }
143    }
144    fn normalize_mut(&mut self) {
145        self.abs_mut()
146    }
147}