Skip to main content

karpal_algebra/
ring.rs

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