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
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}