1use core::num::Wrapping;
2use core::ops::{Add, Mul};
3
4pub trait Zero: Sized + Add<Self, Output = Self> {
13    fn zero() -> Self;
21
22    fn set_zero(&mut self) {
24        *self = Zero::zero();
25    }
26
27    fn is_zero(&self) -> bool;
29}
30
31pub trait ConstZero: Zero {
34    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
98pub trait One: Sized + Mul<Self, Output = Self> {
107    fn one() -> Self;
116
117    fn set_one(&mut self) {
119        *self = One::one();
120    }
121
122    #[inline]
128    fn is_one(&self) -> bool
129    where
130        Self: PartialEq,
131    {
132        *self == Self::one()
133    }
134}
135
136pub trait ConstOne: One {
139    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#[inline(always)]
203pub fn zero<T: Zero>() -> T {
204    Zero::zero()
205}
206
207#[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}