balanced_ternary/
operations.rs1use crate::concepts::DigitOperate;
32use crate::{Digit, Ternary};
33use alloc::vec;
34use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Sub};
35
36impl Neg for &Ternary {
37 type Output = Ternary;
38
39 fn neg(self) -> Self::Output {
43 let mut repr = Ternary::new(vec![]);
44 for digit in self.digits.iter() {
45 repr.digits.push(-*digit);
46 }
47 repr
48 }
49}
50
51impl Add<&Ternary> for &Ternary {
52 type Output = Ternary;
53
54 fn add(self, rhs: &Ternary) -> Self::Output {
55 Ternary::from_dec(
56 self.to_dec()
57 .checked_add(rhs.to_dec())
58 .expect("Overflow in addition."),
59 )
60 }
61}
62
63impl Add<Digit> for &Ternary {
64 type Output = Ternary;
65
66 fn add(self, rhs: Digit) -> Self::Output {
67 Ternary::from_dec(
68 self.to_dec()
69 .checked_add(rhs.to_i8() as i64)
70 .expect("Overflow in addition."),
71 )
72 }
73}
74
75impl Sub<&Ternary> for &Ternary {
76 type Output = Ternary;
77
78 fn sub(self, rhs: &Ternary) -> Self::Output {
79 Ternary::from_dec(
80 self.to_dec()
81 .checked_sub(rhs.to_dec())
82 .expect("Overflow in subtraction."),
83 )
84 }
85}
86
87impl Sub<Digit> for &Ternary {
88 type Output = Ternary;
89 fn sub(self, rhs: Digit) -> Self::Output {
90 Ternary::from_dec(
91 self.to_dec()
92 .checked_sub(rhs.to_i8() as i64)
93 .expect("Overflow in subtraction."),
94 )
95 }
96}
97
98impl Mul<&Ternary> for &Ternary {
99 type Output = Ternary;
100
101 fn mul(self, rhs: &Ternary) -> Self::Output {
102 Ternary::from_dec(
103 self.to_dec()
104 .checked_mul(rhs.to_dec())
105 .expect("Overflow in multiplication."),
106 )
107 }
108}
109
110impl Div<&Ternary> for &Ternary {
111 type Output = Ternary;
112
113 fn div(self, rhs: &Ternary) -> Self::Output {
114 Ternary::from_dec(
115 self.to_dec()
116 .checked_div(rhs.to_dec())
117 .expect("Overflow in division or division by zero."),
118 )
119 }
120}
121
122impl BitAnd<&Ternary> for &Ternary {
123 type Output = Ternary;
124
125 fn bitand(self, rhs: &Ternary) -> Self::Output {
126 self.each_zip(Digit::bitand, rhs.clone())
127 }
128}
129
130impl BitOr<&Ternary> for &Ternary {
131 type Output = Ternary;
132
133 fn bitor(self, rhs: &Ternary) -> Self::Output {
134 self.each_zip(Digit::bitor, rhs.clone())
135 }
136}
137
138impl BitXor<&Ternary> for &Ternary {
139 type Output = Ternary;
140
141 fn bitxor(self, rhs: &Ternary) -> Self::Output {
142 self.each_zip(Digit::bitxor, rhs.clone())
143 }
144}
145
146impl Not for &Ternary {
147 type Output = Ternary;
148 fn not(self) -> Self::Output {
149 -self
150 }
151}
152
153#[cfg(test)]
154#[test]
155fn test_ternary_ops() {
156 use alloc::string::ToString;
157
158 let repr9 = Ternary::parse("+00");
159 let repr4 = Ternary::parse("++");
160 let repr13 = &repr9 + &repr4;
161 let repr17 = &repr13 + &repr4;
162 let repr34 = &repr17 + &repr17;
163
164 assert_eq!(repr13.to_string(), "+++");
165 assert_eq!(repr17.to_string(), "+-0-");
166 assert_eq!(repr34.to_string(), "++-+");
167
168 let repr30 = &repr34 - &repr4;
169 assert_eq!(repr30.to_dec(), 30);
170 assert_eq!(repr30.to_string(), "+0+0");
171
172 let repr120 = &repr30 * &repr4;
173 assert_eq!(repr120.to_dec(), 120);
174 assert_eq!(repr120.to_string(), "++++0");
175
176 let repr_neg120 = -&repr120;
177 assert_eq!(repr_neg120.to_dec(), -120);
178 assert_eq!(repr_neg120.to_string(), "----0");
179
180 let bitwise = &Ternary::parse("++00") & &Ternary::parse("0000");
181 assert_eq!(bitwise.to_string(), "0000");
182
183 let bitwise = &Ternary::parse("++00") & &Ternary::parse("0+00");
184 assert_eq!(bitwise.to_string(), "0+00");
185
186 let bitwise = &Ternary::parse("+000") | &Ternary::parse("000-");
187 assert_eq!(bitwise.to_string(), "+000");
188
189 let bitwise = &Ternary::parse("+000") & &Ternary::parse("000-");
190 assert_eq!(bitwise.to_string(), "000-");
191
192 let bitwise = &Ternary::parse("+000") | &Ternary::parse("000+");
193 assert_eq!(bitwise.to_string(), "+00+");
194}