1use crate::semiring::Semiring;
5
6pub 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}