balanced_ternary/digit.rs
1//! ## Module: Balanced Ternary `Digit`
2//!
3//! This module defines the `Digit` type for the balanced ternary numeral system,
4//! along with its associated operations and functionality.
5//!
6//! ### Key Features
7//!
8//! - **`Digit` Type**: Represents a digit in the balanced ternary numeral system.
9//! - Possible values: `Neg` (-1), `Zero` (0), `Pos` (+1).
10//! - Provides utility functions for converting between characters, integers, and other formats.
11//! - **Arithmetic Operators**: Implements arithmetic operations for digits, including:
12//! - Negation (`Neg`) and Bitwise Not (`Not`).
13//! - Addition (`Add`) and Subtraction (`Sub`).
14//! - Multiplication (`Mul`) and Division (`Div`), with safe handling of divisors (division by zero panics).
15//! - **Logical Operators**: Supports bitwise logical operations (AND, OR, XOR) based on ternary logic rules.
16//! - **Custom Methods**: Additional utility methods implementing balanced ternary logic principles.
17//!
18//! ### Supported Use Cases
19//!
20//! - Arithmetic in balanced ternary numeral systems.
21//! - Logic operations in custom numeral systems.
22//! - Conversion between balanced ternary representation and more common formats like integers and characters.
23//!
24//! ## `Digit` type arithmetical and logical operations
25//!
26//! - `Neg` and `Not` for `Digit`: Negates the digit value, adhering to balanced ternary rules.
27//! - `Add<Digit>` for `Digit`: Adds two `Digit` values and returns a `Ternary`.
28//! - `Sub<Digit>` for `Digit`: Subtracts one `Digit` from another and returns a `Ternary`.
29//! - `Mul<Digit>` for `Digit`: Multiplies two `Digit` values and returns a `Digit`.
30//! - `Div<Digit>` for `Digit`: Divides one `Digit` by another and returns a `Digit`. Division by zero panics.
31//!
32//! ### Logical Operations for `Digit`
33//!
34//! The `Digit` type supports bitwise logical operations, which are implemented according to logical rules applicable to balanced ternary digits.
35//!
36//! #### `BitAnd` for `Digit`
37//!
38//! Performs a bitwise AND operation between two `Digit` values.
39//!
40//! - `Digit::Neg & other` → `Digit::Neg`
41//! - `Digit::Zero & Digit::Neg` → `Digit::Neg`
42//! - `Digit::Zero & other` → `Digit::Zero`
43//! - `Digit::Pos & other` → `other`
44//!
45//! #### `BitOr` for `Digit`
46//!
47//! Performs a bitwise OR operation between two `Digit` values.
48//!
49//! - `Digit::Neg | other` → `other`
50//! - `Digit::Zero | Digit::Pos` → `Digit::Pos`
51//! - `Digit::Zero | other` → `Digit::Zero`
52//! - `Digit::Pos | other` → `Digit::Pos`
53//!
54//! #### `BitXor` for `Digit`
55//!
56//! Performs a bitwise XOR operation between two `Digit` values.
57//!
58//! - `Digit::Neg ^ other` → `other`
59//! - `Digit::Zero ^ other` → `Digit::Zero`
60//! - `Digit::Pos ^ other` → `-other`
61
62use crate::Ternary;
63use alloc::vec;
64use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Sub};
65
66/// Represents a digit in the balanced ternary numeral system.
67///
68/// A digit can have one of three values:
69/// - `Neg` (-1): Represents the value -1 in the balanced ternary system.
70/// - `Zero` (0): Represents the value 0 in the balanced ternary system.
71/// - `Pos` (+1): Represents the value +1 in the balanced ternary system.
72///
73/// Provides utility functions for converting to/from characters, integers, and negation.
74#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
75pub enum Digit {
76 /// Represents -1
77 Neg,
78 /// Represents 0
79 Zero,
80 /// Represents +1
81 Pos,
82}
83
84impl Digit {
85 /// Converts the `Digit` into its character representation.
86 ///
87 /// - Returns:
88 /// - `-` for `Digit::Neg`
89 /// - `0` for `Digit::Zero`
90 /// - `+` for `Digit::Pos`
91 pub fn to_char(&self) -> char {
92 match self {
93 Digit::Neg => '-',
94 Digit::Zero => '0',
95 Digit::Pos => '+',
96 }
97 }
98
99 /// Creates a `Digit` from its character representation.
100 ///
101 /// - Accepts:
102 /// - `-` for `Digit::Neg`
103 /// - `0` for `Digit::Zero`
104 /// - `+` for `Digit::Pos`
105 /// - Panics if the input character is invalid.
106 pub fn from_char(c: char) -> Digit {
107 match c {
108 '-' => Digit::Neg,
109 '0' => Digit::Zero,
110 '+' => Digit::Pos,
111 _ => panic!("Invalid value. A Ternary must be either -, 0 or +."),
112 }
113 }
114
115 /// Converts the `Digit` into its integer representation.
116 ///
117 /// - Returns:
118 /// - -1 for `Digit::Neg`
119 /// - 0 for `Digit::Zero`
120 /// - 1 for `Digit::Pos`
121 pub fn to_i8(&self) -> i8 {
122 match self {
123 Digit::Neg => -1,
124 Digit::Zero => 0,
125 Digit::Pos => 1,
126 }
127 }
128
129 /// Creates a `Digit` from its integer representation.
130 ///
131 /// - Accepts:
132 /// - -1 for `Digit::Neg`
133 /// - 0 for `Digit::Zero`
134 /// - 1 for `Digit::Pos`
135 /// - Panics if the input integer is invalid.
136 pub fn from_i8(i: i8) -> Digit {
137 match i {
138 -1 => Digit::Neg,
139 0 => Digit::Zero,
140 1 => Digit::Pos,
141 _ => panic!("Invalid value. A Ternary must be either -1, 0 or +1."),
142 }
143 }
144 /// Returns the corresponding possible value of the current `Digit`.
145 ///
146 /// - Returns:
147 /// - `Digit::Neg` for `Digit::Neg`
148 /// - `Digit::Pos` for `Digit::Zero`
149 /// - `Digit::Pos` for `Digit::Pos`
150 pub fn possibly(self) -> Self {
151 match self {
152 Digit::Neg => Digit::Neg,
153 Digit::Zero => Digit::Pos,
154 Digit::Pos => Digit::Pos,
155 }
156 }
157
158 /// Determines the condition of necessity for the current `Digit`.
159 ///
160 /// - Returns:
161 /// - `Digit::Neg` for `Digit::Neg`
162 /// - `Digit::Neg` for `Digit::Zero`
163 /// - `Digit::Pos` for `Digit::Pos`
164 ///
165 /// This method is used to calculate necessity as part
166 /// of balanced ternary logic systems.
167 pub fn necessary(self) -> Self {
168 match self {
169 Digit::Neg => Digit::Neg,
170 Digit::Zero => Digit::Neg,
171 Digit::Pos => Digit::Pos,
172 }
173 }
174
175 /// Determines the condition of contingency for the current `Digit`.
176 ///
177 /// - Returns:
178 /// - `Digit::Neg` for `Digit::Neg`
179 /// - `Digit::Pos` for `Digit::Zero`
180 /// - `Digit::Neg` for `Digit::Pos`
181 ///
182 /// This method represents contingency in balanced ternary logic,
183 /// which defines the specific alternation of `Digit` values.
184 pub fn contingently(self) -> Self {
185 match self {
186 Digit::Neg => Digit::Neg,
187 Digit::Zero => Digit::Pos,
188 Digit::Pos => Digit::Neg,
189 }
190 }
191
192 /// Returns the absolute positive value of the current `Digit`.
193 ///
194 /// - Returns:
195 /// - `Digit::Pos` for `Digit::Neg`
196 /// - `Digit::Zero` for `Digit::Zero`
197 /// - `Digit::Pos` for `Digit::Pos`
198 pub fn absolute_positive(self) -> Self {
199 match self {
200 Digit::Neg => Digit::Pos,
201 Digit::Zero => Digit::Zero,
202 Digit::Pos => Digit::Pos,
203 }
204 }
205
206 /// Determines the strictly positive condition for the current `Digit`.
207 ///
208 /// - Returns:
209 /// - `Digit::Zero` for `Digit::Neg`
210 /// - `Digit::Zero` for `Digit::Zero`
211 /// - `Digit::Pos` for `Digit::Pos`
212 ///
213 /// This method is used to calculate strictly positive states
214 /// in association with ternary logic.
215 pub fn positive(self) -> Self {
216 match self {
217 Digit::Neg => Digit::Zero,
218 Digit::Zero => Digit::Zero,
219 Digit::Pos => Digit::Pos,
220 }
221 }
222
223 /// Determines the condition of non-negativity for the current `Digit`.
224 ///
225 /// - Returns:
226 /// - `Digit::Zero` for `Digit::Neg`
227 /// - `Digit::Pos` for `Digit::Zero`
228 /// - `Digit::Pos` for `Digit::Pos`
229 ///
230 /// This method is used to filter out negative conditions
231 /// in computations with balanced ternary representations.
232 pub fn not_negative(self) -> Self {
233 match self {
234 Digit::Neg => Digit::Zero,
235 Digit::Zero => Digit::Pos,
236 Digit::Pos => Digit::Pos,
237 }
238 }
239
240 /// Determines the condition of non-positivity for the current `Digit`.
241 ///
242 /// - Returns:
243 /// - `Digit::Neg` for `Digit::Neg`
244 /// - `Digit::Neg` for `Digit::Zero`
245 /// - `Digit::Zero` for `Digit::Pos`
246 ///
247 /// This method complements the `positive` condition and captures
248 /// states that are not strictly positive.
249 pub fn not_positive(self) -> Self {
250 match self {
251 Digit::Neg => Digit::Neg,
252 Digit::Zero => Digit::Neg,
253 Digit::Pos => Digit::Zero,
254 }
255 }
256
257 /// Determines the strictly negative condition for the current `Digit`.
258 ///
259 /// - Returns:
260 /// - `Digit::Neg` for `Digit::Neg`
261 /// - `Digit::Zero` for `Digit::Zero`
262 /// - `Digit::Zero` for `Digit::Pos`
263 ///
264 /// This method calculates strictly negative states
265 /// in association with ternary logic.
266 pub fn negative(self) -> Self {
267 match self {
268 Digit::Neg => Digit::Neg,
269 Digit::Zero => Digit::Zero,
270 Digit::Pos => Digit::Zero,
271 }
272 }
273
274 /// Returns the absolute negative value of the current `Digit`.
275 ///
276 /// - Returns:
277 /// - `Digit::Neg` for `Digit::Neg`
278 /// - `Digit::Zero` for `Digit::Zero`
279 /// - `Digit::Neg` for `Digit::Pos`
280 pub fn absolute_negative(self) -> Self {
281 match self {
282 Digit::Neg => Digit::Neg,
283 Digit::Zero => Digit::Zero,
284 Digit::Pos => Digit::Neg,
285 }
286 }
287
288 /// Performs Kleene implication with the current `Digit` as `self` and another `Digit`.
289 ///
290 /// - `self`: The antecedent of the implication.
291 /// - `other`: The consequent of the implication.
292 ///
293 /// - Returns:
294 /// - `Digit::Pos` when `self` is `Digit::Neg`.
295 /// - The positive condition of `other` when `self` is `Digit::Zero`.
296 /// - `other` when `self` is `Digit::Pos`.
297 ///
298 /// Implements Kleene ternary implication logic, which includes
299 /// determining the logical result based on antecedent and consequent.
300 pub fn k3_imply(self, other: Self) -> Self {
301 match self {
302 Digit::Neg => Digit::Pos,
303 Digit::Zero => other.positive(),
304 Digit::Pos => other,
305 }
306 }
307
308 /// Apply a ternary equivalence operation for the current `Digit` and another `Digit`.
309 ///
310 /// - `self`: The first operand of the equivalence operation.
311 /// - `other`: The second operand of the equivalence operation.
312 ///
313 /// - Returns:
314 /// - The negation of `other` when `self` is `Digit::Neg`.
315 /// - `Digit::Zero` when `self` is `Digit::Zero`.
316 /// - `other` when `self` is `Digit::Pos`.
317 ///
318 /// This method implements a ternary logic equivalence, which captures the relationship between
319 /// two balanced ternary `Digit`s based on their logical equivalence.
320 pub fn k3_equiv(self, other: Self) -> Self {
321 match self {
322 Digit::Neg => -other,
323 Digit::Zero => Digit::Zero,
324 Digit::Pos => other,
325 }
326 }
327
328 /// Performs a ternary AND operation for the current `Digit` and another `Digit`.
329 ///
330 /// - `self`: The first operand of the AND operation.
331 /// - `other`: The second operand of the AND operation.
332 ///
333 /// - Returns:
334 /// - `Digit::Neg` if `self` is `Digit::Neg` and `other` is not `Digit::Zero`.
335 /// - `Digit::Zero` if either `self` or `other` is `Digit::Zero`.
336 /// - `other` if `self` is `Digit::Pos`.
337 ///
338 /// This method implements Bochvar's internal three-valued logic in balanced ternary AND operation,
339 /// which evaluates the logical conjunction of two `Digit`s in the ternary logic system.
340 pub fn bi3_and(self, other: Self) -> Self {
341 match self {
342 Digit::Neg => other.absolute_negative(),
343 Digit::Zero => Digit::Zero,
344 Digit::Pos => other,
345 }
346 }
347
348 /// Performs a ternary OR operation for the current `Digit` and another `Digit`.
349 ///
350 /// - `self`: The first operand of the OR operation.
351 /// - `other`: The second operand of the OR operation.
352 ///
353 /// - Returns:
354 /// - `other` if `self` is `Digit::Neg`.
355 /// - `Digit::Zero` if `self` is `Digit::Zero`.
356 /// - `Digit::Pos` if `self` is `Digit::Pos` and `other` is not `Digit::Zero`.
357 ///
358 /// This method implements Bochvar's three-valued internal ternary logic for the OR operation,
359 /// determining the logical disjunction of two balanced ternary `Digit`s.
360 pub fn bi3_or(self, other: Self) -> Self {
361 match self {
362 Digit::Neg => other,
363 Digit::Zero => Digit::Zero,
364 Digit::Pos => other.absolute_positive(),
365 }
366 }
367
368 /// Performs Bochvar's internal three-valued implication with the current `Digit` as `self`
369 /// and another `Digit` as the consequent.
370 ///
371 /// - `self`: The antecedent of the implication.
372 /// - `other`: The consequent of the implication.
373 ///
374 /// - Returns:
375 /// - `Digit::Zero` if `self` is `Digit::Neg` and `other` is `Digit::Zero`.
376 /// - `Digit::Pos` if `self` is `Digit::Neg` and `other` is not `Digit::Zero`.
377 /// - `Digit::Zero` if `self` is `Digit::Zero`.
378 /// - `other` if `self` is `Digit::Pos`.
379 ///
380 /// This method implements Bochvar's internal implication logic, which evaluates
381 /// the logical consequence, between two balanced ternary `Digit`s in a manner
382 /// consistent with three-valued logic principles.
383 pub fn bi3_imply(self, other: Self) -> Self {
384 match self {
385 Digit::Neg => other.absolute_positive(),
386 Digit::Zero => Digit::Zero,
387 Digit::Pos => other,
388 }
389 }
390
391 /// Performs Łukasiewicz implication with the current `Digit` as `self` and another `Digit`.
392 ///
393 /// - `self`: The antecedent of the implication.
394 /// - `other`: The consequent of the implication.
395 ///
396 /// - Returns:
397 /// - `Digit::Pos` when `self` is `Digit::Neg`.
398 /// - The non-negative condition of `other` when `self` is `Digit::Zero`.
399 /// - `other` when `self` is `Digit::Pos`.
400 ///
401 /// Implements Łukasiewicz ternary implication logic, which
402 /// evaluates an alternative approach for implication compared to Kleene logic.
403 pub fn l3_imply(self, other: Self) -> Self {
404 match self {
405 Digit::Neg => Digit::Pos,
406 Digit::Zero => other.not_negative(),
407 Digit::Pos => other,
408 }
409 }
410
411 /// Performs RM3 implication with the current `Digit` as `self` and another `Digit`.
412 ///
413 /// - `self`: The antecedent of the implication.
414 /// - `other`: The consequent of the implication.
415 ///
416 /// - Returns:
417 /// - `Digit::Pos` when `self` is `Digit::Neg`.
418 /// - `other` when `self` is `Digit::Zero`.
419 /// - The necessary condition of `other` when `self` is `Digit::Pos`.
420 ///
421 /// Implements RM3 ternary implication logic, which defines a unique
422 /// perspective for implication operations in balanced ternary systems.
423 pub fn rm3_imply(self, other: Self) -> Self {
424 match self {
425 Digit::Neg => Digit::Pos,
426 Digit::Zero => other,
427 Digit::Pos => other.necessary(),
428 }
429 }
430
431 /// Performs HT implication with the current `Digit` as `self` and another `Digit`.
432 ///
433 /// - `self`: The antecedent of the implication.
434 /// - `other`: The consequent of the implication.
435 ///
436 /// - Returns:
437 /// - `Digit::Pos` when `self` is `Digit::Neg`.
438 /// - The possibility condition of `other` when `self` is `Digit::Zero`.
439 /// - `other` when `self` is `Digit::Pos`.
440 ///
441 /// This method computes HT ternary implication based on heuristic logic.
442 pub fn ht_imply(self, other: Self) -> Self {
443 match self {
444 Digit::Neg => Digit::Pos,
445 Digit::Zero => other.possibly(),
446 Digit::Pos => other,
447 }
448 }
449
450 /// Performs HT logical negation of the current `Digit`.
451 ///
452 /// - Returns:
453 /// - `Digit::Pos` when `self` is `Digit::Neg`.
454 /// - `Digit::Neg` when `self` is `Digit::Zero` or `Digit::Pos`.
455 ///
456 /// This method evaluates the HT negation result using heuristic ternary logic.
457 pub fn ht_not(self) -> Self {
458 match self {
459 Digit::Neg => Digit::Pos,
460 Digit::Zero => Digit::Neg,
461 Digit::Pos => Digit::Neg,
462 }
463 }
464
465 /// Converts the `Digit` to a `bool` in HT logic.
466 ///
467 /// - Returns:
468 /// - `true` when `self` is `Digit::Pos`.
469 /// - `false` when `self` is `Digit::Neg`.
470 ///
471 /// - Panics:
472 /// - Panics if `self` is `Digit::Zero`, as `Digit::Zero` cannot be directly
473 /// converted to a boolean value.
474 /// > To ensure `Pos` or `Neg` value, use one of :
475 /// > * [Digit::possibly]
476 /// > * [Digit::necessary]
477 /// > * [Digit::contingently]
478 /// > * [Digit::ht_not]
479 ///
480 pub fn ht_bool(self) -> bool {
481 match self {
482 Digit::Neg => false,
483 Digit::Zero => panic!(
484 "Cannot convert a Digit::Zero to a bool. \
485 Use Digit::possibly()->to_bool() or Digit::necessary()->to_bool() instead."
486 ),
487 Digit::Pos => true,
488 }
489 }
490
491 /// Performs Post's negation of the current `Digit`.
492 ///
493 /// - Returns:
494 /// - `Digit::Zero` when `self` is `Digit::Neg`.
495 /// - `Digit::Pos` when `self` is `Digit::Zero`.
496 /// - `Digit::Neg` when `self` is `Digit::Pos`.
497 ///
498 /// This method evaluates the negation based on Post's logic in ternary systems,
499 /// which differs from standard negation logic.
500 pub fn post(self) -> Self {
501 match self {
502 Digit::Neg => Digit::Zero,
503 Digit::Zero => Digit::Pos,
504 Digit::Pos => Digit::Neg,
505 }
506 }
507
508 /// Performs the inverse operation from the Post's negation of the current `Digit`.
509 ///
510 /// - Returns:
511 /// - `Digit::Pos` when `self` is `Digit::Neg`.
512 /// - `Digit::Neg` when `self` is `Digit::Zero`.
513 /// - `Digit::Zero` when `self` is `Digit::Pos`.
514 pub fn pre(self) -> Self {
515 match self {
516 Digit::Neg => Digit::Pos,
517 Digit::Zero => Digit::Neg,
518 Digit::Pos => Digit::Zero,
519 }
520 }
521
522
523 /// This method maps this `Digit` value to its corresponding unbalanced ternary
524 /// integer representation.
525 ///
526 /// - Returns:
527 /// - `0` for `Digit::Neg`.
528 /// - `1` for `Digit::Zero`.
529 /// - `2` for `Digit::Pos`.
530 ///
531 pub fn to_unbalanced(self) -> u8 {
532 match self {
533 Digit::Neg => 0,
534 Digit::Zero => 1,
535 Digit::Pos => 2,
536 }
537 }
538
539 /// Creates a `Digit` from an unbalanced ternary integer representation.
540 ///
541 /// # Arguments:
542 /// - `u`: An unsigned 8-bit integer representing an unbalanced ternary value.
543 ///
544 /// # Returns:
545 /// - `Digit::Neg` for `0`.
546 /// - `Digit::Zero` for `1`.
547 /// - `Digit::Pos` for `2`.
548 ///
549 /// # Panics:
550 /// - Panics if the provided value is not `0`, `1`, or `2`, as these are the
551 /// only valid representations of unbalanced ternary values.
552 pub fn from_unbalanced(u: u8) -> Digit {
553 match u {
554 0 => Digit::Neg,
555 1 => Digit::Zero,
556 2 => Digit::Pos,
557 _ => panic!("Invalid value. A unbalanced ternary value must be either 0, 1 or 2."),
558 }
559 }
560}
561
562impl Neg for Digit {
563 type Output = Self;
564
565 /// Returns the negation of the `Digit`.
566 ///
567 /// - `Digit::Neg` becomes `Digit::Pos`
568 /// - `Digit::Pos` becomes `Digit::Neg`
569 /// - `Digit::Zero` remains `Digit::Zero`
570 fn neg(self) -> Self::Output {
571 match self {
572 Digit::Neg => Digit::Pos,
573 Digit::Zero => Digit::Zero,
574 Digit::Pos => Digit::Neg,
575 }
576 }
577}
578
579impl Not for Digit {
580 type Output = Self;
581 fn not(self) -> Self::Output {
582 -self
583 }
584}
585
586impl Add<Digit> for Digit {
587 type Output = Ternary;
588
589 /// Adds two `Digit` values together and returns a `Ternary` result.
590 ///
591 /// - The rules for addition are based on ternary arithmetic:
592 /// - For `Digit::Neg`:
593 /// - Adding `Digit::Neg` results in "underflow" (`Ternary::parse("-+")`).
594 /// - Adding `Digit::Zero` keeps the result as `Digit::Neg` (`Ternary::parse("-")`).
595 /// - Adding `Digit::Pos` results in a balance (`Ternary::parse("0")`).
596 /// - For `Digit::Zero`:
597 /// - Simply returns the other operand wrapped in a `Ternary` object.
598 /// - For `Digit::Pos`:
599 /// - Adding `Digit::Neg` results in balance (`Ternary::parse("0")`).
600 /// - Adding `Digit::Zero` keeps the result as `Digit::Pos` (`Ternary::parse("+")`).
601 /// - Adding `Digit::Pos` results in "overflow" (`Ternary::parse("+-")`).
602 ///
603 /// - Returns:
604 /// - A `Ternary` instance that holds the result of the addition.
605 ///
606 /// - Panics:
607 /// - This method does not panic under any circumstances.
608 fn add(self, other: Digit) -> Self::Output {
609 match self {
610 Digit::Neg => match other {
611 Digit::Neg => Ternary::parse("-+"),
612 Digit::Zero => Ternary::parse("-"),
613 Digit::Pos => Ternary::parse("0"),
614 },
615 Digit::Zero => Ternary::new(vec![other]),
616 Digit::Pos => match other {
617 Digit::Neg => Ternary::parse("0"),
618 Digit::Zero => Ternary::parse("+"),
619 Digit::Pos => Ternary::parse("+-"),
620 },
621 }
622 }
623}
624
625impl Sub<Digit> for Digit {
626 type Output = Ternary;
627
628 /// Subtracts two `Digit` values and returns a `Ternary` result.
629 ///
630 /// - The rules for subtraction are based on ternary arithmetic:
631 /// - For `Digit::Neg`:
632 /// - Subtracting `Digit::Neg` results in balance (`Ternary::parse("0")`).
633 /// - Subtracting `Digit::Zero` keeps the result as `Digit::Neg` (`Ternary::parse("-")`).
634 /// - Subtracting `Digit::Pos` results in "underflow" (`Ternary::parse("-+")`).
635 /// - For `Digit::Zero`:
636 /// - Simply negates the other operand and returns it wrapped in a `Ternary` object.
637 /// - For `Digit::Pos`:
638 /// - Subtracting `Digit::Neg` results in "overflow" (`Ternary::parse("+-")`).
639 /// - Subtracting `Digit::Zero` keeps the result as `Digit::Pos` (`Ternary::parse("+")`).
640 /// - Subtracting `Digit::Pos` results in balance (`Ternary::parse("0")`).
641 ///
642 /// - Returns:
643 /// - A `Ternary` instance that holds the result of the subtraction.
644 ///
645 /// - Panics:
646 /// - This method does not panic under any circumstances.
647 fn sub(self, other: Digit) -> Self::Output {
648 match self {
649 Digit::Neg => match other {
650 Digit::Neg => Ternary::parse("0"),
651 Digit::Zero => Ternary::parse("-"),
652 Digit::Pos => Ternary::parse("-+"),
653 },
654 Digit::Zero => Ternary::new(vec![-other]),
655 Digit::Pos => match other {
656 Digit::Neg => Ternary::parse("+-"),
657 Digit::Zero => Ternary::parse("+"),
658 Digit::Pos => Ternary::parse("0"),
659 },
660 }
661 }
662}
663
664impl Mul<Digit> for Digit {
665 type Output = Digit;
666
667 /// Multiplies two `Digit` values together and returns the product as a `Digit`.
668 ///
669 /// - The rules for multiplication in this implementation are straightforward:
670 /// - `Digit::Neg` multiplied by:
671 /// - `Digit::Neg` results in `Digit::Pos`.
672 /// - `Digit::Zero` results in `Digit::Zero`.
673 /// - `Digit::Pos` results in `Digit::Neg`.
674 /// - `Digit::Zero` multiplied by any `Digit` always results in `Digit::Zero`.
675 /// - `Digit::Pos` multiplied by:
676 /// - `Digit::Neg` results in `Digit::Neg`.
677 /// - `Digit::Zero` results in `Digit::Zero`.
678 /// - `Digit::Pos` results in `Digit::Pos`.
679 ///
680 /// - Returns:
681 /// - A `Digit` instance representing the result of the multiplication.
682 fn mul(self, other: Digit) -> Self::Output {
683 match self {
684 Digit::Neg => -other,
685 Digit::Zero => Digit::Zero,
686 Digit::Pos => other,
687 }
688 }
689}
690
691impl Div<Digit> for Digit {
692 type Output = Digit;
693
694 /// Divides one `Digit` value by another and returns the result as a `Digit`.
695 ///
696 /// # Rules for division:
697 /// - For `Digit::Neg`:
698 /// - Dividing `Digit::Neg` by `Digit::Neg` results in `Digit::Pos`.
699 /// - Dividing `Digit::Neg` by `Digit::Zero` will panic with "Cannot divide by zero."
700 /// - Dividing `Digit::Neg` by `Digit::Pos` results in `Digit::Neg`.
701 /// - For `Digit::Zero`:
702 /// - Dividing `Digit::Zero` by `Digit::Neg` results in `Digit::Zero`.
703 /// - Dividing `Digit::Zero` by `Digit::Zero` will panic with "Cannot divide by zero."
704 /// - Dividing `Digit::Zero` by `Digit::Pos` results in `Digit::Zero`.
705 /// - For `Digit::Pos`:
706 /// - Dividing `Digit::Pos` by `Digit::Neg` results in `Digit::Neg`.
707 /// - Dividing `Digit::Pos` by `Digit::Zero` will panic with "Cannot divide by zero."
708 /// - Dividing `Digit::Pos` by `Digit::Pos` results in `Digit::Pos`.
709 ///
710 /// # Returns:
711 /// - A `Digit` value representing the result of the division.
712 ///
713 /// # Panics:
714 /// - Panics with "Cannot divide by zero." if the `other` operand is `Digit::Zero`.
715 fn div(self, other: Digit) -> Self::Output {
716 match self {
717 Digit::Neg => match other {
718 Digit::Neg => Digit::Pos,
719 Digit::Zero => panic!("Cannot divide by zero."),
720 Digit::Pos => Digit::Neg,
721 },
722 Digit::Zero => match other {
723 Digit::Neg => Digit::Zero,
724 Digit::Zero => panic!("Cannot divide by zero."),
725 Digit::Pos => Digit::Zero,
726 },
727 Digit::Pos => match other {
728 Digit::Neg => Digit::Neg,
729 Digit::Zero => panic!("Cannot divide by zero."),
730 Digit::Pos => Digit::Pos,
731 },
732 }
733 }
734}
735
736impl BitAnd for Digit {
737 type Output = Self;
738
739 /// Performs a bitwise AND operation between two `Digit` values and returns the result.
740 ///
741 /// - The rules for the bitwise AND (`&`) operation are:
742 /// - If `self` is `Digit::Neg`, the result is always `Digit::Neg`.
743 /// - If `self` is `Digit::Zero`, the result depends on the value of `other`:
744 /// - `Digit::Neg` results in `Digit::Neg`.
745 /// - Otherwise, the result is `Digit::Zero`.
746 /// - If `self` is `Digit::Pos`, the result is simply `other`.
747 ///
748 /// # Returns:
749 /// - A `Digit` value that is the result of the bitwise AND operation.
750 ///
751 /// # Examples:
752 /// ```
753 /// use balanced_ternary::Digit;
754 /// use Digit::{Neg, Pos, Zero};
755 ///
756 /// assert_eq!(Neg & Pos, Neg);
757 /// assert_eq!(Zero & Neg, Neg);
758 /// assert_eq!(Zero & Pos, Zero);
759 /// assert_eq!(Pos & Zero, Zero);
760 /// ```
761 fn bitand(self, other: Self) -> Self::Output {
762 match self {
763 Digit::Neg => Digit::Neg,
764 Digit::Zero => other.negative(),
765 Digit::Pos => other,
766 }
767 }
768}
769
770impl BitOr for Digit {
771 type Output = Self;
772
773 /// Performs a bitwise OR operation between two `Digit` values and returns the result.
774 ///
775 /// - The rules for the bitwise OR (`|`) operation are as follows:
776 /// - If `self` is `Digit::Neg`, the result is always the value of `other`.
777 /// - If `self` is `Digit::Zero`, the result depends on the value of `other`:
778 /// - `Digit::Pos` results in `Digit::Pos`.
779 /// - Otherwise, the result is `Digit::Zero`.
780 /// - If `self` is `Digit::Pos`, the result is always `Digit::Pos`.
781 ///
782 /// # Returns:
783 /// - A `Digit` value that is the result of the bitwise OR operation.
784 ///
785 /// # Examples:
786 /// ```
787 /// use balanced_ternary::Digit;
788 /// use Digit::{Neg, Pos, Zero};
789 ///
790 /// assert_eq!(Neg | Pos, Pos);
791 /// assert_eq!(Zero | Neg, Zero);
792 /// assert_eq!(Zero | Pos, Pos);
793 /// assert_eq!(Pos | Zero, Pos);
794 /// ```
795 fn bitor(self, other: Self) -> Self::Output {
796 match self {
797 Digit::Neg => other,
798 Digit::Zero => other.positive(),
799 Digit::Pos => Digit::Pos,
800 }
801 }
802}
803
804impl BitXor for Digit {
805 type Output = Self;
806
807 /// Performs a bitwise XOR (exclusive OR) operation between two `Digit` values.
808 ///
809 /// - The rules for the bitwise XOR (`^`) operation are as follows:
810 /// - If `self` is `Digit::Neg`, the result is always the value of `rhs`.
811 /// - If `self` is `Digit::Zero`, the result is always `Digit::Zero`.
812 /// - If `self` is `Digit::Pos`, the result is the negation of `rhs`:
813 /// - `Digit::Neg` becomes `Digit::Pos`.
814 /// - `Digit::Zero` becomes `Digit::Zero`.
815 /// - `Digit::Pos` becomes `Digit::Neg`.
816 ///
817 /// # Returns:
818 /// - A `Digit` value that is the result of the bitwise XOR operation.
819 ///
820 /// # Examples:
821 /// ```
822 /// use balanced_ternary::Digit;
823 /// use Digit::{Neg, Pos, Zero};
824 ///
825 /// assert_eq!(Neg ^ Pos, Pos);
826 /// assert_eq!(Zero ^ Neg, Zero);
827 /// assert_eq!(Pos ^ Pos, Neg);
828 /// ```
829 fn bitxor(self, rhs: Self) -> Self::Output {
830 match self {
831 Digit::Neg => rhs,
832 Digit::Zero => Digit::Zero,
833 Digit::Pos => -rhs,
834 }
835 }
836}