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