Skip to main content

karpal_algebra/
ring.rs

1use crate::semiring::Semiring;
2
3/// A `Semiring` with additive inverses.
4pub trait Ring: Semiring {
5    fn negate(self) -> Self;
6
7    fn sub(self, other: Self) -> Self
8    where
9        Self: Sized,
10    {
11        self.add(other.negate())
12    }
13}
14
15macro_rules! impl_signed_ring {
16    ($($t:ty),*) => {
17        $(
18            impl Ring for $t {
19                fn negate(self) -> Self { -self }
20            }
21        )*
22    };
23}
24
25impl_signed_ring!(i8, i16, i32, i64, i128, f32, f64);
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30
31    #[test]
32    fn i32_negate() {
33        assert_eq!(5i32.negate(), -5);
34    }
35
36    #[test]
37    fn i32_sub() {
38        assert_eq!(10i32.sub(3), 7);
39    }
40}
41
42#[cfg(test)]
43mod law_tests {
44    use super::*;
45    use proptest::prelude::*;
46
47    proptest! {
48        #[test]
49        fn additive_inverse(a in -100i16..100i16) {
50            prop_assert_eq!(a.add(a.negate()), i16::zero());
51        }
52
53        #[test]
54        fn sub_is_add_negate(a in -50i16..50i16, b in -50i16..50i16) {
55            prop_assert_eq!(a.sub(b), a.add(b.negate()));
56        }
57    }
58}