1 use core::ops::{Add, Mul};
2 use core::num::Wrapping;
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     // FIXME (#5527): This should be an associated constant
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 { $v }
33             #[inline]
34             fn is_zero(&self) -> bool { *self == $v }
35         }
36     }
37 }
38 
39 zero_impl!(usize, 0usize);
40 zero_impl!(u8,    0u8);
41 zero_impl!(u16,   0u16);
42 zero_impl!(u32,   0u32);
43 zero_impl!(u64,   0u64);
44 
45 zero_impl!(isize, 0isize);
46 zero_impl!(i8,    0i8);
47 zero_impl!(i16,   0i16);
48 zero_impl!(i32,   0i32);
49 zero_impl!(i64,   0i64);
50 
51 zero_impl!(f32, 0.0f32);
52 zero_impl!(f64, 0.0f64);
53 
54 impl<T: Zero> Zero for Wrapping<T> where Wrapping<T>: Add<Output=Wrapping<T>> {
is_zero(&self) -> bool55     fn is_zero(&self) -> bool {
56         self.0.is_zero()
57     }
zero() -> Self58     fn zero() -> Self {
59         Wrapping(T::zero())
60     }
61 }
62 
63 
64 /// Defines a multiplicative identity element for `Self`.
65 pub trait One: Sized + Mul<Self, Output = Self> {
66     /// Returns the multiplicative identity element of `Self`, `1`.
67     ///
68     /// # Laws
69     ///
70     /// ```{.text}
71     /// a * 1 = a       ∀ a ∈ Self
72     /// 1 * a = a       ∀ a ∈ Self
73     /// ```
74     ///
75     /// # Purity
76     ///
77     /// This function should return the same result at all times regardless of
78     /// external mutable state, for example values stored in TLS or in
79     /// `static mut`s.
80     // FIXME (#5527): This should be an associated constant
one() -> Self81     fn one() -> Self;
82 }
83 
84 macro_rules! one_impl {
85     ($t:ty, $v:expr) => {
86         impl One for $t {
87             #[inline]
88             fn one() -> $t { $v }
89         }
90     }
91 }
92 
93 one_impl!(usize, 1usize);
94 one_impl!(u8,    1u8);
95 one_impl!(u16,   1u16);
96 one_impl!(u32,   1u32);
97 one_impl!(u64,   1u64);
98 
99 one_impl!(isize, 1isize);
100 one_impl!(i8,    1i8);
101 one_impl!(i16,   1i16);
102 one_impl!(i32,   1i32);
103 one_impl!(i64,   1i64);
104 
105 one_impl!(f32, 1.0f32);
106 one_impl!(f64, 1.0f64);
107 
108 impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
one() -> Self109     fn one() -> Self {
110         Wrapping(T::one())
111     }
112 }
113 
114 // Some helper functions provided for backwards compatibility.
115 
116 /// Returns the additive identity, `0`.
zero<T: Zero>() -> T117 #[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
118 
119 /// Returns the multiplicative identity, `1`.
one<T: One>() -> T120 #[inline(always)] pub fn one<T: One>() -> T { One::one() }
121 
122 
123 #[test]
wrapping_identities()124 fn wrapping_identities() {
125     macro_rules! test_wrapping_identities {
126         ($($t:ty)+) => {
127             $(
128                 assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0);
129                 assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0);
130                 assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero());
131                 assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero());
132             )+
133         };
134     }
135 
136     test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64);
137 }
138 
139 #[test]
wrapping_is_zero()140 fn wrapping_is_zero() {
141     fn require_zero<T: Zero>(_: &T) {}
142     require_zero(&Wrapping(42));
143 }
144 #[test]
wrapping_is_one()145 fn wrapping_is_one() {
146     fn require_one<T: One>(_: &T) {}
147     require_one(&Wrapping(42));
148 }
149