1 use core::num::Wrapping;
2 use core::ops::{Add, Mul};
3
4 /// Defines an additive identity element for `Self`.
5 pub trait Zero: Sized + Add<Self, Output = Self> {
6 /// Returns the additive identity element of `Self`, `0`.
7 ///
8 /// # Laws
9 ///
10 /// ```{.text}
11 /// a + 0 = a ∀ a ∈ Self
12 /// 0 + a = a ∀ a ∈ Self
13 /// ```
14 ///
15 /// # Purity
16 ///
17 /// This function should return the same result at all times regardless of
18 /// external mutable state, for example values stored in TLS or in
19 /// `static mut`s.
20 // This cannot be an associated constant, because of bignums.
zero() -> Self21 fn zero() -> Self;
22
23 /// Returns `true` if `self` is equal to the additive identity.
24 #[inline]
is_zero(&self) -> bool25 fn is_zero(&self) -> bool;
26 }
27
28 macro_rules! zero_impl {
29 ($t:ty, $v:expr) => {
30 impl Zero for $t {
31 #[inline]
32 fn zero() -> $t {
33 $v
34 }
35 #[inline]
36 fn is_zero(&self) -> bool {
37 *self == $v
38 }
39 }
40 };
41 }
42
43 zero_impl!(usize, 0);
44 zero_impl!(u8, 0);
45 zero_impl!(u16, 0);
46 zero_impl!(u32, 0);
47 zero_impl!(u64, 0);
48 #[cfg(has_i128)]
49 zero_impl!(u128, 0);
50
51 zero_impl!(isize, 0);
52 zero_impl!(i8, 0);
53 zero_impl!(i16, 0);
54 zero_impl!(i32, 0);
55 zero_impl!(i64, 0);
56 #[cfg(has_i128)]
57 zero_impl!(i128, 0);
58
59 zero_impl!(f32, 0.0);
60 zero_impl!(f64, 0.0);
61
62 impl<T: Zero> Zero for Wrapping<T>
63 where
64 Wrapping<T>: Add<Output = Wrapping<T>>,
65 {
is_zero(&self) -> bool66 fn is_zero(&self) -> bool {
67 self.0.is_zero()
68 }
zero() -> Self69 fn zero() -> Self {
70 Wrapping(T::zero())
71 }
72 }
73
74 /// Defines a multiplicative identity element for `Self`.
75 pub trait One: Sized + Mul<Self, Output = Self> {
76 /// Returns the multiplicative identity element of `Self`, `1`.
77 ///
78 /// # Laws
79 ///
80 /// ```{.text}
81 /// a * 1 = a ∀ a ∈ Self
82 /// 1 * a = a ∀ a ∈ Self
83 /// ```
84 ///
85 /// # Purity
86 ///
87 /// This function should return the same result at all times regardless of
88 /// external mutable state, for example values stored in TLS or in
89 /// `static mut`s.
90 // This cannot be an associated constant, because of bignums.
one() -> Self91 fn one() -> Self;
92
93 /// Returns `true` if `self` is equal to the multiplicative identity.
94 ///
95 /// For performance reasons, it's best to implement this manually.
96 /// After a semver bump, this method will be required, and the
97 /// `where Self: PartialEq` bound will be removed.
98 #[inline]
is_one(&self) -> bool where Self: PartialEq,99 fn is_one(&self) -> bool
100 where
101 Self: PartialEq,
102 {
103 *self == Self::one()
104 }
105 }
106
107 macro_rules! one_impl {
108 ($t:ty, $v:expr) => {
109 impl One for $t {
110 #[inline]
111 fn one() -> $t {
112 $v
113 }
114 }
115 };
116 }
117
118 one_impl!(usize, 1);
119 one_impl!(u8, 1);
120 one_impl!(u16, 1);
121 one_impl!(u32, 1);
122 one_impl!(u64, 1);
123 #[cfg(has_i128)]
124 one_impl!(u128, 1);
125
126 one_impl!(isize, 1);
127 one_impl!(i8, 1);
128 one_impl!(i16, 1);
129 one_impl!(i32, 1);
130 one_impl!(i64, 1);
131 #[cfg(has_i128)]
132 one_impl!(i128, 1);
133
134 one_impl!(f32, 1.0);
135 one_impl!(f64, 1.0);
136
137 impl<T: One> One for Wrapping<T>
138 where
139 Wrapping<T>: Mul<Output = Wrapping<T>>,
140 {
one() -> Self141 fn one() -> Self {
142 Wrapping(T::one())
143 }
144 }
145
146 // Some helper functions provided for backwards compatibility.
147
148 /// Returns the additive identity, `0`.
149 #[inline(always)]
zero<T: Zero>() -> T150 pub fn zero<T: Zero>() -> T {
151 Zero::zero()
152 }
153
154 /// Returns the multiplicative identity, `1`.
155 #[inline(always)]
one<T: One>() -> T156 pub fn one<T: One>() -> T {
157 One::one()
158 }
159
160 #[test]
wrapping_identities()161 fn wrapping_identities() {
162 macro_rules! test_wrapping_identities {
163 ($($t:ty)+) => {
164 $(
165 assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0);
166 assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0);
167 assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero());
168 assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero());
169 )+
170 };
171 }
172
173 test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64);
174 }
175
176 #[test]
wrapping_is_zero()177 fn wrapping_is_zero() {
178 fn require_zero<T: Zero>(_: &T) {}
179 require_zero(&Wrapping(42));
180 }
181 #[test]
wrapping_is_one()182 fn wrapping_is_one() {
183 fn require_one<T: One>(_: &T) {}
184 require_one(&Wrapping(42));
185 }
186