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