relp_num/
zero.rs

1//! # Zero
2//!
3//! A type that is always zero.
4use std::cmp::Ordering;
5use std::fmt;
6use std::ops::{Add, AddAssign, Mul, Neg};
7
8use crate::{Sign, Signed, Negateable};
9
10/// # Zero
11///
12/// A ZST who's value is always zero.
13///
14/// Can be used in specific situations where one knows that, for example, the right-hand side `b` is
15/// always zero. Operations related to `b` should then be compiled away because the operations on
16/// its elements are no-ops.
17#[derive(Copy, Clone)]
18pub struct Zero;
19
20impl num_traits::Zero for Zero {
21    fn zero() -> Self {
22        Self
23    }
24
25    fn is_zero(&self) -> bool {
26        true
27    }
28}
29
30impl Default for Zero {
31    fn default() -> Self {
32        Zero
33    }
34}
35
36impl Add for Zero {
37    type Output = Self;
38
39    fn add(self, _: Self) -> Self::Output {
40        Self
41    }
42}
43
44impl Mul for Zero {
45    type Output = Self;
46
47    fn mul(self, _: Self) -> Self::Output {
48        Self
49    }
50}
51
52impl Eq for Zero {}
53
54impl PartialEq for Zero {
55    fn eq(&self, _: &Self) -> bool {
56        true
57    }
58}
59
60impl PartialOrd for Zero {
61    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
62        Some(Ordering::Equal)
63    }
64}
65
66impl Ord for Zero {
67    fn cmp(&self, _: &Self) -> Ordering {
68        Ordering::Equal
69    }
70}
71
72impl Signed for Zero {
73    fn signum(&self) -> Sign {
74        Sign::Zero
75    }
76}
77
78impl Negateable for Zero {
79    #[inline]
80    fn negate(&mut self) {
81    }
82}
83
84impl Neg for Zero {
85    type Output = Self;
86
87    fn neg(self) -> Self::Output {
88        self
89    }
90}
91
92impl fmt::Debug for Zero {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        <Self as fmt::Display>::fmt(self, f)
95    }
96}
97
98impl fmt::Display for Zero {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        f.write_str("0")
101    }
102}
103
104macro_rules! define_ops {
105    ($primitive:ident) => {
106        impl From<Zero> for $primitive {
107            fn from(_: Zero) -> Self {
108                0
109            }
110        }
111
112        impl From<&Zero> for $primitive {
113            fn from(_: &Zero) -> Self {
114                0
115            }
116        }
117
118        impl Add<Zero> for $primitive {
119            type Output = Self;
120
121            fn add(self, _: Zero) -> Self::Output {
122                self
123            }
124        }
125
126        impl Add<&Zero> for $primitive {
127            type Output = Self;
128
129            fn add(self, _: &Zero) -> Self::Output {
130                self
131            }
132        }
133
134        impl AddAssign<&Zero> for $primitive {
135            fn add_assign(&mut self, _: &Zero) {
136            }
137        }
138
139        impl Mul<Zero> for $primitive {
140            type Output = Self;
141
142            fn mul(self, _: Zero) -> Self::Output {
143                0
144            }
145        }
146
147        impl Mul<&Zero> for $primitive {
148            type Output = Self;
149
150            fn mul(self, _: &Zero) -> Self::Output {
151                0
152            }
153        }
154
155        impl Mul<&Zero> for &$primitive {
156            type Output = $primitive;
157
158            fn mul(self, _: &Zero) -> Self::Output {
159                0
160            }
161        }
162    }
163}
164
165define_ops!(i8);
166define_ops!(i16);
167define_ops!(i32);
168define_ops!(i64);
169define_ops!(i128);
170define_ops!(u8);
171define_ops!(u16);
172define_ops!(u32);
173define_ops!(u64);
174define_ops!(u128);
175
176#[cfg(test)]
177mod test {
178    use crate::{Abs, Sign, Signed, Zero};
179
180    #[test]
181    fn test() {
182        assert_eq!(Zero, num_traits::Zero::zero());
183        assert!(num_traits::Zero::is_zero(&Zero));
184        assert_eq!(Zero + Zero, Zero);
185        assert_eq!(Zero * Zero, Zero);
186        assert_eq!(Zero.abs(), Zero);
187        assert_eq!(Zero.signum(), Sign::Zero);
188    }
189    
190    #[test]
191    fn test_integer() {
192        assert_eq!(1 + Zero, 1);
193        assert_eq!(-1 + Zero, -1);
194        assert_eq!(894 * Zero, 0);
195        assert_eq!(-894 * &Zero, 0);
196        assert_eq!(0_u8 * &Zero, 0);
197    }
198}