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 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 {
is_zero(&self) -> bool69 fn is_zero(&self) -> bool {
70 self.0.is_zero()
71 }
72
set_zero(&mut self)73 fn set_zero(&mut self) {
74 self.0.set_zero();
75 }
76
zero() -> Self77 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.
one() -> Self99 fn one() -> Self;
100
101 /// Sets `self` to the multiplicative identity element of `Self`, `1`.
set_one(&mut self)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]
is_one(&self) -> bool where Self: PartialEq,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 {
set_one(&mut self)158 fn set_one(&mut self) {
159 self.0.set_one();
160 }
161
one() -> Self162 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)]
zero<T: Zero>() -> T171 pub fn zero<T: Zero>() -> T {
172 Zero::zero()
173 }
174
175 /// Returns the multiplicative identity, `1`.
176 #[inline(always)]
one<T: One>() -> T177 pub fn one<T: One>() -> T {
178 One::one()
179 }
180
181 #[test]
wrapping_identities()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]
wrapping_is_zero()198 fn wrapping_is_zero() {
199 fn require_zero<T: Zero>(_: &T) {}
200 require_zero(&Wrapping(42));
201 }
202 #[test]
wrapping_is_one()203 fn wrapping_is_one() {
204 fn require_one<T: One>(_: &T) {}
205 require_one(&Wrapping(42));
206 }
207