1use core::num::Wrapping;
2use 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/// ```
12pub 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
31macro_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
46zero_impl!(usize, 0);
47zero_impl!(u8, 0);
48zero_impl!(u16, 0);
49zero_impl!(u32, 0);
50zero_impl!(u64, 0);
51#[cfg(has_i128)]
52zero_impl!(u128, 0);
53
54zero_impl!(isize, 0);
55zero_impl!(i8, 0);
56zero_impl!(i16, 0);
57zero_impl!(i32, 0);
58zero_impl!(i64, 0);
59#[cfg(has_i128)]
60zero_impl!(i128, 0);
61
62zero_impl!(f32, 0.0);
63zero_impl!(f64, 0.0);
64
65impl<T: Zero> Zero for Wrapping<T>
66where
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/// ```
90pub 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
120macro_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
135one_impl!(usize, 1);
136one_impl!(u8, 1);
137one_impl!(u16, 1);
138one_impl!(u32, 1);
139one_impl!(u64, 1);
140#[cfg(has_i128)]
141one_impl!(u128, 1);
142
143one_impl!(isize, 1);
144one_impl!(i8, 1);
145one_impl!(i16, 1);
146one_impl!(i32, 1);
147one_impl!(i64, 1);
148#[cfg(has_i128)]
149one_impl!(i128, 1);
150
151one_impl!(f32, 1.0);
152one_impl!(f64, 1.0);
153
154impl<T: One> One for Wrapping<T>
155where
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)]
171pub fn zero<T: Zero>() -> T {
172 Zero::zero()
173}
174
175/// Returns the multiplicative identity, `1`.
176#[inline(always)]
177pub fn one<T: One>() -> T {
178 One::one()
179}
180
181#[test]
182fn 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]
198fn wrapping_is_zero() {
199 fn require_zero<T: Zero>(_: &T) {}
200 require_zero(&Wrapping(42));
201}
202#[test]
203fn wrapping_is_one() {
204 fn require_one<T: One>(_: &T) {}
205 require_one(&Wrapping(42));
206}
207