num_traits/
identities.rs

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