1 | use core::num::Wrapping; |
2 | use core::ops::{Add, Mul}; |
3 | |
4 | /// Defines an additive identity element for `Self`. |
5 | /// |
6 | /// # Laws |
7 | /// |
8 | /// ```{.text} |
9 | /// a + 0 = a ∀ a ∈ Self |
10 | /// 0 + a = a ∀ a ∈ Self |
11 | /// ``` |
12 | pub trait Zero: Sized + Add<Self, Output = Self> { |
13 | /// Returns the additive identity element of `Self`, `0`. |
14 | /// # Purity |
15 | /// |
16 | /// This function should return the same result at all times regardless of |
17 | /// external mutable state, for example values stored in TLS or in |
18 | /// `static mut`s. |
19 | // This cannot be an associated constant, because of bignums. |
20 | fn zero() -> Self; |
21 | |
22 | /// Sets `self` to the additive identity element of `Self`, `0`. |
23 | fn set_zero(&mut self) { |
24 | *self = Zero::zero(); |
25 | } |
26 | |
27 | /// Returns `true` if `self` is equal to the additive identity. |
28 | fn is_zero(&self) -> bool; |
29 | } |
30 | |
31 | macro_rules! zero_impl { |
32 | ($t:ty, $v:expr) => { |
33 | impl Zero for $t { |
34 | #[inline] |
35 | fn zero() -> $t { |
36 | $v |
37 | } |
38 | #[inline] |
39 | fn is_zero(&self) -> bool { |
40 | *self == $v |
41 | } |
42 | } |
43 | }; |
44 | } |
45 | |
46 | zero_impl!(usize, 0); |
47 | zero_impl!(u8, 0); |
48 | zero_impl!(u16, 0); |
49 | zero_impl!(u32, 0); |
50 | zero_impl!(u64, 0); |
51 | #[cfg (has_i128)] |
52 | zero_impl!(u128, 0); |
53 | |
54 | zero_impl!(isize, 0); |
55 | zero_impl!(i8, 0); |
56 | zero_impl!(i16, 0); |
57 | zero_impl!(i32, 0); |
58 | zero_impl!(i64, 0); |
59 | #[cfg (has_i128)] |
60 | zero_impl!(i128, 0); |
61 | |
62 | zero_impl!(f32, 0.0); |
63 | zero_impl!(f64, 0.0); |
64 | |
65 | impl<T: Zero> Zero for Wrapping<T> |
66 | where |
67 | Wrapping<T>: Add<Output = Wrapping<T>>, |
68 | { |
69 | fn is_zero(&self) -> bool { |
70 | self.0.is_zero() |
71 | } |
72 | |
73 | fn set_zero(&mut self) { |
74 | self.0.set_zero(); |
75 | } |
76 | |
77 | fn zero() -> Self { |
78 | Wrapping(T::zero()) |
79 | } |
80 | } |
81 | |
82 | /// Defines a multiplicative identity element for `Self`. |
83 | /// |
84 | /// # Laws |
85 | /// |
86 | /// ```{.text} |
87 | /// a * 1 = a ∀ a ∈ Self |
88 | /// 1 * a = a ∀ a ∈ Self |
89 | /// ``` |
90 | pub trait One: Sized + Mul<Self, Output = Self> { |
91 | /// Returns the multiplicative identity element of `Self`, `1`. |
92 | /// |
93 | /// # Purity |
94 | /// |
95 | /// This function should return the same result at all times regardless of |
96 | /// external mutable state, for example values stored in TLS or in |
97 | /// `static mut`s. |
98 | // This cannot be an associated constant, because of bignums. |
99 | fn one() -> Self; |
100 | |
101 | /// Sets `self` to the multiplicative identity element of `Self`, `1`. |
102 | fn set_one(&mut self) { |
103 | *self = One::one(); |
104 | } |
105 | |
106 | /// Returns `true` if `self` is equal to the multiplicative identity. |
107 | /// |
108 | /// For performance reasons, it's best to implement this manually. |
109 | /// After a semver bump, this method will be required, and the |
110 | /// `where Self: PartialEq` bound will be removed. |
111 | #[inline ] |
112 | fn is_one(&self) -> bool |
113 | where |
114 | Self: PartialEq, |
115 | { |
116 | *self == Self::one() |
117 | } |
118 | } |
119 | |
120 | macro_rules! one_impl { |
121 | ($t:ty, $v:expr) => { |
122 | impl One for $t { |
123 | #[inline] |
124 | fn one() -> $t { |
125 | $v |
126 | } |
127 | #[inline] |
128 | fn is_one(&self) -> bool { |
129 | *self == $v |
130 | } |
131 | } |
132 | }; |
133 | } |
134 | |
135 | one_impl!(usize, 1); |
136 | one_impl!(u8, 1); |
137 | one_impl!(u16, 1); |
138 | one_impl!(u32, 1); |
139 | one_impl!(u64, 1); |
140 | #[cfg (has_i128)] |
141 | one_impl!(u128, 1); |
142 | |
143 | one_impl!(isize, 1); |
144 | one_impl!(i8, 1); |
145 | one_impl!(i16, 1); |
146 | one_impl!(i32, 1); |
147 | one_impl!(i64, 1); |
148 | #[cfg (has_i128)] |
149 | one_impl!(i128, 1); |
150 | |
151 | one_impl!(f32, 1.0); |
152 | one_impl!(f64, 1.0); |
153 | |
154 | impl<T: One> One for Wrapping<T> |
155 | where |
156 | Wrapping<T>: Mul<Output = Wrapping<T>>, |
157 | { |
158 | fn set_one(&mut self) { |
159 | self.0.set_one(); |
160 | } |
161 | |
162 | fn one() -> Self { |
163 | Wrapping(T::one()) |
164 | } |
165 | } |
166 | |
167 | // Some helper functions provided for backwards compatibility. |
168 | |
169 | /// Returns the additive identity, `0`. |
170 | #[inline (always)] |
171 | pub fn zero<T: Zero>() -> T { |
172 | Zero::zero() |
173 | } |
174 | |
175 | /// Returns the multiplicative identity, `1`. |
176 | #[inline (always)] |
177 | pub fn one<T: One>() -> T { |
178 | One::one() |
179 | } |
180 | |
181 | #[test ] |
182 | fn wrapping_identities() { |
183 | macro_rules! test_wrapping_identities { |
184 | ($($t:ty)+) => { |
185 | $( |
186 | assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0); |
187 | assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0); |
188 | assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero()); |
189 | assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero()); |
190 | )+ |
191 | }; |
192 | } |
193 | |
194 | test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64); |
195 | } |
196 | |
197 | #[test ] |
198 | fn wrapping_is_zero() { |
199 | fn require_zero<T: Zero>(_: &T) {} |
200 | require_zero(&Wrapping(42)); |
201 | } |
202 | #[test ] |
203 | fn wrapping_is_one() { |
204 | fn require_one<T: One>(_: &T) {} |
205 | require_one(&Wrapping(42)); |
206 | } |
207 | |