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