1use std::fmt;
5use std::ops::{Add, AddAssign, Mul};
6
7use crate::{NonZero, Sign, Signed};
8
9#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
36pub enum Binary {
37 #[default]
39 Zero,
40 One,
42}
43
44impl NonZero for Binary {
46 #[inline]
47 fn is_not_zero(&self) -> bool {
48 match self {
49 Binary::Zero => false,
50 Binary::One => true,
51 }
52 }
53}
54
55impl Signed for Binary {
57 #[inline]
58 fn signum(&self) -> Sign {
59 match self {
60 Binary::Zero => Sign::Zero,
61 Binary::One => Sign::Positive,
62 }
63 }
64}
65
66impl fmt::Debug for Binary {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 fmt::Display::fmt(&self, f)
71 }
72}
73
74impl fmt::Display for Binary {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 f.write_str(match self {
77 Binary::Zero => "0",
78 Binary::One => "1",
79 })
80 }
81}
82
83impl Mul<Binary> for Binary {
86 type Output = Self;
87
88 #[inline]
89 fn mul(self, rhs: Binary) -> Self::Output {
90 match (self, rhs) {
91 (Binary::One, Binary::One) => Binary::One,
92 _ => Binary::Zero,
93 }
94 }
95}
96
97macro_rules! define_ops {
98 ($primitive:ident) => {
99 impl From<Binary> for $primitive {
100 fn from(other: Binary) -> Self {
101 From::from(&other)
102 }
103 }
104
105 impl From<&Binary> for $primitive {
106 fn from(other: &Binary) -> Self {
107 match other {
108 Binary::Zero => 0,
109 Binary::One => 1,
110 }
111 }
112 }
113
114 impl Add<Binary> for $primitive {
115 type Output = Self;
116
117 fn add(self, rhs: Binary) -> Self::Output {
118 Add::add(self, &rhs)
119 }
120 }
121
122 impl Add<&Binary> for $primitive {
123 type Output = Self;
124
125 fn add(self, rhs: &Binary) -> Self::Output {
126 match rhs {
127 Binary::Zero => self,
128 Binary::One => self + 1,
129 }
130 }
131 }
132
133 impl AddAssign<&Binary> for $primitive {
134 fn add_assign(&mut self, rhs: &Binary) {
135 match rhs {
136 Binary::Zero => {},
137 Binary::One => *self += 1,
138 }
139 }
140 }
141
142 impl Mul<Binary> for $primitive {
143 type Output = Self;
144
145 fn mul(self, rhs: Binary) -> Self::Output {
146 Mul::mul(self, &rhs)
147 }
148 }
149
150 impl Mul<&Binary> for $primitive {
151 type Output = Self;
152
153 fn mul(self, rhs: &Binary) -> Self::Output {
154 match rhs {
155 Binary::Zero => 0,
156 Binary::One => self,
157 }
158 }
159 }
160
161 impl Mul<&Binary> for &$primitive {
162 type Output = $primitive;
163
164 fn mul(self, rhs: &Binary) -> Self::Output {
165 match rhs {
166 Binary::Zero => 0,
167 Binary::One => *self,
168 }
169 }
170 }
171 }
172}
173
174define_ops!(i8);
175define_ops!(i16);
176define_ops!(i32);
177define_ops!(i64);
178define_ops!(i128);
179define_ops!(u8);
180define_ops!(u16);
181define_ops!(u32);
182define_ops!(u64);
183define_ops!(u128);
184
185#[cfg(test)]
186mod test {
187 use std::cmp::Ordering;
188
189 use crate::{NonZero, Sign, Signed};
190 use crate::fixed::Binary;
191
192 #[test]
193 fn test_binary() {
194 assert_eq!(Binary::One * Binary::One, Binary::One);
195 assert_eq!(Binary::One * Binary::Zero, Binary::Zero);
196 assert_eq!(Binary::Zero * Binary::Zero, Binary::Zero);
197 }
198
199 #[test]
200 fn test_default() {
201 assert_eq!(Binary::default(), Binary::Zero);
202 }
203
204 #[test]
205 fn test_signum() {
206 assert_eq!(Binary::Zero.signum(), Sign::Zero);
207 assert_eq!(Binary::One.signum(), Sign::Positive);
208 assert!(!Binary::Zero.is_positive());
209 assert!(Binary::One.is_positive());
210 assert!(!Binary::Zero.is_negative());
211 assert!(!Binary::One.is_negative());
212 }
213
214 #[test]
216 fn test_non_zero() {
217 assert!(!Binary::Zero.is_not_zero());
218 assert!(Binary::One.is_not_zero());
219 }
220
221 #[test]
223 fn test_ord() {
224 assert_eq!(Binary::Zero.cmp(&Binary::One), Ordering::Less);
225 assert_eq!(Binary::One.cmp(&Binary::Zero), Ordering::Greater);
226 assert!(Binary::Zero < Binary::One);
227
228 for a in [Binary::Zero, Binary::One] {
229 assert_eq!(a.cmp(&a), Ordering::Equal);
230 for b in [Binary::Zero, Binary::One] {
231 assert_eq!(a.partial_cmp(&b), Some(a.cmp(&b)));
232 assert_eq!(a.cmp(&b), b.cmp(&a).reverse());
233 assert_eq!(a == b, a.cmp(&b) == Ordering::Equal);
234 }
235 }
236 }
237
238 #[test]
239 fn test_display() {
240 assert_eq!(Binary::Zero.to_string(), "0");
241 assert_eq!(Binary::One.to_string(), "1");
242 assert_eq!(format!("{:?}", Binary::Zero), "0");
243 assert_eq!(format!("{:?}", Binary::One), "1");
244 }
245
246 #[test]
247 fn test_integer() {
248 assert_eq!(1 + Binary::One, 2);
249 assert_eq!(-1 + Binary::One, 0);
250 assert_eq!(894 * Binary::One, 894);
251 assert_eq!(-894 * &Binary::One, -894);
252 assert_eq!(0_u8 * &Binary::One, 0);
253
254 assert_eq!(1 + Binary::Zero, 1);
255 assert_eq!(-1 + Binary::Zero, -1);
256 assert_eq!(894 * Binary::Zero, 0);
257 assert_eq!(-894 * &Binary::Zero, 0);
258 assert_eq!(0_u8 * &Binary::Zero, 0);
259 }
260}