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