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}