1use std::fmt;
5use std::ops::{Add, AddAssign, Mul};
6
7use crate::NonZero;
8
9#[derive(Eq, PartialEq, Copy, Clone, Debug, Default)]
17#[allow(missing_docs)]
18pub enum Binary {
19 #[default]
20 Zero,
21 One,
22}
23
24impl NonZero for Binary {
25 fn is_not_zero(&self) -> bool {
26 match self {
27 Binary::Zero => false,
28 Binary::One => true,
29 }
30 }
31}
32
33impl num_traits::Zero for Binary {
34 fn zero() -> Self {
35 Self::Zero
36 }
37
38 fn is_zero(&self) -> bool {
39 self == &Binary::Zero
40 }
41}
42
43impl num_traits::One for Binary {
44 fn one() -> Self {
45 Self::One
46 }
47}
48
49impl fmt::Display for Binary {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 f.write_str(match self {
52 Binary::Zero => "0",
53 Binary::One => "1",
54 })
55 }
56}
57
58impl Add<Binary> for Binary {
59 type Output = Self;
60
61 fn add(self, rhs: Binary) -> Self::Output {
62 match (self, rhs) {
63 (Binary::Zero, Binary::Zero) => Binary::Zero,
64 (Binary::Zero, Binary::One) => Binary::One,
65 (Binary::One, Binary::Zero) => Binary::One,
66 (Binary::One, Binary::One) => Binary::Zero,
67 }
68 }
69}
70
71impl Mul<Binary> for Binary {
72 type Output = Self;
73
74 fn mul(self, rhs: Binary) -> Self::Output {
75 match (self, rhs) {
76 (Binary::One, Binary::One) => Binary::One,
77 _ => Binary::Zero,
78 }
79 }
80}
81
82macro_rules! define_ops {
83 ($primitive:ident) => {
84 impl From<Binary> for $primitive {
85 fn from(other: Binary) -> Self {
86 From::from(&other)
87 }
88 }
89
90 impl From<&Binary> for $primitive {
91 fn from(other: &Binary) -> Self {
92 match other {
93 Binary::Zero => 0,
94 Binary::One => 1,
95 }
96 }
97 }
98
99 impl Add<Binary> for $primitive {
100 type Output = Self;
101
102 fn add(self, rhs: Binary) -> Self::Output {
103 Add::add(self, &rhs)
104 }
105 }
106
107 impl Add<&Binary> for $primitive {
108 type Output = Self;
109
110 fn add(self, rhs: &Binary) -> Self::Output {
111 match rhs {
112 Binary::Zero => self,
113 Binary::One => self + 1,
114 }
115 }
116 }
117
118 impl AddAssign<&Binary> for $primitive {
119 fn add_assign(&mut self, rhs: &Binary) {
120 match rhs {
121 Binary::Zero => {},
122 Binary::One => *self += 1,
123 }
124 }
125 }
126
127 impl Mul<Binary> for $primitive {
128 type Output = Self;
129
130 fn mul(self, rhs: Binary) -> Self::Output {
131 Mul::mul(self, &rhs)
132 }
133 }
134
135 impl Mul<&Binary> for $primitive {
136 type Output = Self;
137
138 fn mul(self, rhs: &Binary) -> Self::Output {
139 match rhs {
140 Binary::Zero => 0,
141 Binary::One => self,
142 }
143 }
144 }
145
146 impl Mul<&Binary> for &$primitive {
147 type Output = $primitive;
148
149 fn mul(self, rhs: &Binary) -> Self::Output {
150 match rhs {
151 Binary::Zero => 0,
152 Binary::One => *self,
153 }
154 }
155 }
156 }
157}
158
159define_ops!(i8);
160define_ops!(i16);
161define_ops!(i32);
162define_ops!(i64);
163define_ops!(i128);
164define_ops!(u8);
165define_ops!(u16);
166define_ops!(u32);
167define_ops!(u64);
168define_ops!(u128);
169
170#[cfg(test)]
171mod test {
172 use crate::Binary;
173
174 #[test]
175 fn test_integer() {
176 assert_eq!(1 + Binary::One, 2);
177 assert_eq!(-1 + Binary::One, 0);
178 assert_eq!(894 * Binary::One, 894);
179 assert_eq!(-894 * &Binary::One, -894);
180 assert_eq!(0_u8 * &Binary::One, 0);
181
182 assert_eq!(1 + Binary::Zero, 1);
183 assert_eq!(-1 + Binary::Zero, -1);
184 assert_eq!(894 * Binary::Zero, 0);
185 assert_eq!(-894 * &Binary::Zero, 0);
186 assert_eq!(0_u8 * &Binary::Zero, 0);
187 }
188}