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