1use std::fmt;
5use std::ops::{Add, AddAssign, Mul, Neg};
6
7use crate::{Sign, Signed, Negateable};
8
9#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
28pub struct Zero;
29
30impl num_traits::Zero for Zero {
31 fn zero() -> Self {
32 Self
33 }
34
35 fn is_zero(&self) -> bool {
36 true
37 }
38}
39
40impl Add for Zero {
41 type Output = Self;
42
43 fn add(self, _: Self) -> Self::Output {
44 Self
45 }
46}
47
48impl Mul for Zero {
49 type Output = Self;
50
51 fn mul(self, _: Self) -> Self::Output {
52 Self
53 }
54}
55
56impl Signed for Zero {
58 #[inline]
59 fn signum(&self) -> Sign {
60 Sign::Zero
61 }
62}
63
64impl Negateable for Zero {
66 #[inline]
67 fn negate(&mut self) {
68 }
69}
70
71impl Neg for Zero {
72 type Output = Self;
73
74 #[inline]
75 fn neg(self) -> Self::Output {
76 self
77 }
78}
79
80impl fmt::Debug for Zero {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 <Self as fmt::Display>::fmt(self, f)
84 }
85}
86
87impl fmt::Display for Zero {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.write_str("0")
90 }
91}
92
93macro_rules! define_ops {
94 ($primitive:ident) => {
95 impl From<Zero> for $primitive {
96 fn from(_: Zero) -> Self {
97 0
98 }
99 }
100
101 impl From<&Zero> for $primitive {
102 fn from(_: &Zero) -> Self {
103 0
104 }
105 }
106
107 impl Add<Zero> for $primitive {
108 type Output = Self;
109
110 fn add(self, _: Zero) -> Self::Output {
111 self
112 }
113 }
114
115 impl Add<&Zero> for $primitive {
116 type Output = Self;
117
118 fn add(self, _: &Zero) -> Self::Output {
119 self
120 }
121 }
122
123 impl AddAssign<&Zero> for $primitive {
124 fn add_assign(&mut self, _: &Zero) {
125 }
126 }
127
128 impl Mul<Zero> for $primitive {
129 type Output = Self;
130
131 fn mul(self, _: Zero) -> Self::Output {
132 0
133 }
134 }
135
136 impl Mul<&Zero> for $primitive {
137 type Output = Self;
138
139 fn mul(self, _: &Zero) -> Self::Output {
140 0
141 }
142 }
143
144 impl Mul<&Zero> for &$primitive {
145 type Output = $primitive;
146
147 fn mul(self, _: &Zero) -> Self::Output {
148 0
149 }
150 }
151 }
152}
153
154define_ops!(i8);
155define_ops!(i16);
156define_ops!(i32);
157define_ops!(i64);
158define_ops!(i128);
159define_ops!(u8);
160define_ops!(u16);
161define_ops!(u32);
162define_ops!(u64);
163define_ops!(u128);
164
165#[cfg(test)]
166mod test {
167 use std::cmp::Ordering;
168
169 use crate::{Abs, Negateable, Sign, Signed};
170 use crate::fixed::Zero;
171
172 #[test]
173 fn test() {
174 assert_eq!(Zero, num_traits::Zero::zero());
175 assert!(num_traits::Zero::is_zero(&Zero));
176 assert_eq!(Zero + Zero, Zero);
177 assert_eq!(Zero * Zero, Zero);
178 assert_eq!(Zero.abs(), Zero);
179 }
180
181 #[test]
183 #[allow(clippy::default_constructed_unit_structs)]
184 fn test_default() {
185 assert_eq!(Zero::default(), Zero);
186 }
187
188 #[test]
189 fn test_signum() {
190 assert_eq!(Zero.signum(), Sign::Zero);
191 assert!(!Zero.is_positive());
192 assert!(!Zero.is_negative());
193 }
194
195 #[test]
198 fn test_non_zero() {
199 assert!(num_traits::Zero::is_zero(&Zero));
200 }
201
202 #[test]
203 fn test_negate() {
204 let mut value = Zero;
205 value.negate();
206 assert_eq!(value, Zero);
207 assert_eq!(-Zero, Zero);
208 }
209
210 #[test]
211 fn test_ord() {
212 assert_eq!(Zero.cmp(&Zero), Ordering::Equal);
213 assert_eq!(Zero.partial_cmp(&Zero), Some(Ordering::Equal));
214 assert_eq!(Zero, Zero);
215 }
216
217 #[test]
218 fn test_display() {
219 assert_eq!(Zero.to_string(), "0");
220 assert_eq!(format!("{Zero:?}"), "0");
221 }
222
223
224 #[test]
225 fn test_integer() {
226 assert_eq!(1 + Zero, 1);
227 assert_eq!(-1 + Zero, -1);
228 assert_eq!(894 * Zero, 0);
229 assert_eq!(-894 * &Zero, 0);
230 assert_eq!(0_u8 * &Zero, 0);
231 }
232}