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