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);
51zero_impl!(u128, 0);
52
53zero_impl!(isize, 0);
54zero_impl!(i8, 0);
55zero_impl!(i16, 0);
56zero_impl!(i32, 0);
57zero_impl!(i64, 0);
58zero_impl!(i128, 0);
59
60zero_impl!(f32, 0.0);
61zero_impl!(f64, 0.0);
62
63impl<T: Zero> Zero for Wrapping<T>
64where
65 Wrapping<T>: Add<Output = Wrapping<T>>,
66{
67 fn is_zero(&self) -> bool {
68 self.0.is_zero()
69 }
70
71 fn set_zero(&mut self) {
72 self.0.set_zero();
73 }
74
75 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/// ```
88pub 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.
97 fn one() -> Self;
98
99 /// Sets `self` to the multiplicative identity element of `Self`, `1`.
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]
110 fn is_one(&self) -> bool
111 where
112 Self: PartialEq,
113 {
114 *self == Self::one()
115 }
116}
117
118macro_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
133one_impl!(usize, 1);
134one_impl!(u8, 1);
135one_impl!(u16, 1);
136one_impl!(u32, 1);
137one_impl!(u64, 1);
138one_impl!(u128, 1);
139
140one_impl!(isize, 1);
141one_impl!(i8, 1);
142one_impl!(i16, 1);
143one_impl!(i32, 1);
144one_impl!(i64, 1);
145one_impl!(i128, 1);
146
147one_impl!(f32, 1.0);
148one_impl!(f64, 1.0);
149
150impl<T: One> One for Wrapping<T>
151where
152 Wrapping<T>: Mul<Output = Wrapping<T>>,
153{
154 fn set_one(&mut self) {
155 self.0.set_one();
156 }
157
158 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)]
167pub fn zero<T: Zero>() -> T {
168 Zero::zero()
169}
170
171/// Returns the multiplicative identity, `1`.
172#[inline(always)]
173pub fn one<T: One>() -> T {
174 One::one()
175}
176
177#[test]
178fn 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]
194fn wrapping_is_zero() {
195 fn require_zero<T: Zero>(_: &T) {}
196 require_zero(&Wrapping(42));
197}
198#[test]
199fn wrapping_is_one() {
200 fn require_one<T: One>(_: &T) {}
201 require_one(&Wrapping(42));
202}
203