polymatheia/
traits.rs

1//! Numeric traits.
2
3macro_rules! checked_unary_impl {
4    ($trait:ident, $method:ident, $type:ty) => {
5        impl $trait for $type {
6            type Output = $type;
7
8            fn $method(&self) -> Option<Self::Output> {
9                <$type>::$method(*self)
10            }
11        }
12    };
13}
14
15macro_rules! checked_binary_impl {
16    ($trait:ident, $method:ident, $type:ty) => {
17        impl $trait for $type {
18            type Output = $type;
19
20            fn $method(&self, other: &$type) -> Option<Self::Output> {
21                <$type>::$method(*self, *other)
22            }
23        }
24    };
25}
26
27macro_rules! binary_impl {
28    ($trait:ident, $method:ident, $type:ty) => {
29        impl $trait for $type {
30            type Output = $type;
31
32            fn $method(&self, other: &$type) -> Self::Output {
33                <$type>::$method(*self, *other)
34            }
35        }
36    };
37}
38
39macro_rules! zero_impl {
40    ($type:ty, $value:expr) => {
41        impl Zero for $type {
42            fn zero() -> Self {
43                $value
44            }
45
46            fn is_zero(&self) -> bool {
47                *self == $value
48            }
49        }
50    };
51}
52
53macro_rules! one_impl {
54    ($type:ty, $value:expr) => {
55        impl One for $type {
56            fn one() -> Self {
57                $value
58            }
59
60            fn is_one(&self) -> bool {
61                *self == $value
62            }
63        }
64    };
65}
66
67/// Negation that returns `None` instead of overflowing.
68pub trait CheckedNeg<Output = Self> {
69    type Output;
70
71    /// Negates a number and returns `None` instead of overflowing.
72    fn checked_neg(&self) -> Option<Self::Output>;
73}
74
75checked_unary_impl!(CheckedNeg, checked_neg, u8);
76checked_unary_impl!(CheckedNeg, checked_neg, u16);
77checked_unary_impl!(CheckedNeg, checked_neg, u32);
78checked_unary_impl!(CheckedNeg, checked_neg, u64);
79checked_unary_impl!(CheckedNeg, checked_neg, u128);
80checked_unary_impl!(CheckedNeg, checked_neg, usize);
81
82checked_unary_impl!(CheckedNeg, checked_neg, i8);
83checked_unary_impl!(CheckedNeg, checked_neg, i16);
84checked_unary_impl!(CheckedNeg, checked_neg, i32);
85checked_unary_impl!(CheckedNeg, checked_neg, i64);
86checked_unary_impl!(CheckedNeg, checked_neg, i128);
87checked_unary_impl!(CheckedNeg, checked_neg, isize);
88
89/// Addition that returns `None` instead of overflowing.
90pub trait CheckedAdd<Output = Self> {
91    type Output;
92
93    /// Adds two numbers and returns `None` instead of overflowing.
94    fn checked_add(&self, other: &Self) -> Option<Self::Output>;
95}
96
97checked_binary_impl!(CheckedAdd, checked_add, u8);
98checked_binary_impl!(CheckedAdd, checked_add, u16);
99checked_binary_impl!(CheckedAdd, checked_add, u32);
100checked_binary_impl!(CheckedAdd, checked_add, u64);
101checked_binary_impl!(CheckedAdd, checked_add, u128);
102checked_binary_impl!(CheckedAdd, checked_add, usize);
103
104checked_binary_impl!(CheckedAdd, checked_add, i8);
105checked_binary_impl!(CheckedAdd, checked_add, i16);
106checked_binary_impl!(CheckedAdd, checked_add, i32);
107checked_binary_impl!(CheckedAdd, checked_add, i64);
108checked_binary_impl!(CheckedAdd, checked_add, i128);
109checked_binary_impl!(CheckedAdd, checked_add, isize);
110
111/// Euclidean division.
112pub trait DivEuclid<Output = Self> {
113    type Output;
114
115    /// Divides two numbers with Euclidean division.
116    fn div_euclid(&self, other: &Self) -> Self::Output;
117}
118
119binary_impl!(DivEuclid, div_euclid, u8);
120binary_impl!(DivEuclid, div_euclid, u16);
121binary_impl!(DivEuclid, div_euclid, u32);
122binary_impl!(DivEuclid, div_euclid, u64);
123binary_impl!(DivEuclid, div_euclid, u128);
124binary_impl!(DivEuclid, div_euclid, usize);
125
126binary_impl!(DivEuclid, div_euclid, i8);
127binary_impl!(DivEuclid, div_euclid, i16);
128binary_impl!(DivEuclid, div_euclid, i32);
129binary_impl!(DivEuclid, div_euclid, i64);
130binary_impl!(DivEuclid, div_euclid, i128);
131binary_impl!(DivEuclid, div_euclid, isize);
132
133impl<T: CheckedAdd<Output = T>> CheckedAdd for Option<T> {
134    type Output = T;
135
136    fn checked_add(&self, other: &Self) -> Option<Self::Output> {
137        self.as_ref()?.checked_add(other.as_ref()?)
138    }
139}
140
141/// The additive identity, `0`.
142pub trait Zero {
143    /// Returns the additive identity, `0`.
144    fn zero() -> Self;
145
146    /// Returns `true` if `self` is the additive identity, `0`.
147    fn is_zero(&self) -> bool;
148}
149
150zero_impl!(u8, 0);
151zero_impl!(u16, 0);
152zero_impl!(u32, 0);
153zero_impl!(u64, 0);
154zero_impl!(u128, 0);
155zero_impl!(usize, 0);
156
157zero_impl!(i8, 0);
158zero_impl!(i16, 0);
159zero_impl!(i32, 0);
160zero_impl!(i64, 0);
161zero_impl!(i128, 0);
162zero_impl!(isize, 0);
163
164zero_impl!(f32, 0.0);
165zero_impl!(f64, 0.0);
166
167/// The multiplicative identity, `1`.
168pub trait One {
169    /// Returns the multiplicative identity, `1`.
170    fn one() -> Self;
171
172    /// Returns `true` if `self` is the multiplicative identity, `1`.
173    fn is_one(&self) -> bool;
174}
175
176one_impl!(u8, 1);
177one_impl!(u16, 1);
178one_impl!(u32, 1);
179one_impl!(u64, 1);
180one_impl!(u128, 1);
181one_impl!(usize, 1);
182
183one_impl!(i8, 1);
184one_impl!(i16, 1);
185one_impl!(i32, 1);
186one_impl!(i64, 1);
187one_impl!(i128, 1);
188one_impl!(isize, 1);
189
190one_impl!(f32, 1.0);
191one_impl!(f64, 1.0);