1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
pub trait UnitaryRing<Output = Self>:
    Sized
    + Clone
    + num_traits::Zero
    + num_traits::One
    + std::ops::Neg<Output = Output>
    + for<'x> std::ops::AddAssign<&'x Self>
    + for<'x> std::ops::SubAssign<&'x Self>
    + for<'x> std::ops::MulAssign<&'x Self>
{
}
impl<T> UnitaryRing for T where
    T: Sized
        + Clone
        + num_traits::Zero
        + num_traits::One
        + std::ops::Neg<Output = Self>
        + for<'x> std::ops::AddAssign<&'x Self>
        + for<'x> std::ops::SubAssign<&'x Self>
        + for<'x> std::ops::MulAssign<&'x Self>
{
}
pub trait EuclideanRing<Output = Self>:
    UnitaryRing + for<'x> std::ops::DivAssign<&'x Self> + for<'x> std::ops::RemAssign<&'x Self>
{
}
impl<T> EuclideanRing for T where
    T: UnitaryRing + for<'x> std::ops::DivAssign<&'x Self> + for<'x> std::ops::RemAssign<&'x Self>
{
}
pub trait RingOperation<Output = Self>:
    Sized
    + std::ops::Add<Output = Output>
    + std::ops::Sub<Output = Output>
    + std::ops::Mul<Output = Output>
{
}
impl<T> RingOperation<T> for T where
    T: Sized + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + std::ops::Mul<Output = T>
{
}
impl<'a, T> RingOperation<T> for &'a T where
    &'a T:
        Sized + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + std::ops::Mul<Output = T>
{
}
pub trait EuclideanRingOperation<Output = Self>:
    RingOperation<Output> + std::ops::Div<Output = Output> + std::ops::Rem<Output = Output>
{
}
impl<T> EuclideanRingOperation<T> for T where
    T: RingOperation<T> + std::ops::Div<Output = T> + std::ops::Rem<Output = T>
{
}
impl<'a, T> EuclideanRingOperation<T> for &'a T where
    &'a T: RingOperation<T> + std::ops::Div<Output = T> + std::ops::Rem<Output = T>
{
}
/** Normarize ring element

`abs(a)` in $`\mathbb{Z}`$.
`a/lc(a)` in $`R[x]`$ (`lc(x)` is leading coefficent of x).
*/
pub trait RingNormalize {
    fn leading_unit(&self) -> Self;
    fn normalize_mut(&mut self);
    fn into_normalize(mut self) -> Self
    where
        Self: Sized,
    {
        self.normalize_mut();
        self
    }
    fn normalize(&self) -> Self
    where
        Self: Clone,
    {
        self.clone().into_normalize()
    }
    fn is_similar(&self, other: &Self) -> bool
    where
        Self: Clone + Eq,
    {
        self.normalize() == other.normalize()
    }
}

#[cfg(feature = "debug")]
pub trait DebugOnFeature: std::fmt::Debug + std::fmt::Display {}
#[cfg(feature = "debug")]
impl<T> DebugOnFeature for T where T: std::fmt::Debug + std::fmt::Display {}
#[cfg(not(feature = "debug"))]
pub trait DebugOnFeature {}
#[cfg(not(feature = "debug"))]
impl<T> DebugOnFeature for T {}

macro_rules! ring_normalize {
    ($t:ty) => {
        impl RingNormalize for $t {
            fn leading_unit(&self) -> Self {
                use num_traits::{One, Zero};
                if self >= &<$t>::zero() {
                    <$t>::one()
                } else {
                    -<$t>::one()
                }
            }
            fn normalize_mut(&mut self) {
                *self = self.abs();
            }
        }
    };
}

ring_normalize!(i8);
ring_normalize!(i16);
ring_normalize!(i32);
ring_normalize!(i64);
ring_normalize!(i128);
ring_normalize!(isize);