1use crate::{Digit, Ternary};
85use alloc::vec;
86use alloc::vec::Vec;
87use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Sub};
88
89impl Neg for Digit {
90 type Output = Self;
91
92 fn neg(self) -> Self::Output {
98 match self {
99 Digit::Neg => Digit::Pos,
100 Digit::Zero => Digit::Zero,
101 Digit::Pos => Digit::Neg,
102 }
103 }
104}
105
106impl Add<Digit> for Digit {
107 type Output = Ternary;
108 fn add(self, other: Digit) -> Self::Output {
109 match self {
110 Digit::Neg => match other {
111 Digit::Neg => Ternary::parse("-+"),
112 Digit::Zero => Ternary::parse("-"),
113 Digit::Pos => Ternary::parse("0"),
114 },
115 Digit::Zero => Ternary::new(vec![other]),
116 Digit::Pos => match other {
117 Digit::Neg => Ternary::parse("0"),
118 Digit::Zero => Ternary::parse("+"),
119 Digit::Pos => Ternary::parse("+-"),
120 },
121 }
122 }
123}
124
125impl Sub<Digit> for Digit {
126 type Output = Ternary;
127 fn sub(self, other: Digit) -> Self::Output {
128 match self {
129 Digit::Neg => match other {
130 Digit::Neg => Ternary::parse("0"),
131 Digit::Zero => Ternary::parse("-"),
132 Digit::Pos => Ternary::parse("-+"),
133 },
134 Digit::Zero => Ternary::new(vec![-other]),
135 Digit::Pos => match other {
136 Digit::Neg => Ternary::parse("+-"),
137 Digit::Zero => Ternary::parse("+"),
138 Digit::Pos => Ternary::parse("0"),
139 },
140 }
141 }
142}
143
144impl Mul<Digit> for Digit {
145 type Output = Digit;
146
147 fn mul(self, other: Digit) -> Self::Output {
148 match self {
149 Digit::Neg => -other,
150 Digit::Zero => Digit::Zero,
151 Digit::Pos => other,
152 }
153 }
154}
155
156impl Div<Digit> for Digit {
157 type Output = Digit;
158
159 fn div(self, other: Digit) -> Self::Output {
160 match self {
161 Digit::Neg => match other {
162 Digit::Neg => Digit::Pos,
163 Digit::Zero => panic!("Cannot divide by zero."),
164 Digit::Pos => Digit::Neg,
165 },
166 Digit::Zero => match other {
167 Digit::Neg => Digit::Zero,
168 Digit::Zero => panic!("Cannot divide by zero."),
169 Digit::Pos => Digit::Zero,
170 },
171 Digit::Pos => match other {
172 Digit::Neg => Digit::Neg,
173 Digit::Zero => panic!("Cannot divide by zero."),
174 Digit::Pos => Digit::Pos,
175 },
176 }
177 }
178}
179
180impl BitAnd for Digit {
181 type Output = Self;
182 fn bitand(self, other: Self) -> Self::Output {
183 match self {
184 Digit::Neg => Digit::Neg,
185 Digit::Zero => match other {
186 Digit::Neg => Digit::Neg,
187 _ => Digit::Zero,
188 },
189 Digit::Pos => other,
190 }
191 }
192}
193
194impl BitOr for Digit {
195 type Output = Self;
196 fn bitor(self, other: Self) -> Self::Output {
197 match self {
198 Digit::Neg => other,
199 Digit::Zero => match other {
200 Digit::Pos => Digit::Pos,
201 _ => Digit::Zero,
202 },
203 Digit::Pos => Digit::Pos,
204 }
205 }
206}
207
208impl BitXor for Digit {
209 type Output = Self;
210
211 fn bitxor(self, rhs: Self) -> Self::Output {
212 match self {
213 Digit::Neg => rhs,
214 Digit::Zero => Digit::Zero,
215 Digit::Pos => -rhs,
216 }
217 }
218}
219
220impl Neg for &Ternary {
221 type Output = Ternary;
222
223 fn neg(self) -> Self::Output {
227 let mut repr = Ternary::new(vec![]);
228 for digit in self.digits.iter() {
229 repr.digits.push(-*digit);
230 }
231 repr
232 }
233}
234
235impl Add<&Ternary> for &Ternary {
236 type Output = Ternary;
237
238 fn add(self, rhs: &Ternary) -> Self::Output {
239 Ternary::from_dec(
240 self.to_dec()
241 .checked_add(rhs.to_dec())
242 .expect("Overflow in addition."),
243 )
244 }
245}
246
247impl Sub<&Ternary> for &Ternary {
248 type Output = Ternary;
249
250 fn sub(self, rhs: &Ternary) -> Self::Output {
251 Ternary::from_dec(
252 self.to_dec()
253 .checked_sub(rhs.to_dec())
254 .expect("Overflow in subtraction."),
255 )
256 }
257}
258
259impl Mul<&Ternary> for &Ternary {
260 type Output = Ternary;
261
262 fn mul(self, rhs: &Ternary) -> Self::Output {
263 Ternary::from_dec(
264 self.to_dec()
265 .checked_mul(rhs.to_dec())
266 .expect("Overflow in multiplication."),
267 )
268 }
269}
270
271impl Div<&Ternary> for &Ternary {
272 type Output = Ternary;
273
274 fn div(self, rhs: &Ternary) -> Self::Output {
275 Ternary::from_dec(
276 self.to_dec()
277 .checked_div(rhs.to_dec())
278 .expect("Overflow in division or division by zero."),
279 )
280 }
281}
282
283impl BitAnd<&Ternary> for &Ternary {
284 type Output = Ternary;
285
286 fn bitand(self, rhs: &Ternary) -> Self::Output {
287 if self.log() < rhs.log() {
288 return rhs & self;
289 }
290 let mut digits = Vec::new();
291 for (i, d) in self.digits.iter().rev().enumerate() {
292 let other = rhs.get_digit(i).unwrap_or(&Digit::Zero);
293 digits.push(*d & *other);
294 }
295 digits.reverse();
296 Ternary::new(digits)
297 }
298}
299
300impl BitOr<&Ternary> for &Ternary {
301 type Output = Ternary;
302
303 fn bitor(self, rhs: &Ternary) -> Self::Output {
304 if self.log() < rhs.log() {
305 return rhs | self;
306 }
307 let mut digits = Vec::new();
308 for (i, d) in self.digits.iter().rev().enumerate() {
309 let other = rhs.get_digit(i).unwrap_or(&Digit::Zero);
310 digits.push(*d | *other);
311 }
312 digits.reverse();
313 Ternary::new(digits)
314 }
315}
316
317impl BitXor<&Ternary> for &Ternary {
318 type Output = Ternary;
319
320 fn bitxor(self, rhs: &Ternary) -> Self::Output {
321 if self.log() < rhs.log() {
322 return rhs ^ self;
323 }
324 let mut digits = Vec::new();
325 for (i, d) in self.digits.iter().rev().enumerate() {
326 let other = rhs.get_digit(i).unwrap_or(&Digit::Zero);
327 digits.push(*d ^ *other);
328 }
329 digits.reverse();
330 Ternary::new(digits)
331 }
332}
333
334#[cfg(test)]
335#[test]
336fn test_ternary_ops() {
337 use alloc::string::ToString;
338
339 let repr9 = Ternary::parse("+00");
340 let repr4 = Ternary::parse("++");
341 let repr13 = &repr9 + &repr4;
342 let repr17 = &repr13 + &repr4;
343 let repr34 = &repr17 + &repr17;
344
345 assert_eq!(repr13.to_string(), "+++");
346 assert_eq!(repr17.to_string(), "+-0-");
347 assert_eq!(repr34.to_string(), "++-+");
348
349 let repr30 = &repr34 - &repr4;
350 assert_eq!(repr30.to_dec(), 30);
351 assert_eq!(repr30.to_string(), "+0+0");
352
353 let repr120 = &repr30 * &repr4;
354 assert_eq!(repr120.to_dec(), 120);
355 assert_eq!(repr120.to_string(), "++++0");
356
357 let repr_neg120 = -&repr120;
358 assert_eq!(repr_neg120.to_dec(), -120);
359 assert_eq!(repr_neg120.to_string(), "----0");
360
361 let bitwise = &Ternary::parse("++00") & &Ternary::parse("0000");
362 assert_eq!(bitwise.to_string(), "0000");
363
364 let bitwise = &Ternary::parse("++00") & &Ternary::parse("0+00");
365 assert_eq!(bitwise.to_string(), "0+00");
366
367 let bitwise = &Ternary::parse("+000") | &Ternary::parse("000-");
368 assert_eq!(bitwise.to_string(), "+000");
369
370
371 let bitwise = &Ternary::parse("+000") & &Ternary::parse("000-");
372 assert_eq!(bitwise.to_string(), "000-");
373
374 let bitwise = &Ternary::parse("+000") | &Ternary::parse("000+");
375 assert_eq!(bitwise.to_string(), "+00+");
376}