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    /// Determines the condition of non-negativity for the current `Digit`.
193    ///
194    /// - Returns:
195    ///     - `Digit::Zero` for `Digit::Neg`
196    ///     - `Digit::Pos` for `Digit::Zero`
197    ///     - `Digit::Pos` for `Digit::Pos`
198    ///
199    /// This method is used to filter out negative conditions
200    /// in computations with balanced ternary representations.
201    pub fn not_negative(&self) -> Self {
202        match self {
203            Digit::Neg => Digit::Zero,
204            Digit::Zero => Digit::Pos,
205            Digit::Pos => Digit::Pos,
206        }
207    }
208
209    /// Determines the strictly positive condition for the current `Digit`.
210    ///
211    /// - Returns:
212    ///     - `Digit::Zero` for `Digit::Neg`
213    ///     - `Digit::Zero` for `Digit::Zero`
214    ///     - `Digit::Pos` for `Digit::Pos`
215    ///
216    /// This method is used to calculate strictly positive states
217    /// in association with ternary logic.
218    pub fn positive(&self) -> Self {
219        match self {
220            Digit::Neg => Digit::Zero,
221            Digit::Zero => Digit::Zero,
222            Digit::Pos => Digit::Pos,
223        }
224    }
225
226    /// Determines the condition of non-positivity for the current `Digit`.
227    ///
228    /// - Returns:
229    ///     - `Digit::Pos` for `Digit::Neg`
230    ///     - `Digit::Pos` for `Digit::Zero`
231    ///     - `Digit::Zero` for `Digit::Pos`
232    ///
233    /// This method complements the `positive` condition and captures
234    /// states that are not strictly positive.
235    pub fn not_positive(&self) -> Self {
236        match self {
237            Digit::Neg => Digit::Pos,
238            Digit::Zero => Digit::Pos,
239            Digit::Pos => Digit::Zero,
240        }
241    }
242
243    /// Determines the strictly negative condition for the current `Digit`.
244    ///
245    /// - Returns:
246    ///     - `Digit::Pos` for `Digit::Neg`
247    ///     - `Digit::Zero` for `Digit::Zero`
248    ///     - `Digit::Zero` for `Digit::Pos`
249    ///
250    /// This method calculates strictly negative states
251    /// in association with ternary logic.
252    pub fn negative(&self) -> Self {
253        match self {
254            Digit::Neg => Digit::Pos,
255            Digit::Zero => Digit::Zero,
256            Digit::Pos => Digit::Zero,
257        }
258    }
259
260    /// Performs Kleene implication with the current `Digit` as `self` and another `Digit`.
261    ///
262    /// - `self`: The antecedent of the implication.
263    /// - `other`: The consequent of the implication.
264    ///
265    /// - Returns:
266    ///     - `Digit::Pos` when `self` is `Digit::Neg`.
267    ///     - The positive condition of `other` when `self` is `Digit::Zero`.
268    ///     - `other` when `self` is `Digit::Pos`.
269    ///
270    /// Implements Kleene ternary implication logic, which includes
271    /// determining the logical result based on antecedent and consequent.
272    pub fn k3_imply(&self, other: Self) -> Self {
273        match self {
274            Digit::Neg => Digit::Pos,
275            Digit::Zero => other.positive(),
276            Digit::Pos => other,
277        }
278    }
279
280    /// Performs Łukasiewicz implication with the current `Digit` as `self` and another `Digit`.
281    ///
282    /// - `self`: The antecedent of the implication.
283    /// - `other`: The consequent of the implication.
284    ///
285    /// - Returns:
286    ///     - `Digit::Pos` when `self` is `Digit::Neg`.
287    ///     - The non-negative condition of `other` when `self` is `Digit::Zero`.
288    ///     - `other` when `self` is `Digit::Pos`.
289    ///
290    /// Implements Łukasiewicz ternary implication logic, which
291    /// evaluates an alternative approach for implication compared to Kleene logic.
292    pub fn l3_imply(&self, other: Self) -> Self {
293        match self {
294            Digit::Neg => Digit::Pos,
295            Digit::Zero => other.not_negative(),
296            Digit::Pos => other,
297        }
298    }
299
300    /// Performs RM3 implication with the current `Digit` as `self` and another `Digit`.
301    ///
302    /// - `self`: The antecedent of the implication.
303    /// - `other`: The consequent of the implication.
304    ///
305    /// - Returns:
306    ///     - `Digit::Pos` when `self` is `Digit::Neg`.
307    ///     - `other` when `self` is `Digit::Zero`.
308    ///     - The necessary condition of `other` when `self` is `Digit::Pos`.
309    ///
310    /// Implements RM3 ternary implication logic, which defines a unique
311    /// perspective for implication operations in balanced ternary systems.
312    pub fn rm3_imply(&self, other: Self) -> Self {
313        match self {
314            Digit::Neg => Digit::Pos,
315            Digit::Zero => other,
316            Digit::Pos => other.necessary(),
317        }
318    }
319
320    /// Performs HT implication with the current `Digit` as `self` and another `Digit`.
321    ///
322    /// - `self`: The antecedent of the implication.
323    /// - `other`: The consequent of the implication.
324    ///
325    /// - Returns:
326    ///     - `Digit::Pos` when `self` is `Digit::Neg`.
327    ///     - The possibility condition of `other` when `self` is `Digit::Zero`.
328    ///     - `other` when `self` is `Digit::Pos`.
329    ///
330    /// This method computes HT ternary implication based on heuristic logic.
331    pub fn ht_imply(&self, other: Self) -> Self {
332        match self {
333            Digit::Neg => Digit::Pos,
334            Digit::Zero => other.possibly(),
335            Digit::Pos => other,
336        }
337    }
338
339    /// Performs HT logical negation of the current `Digit`.
340    ///
341    /// - Returns:
342    ///     - `Digit::Pos` when `self` is `Digit::Neg`.
343    ///     - `Digit::Neg` when `self` is `Digit::Zero` or `Digit::Pos`.
344    ///
345    /// This method evaluates the HT negation result using heuristic ternary logic.
346    pub fn ht_not(&self) -> Self {
347        match self {
348            Digit::Neg => Digit::Pos,
349            Digit::Zero => Digit::Neg,
350            Digit::Pos => Digit::Neg,
351        }
352    }
353
354
355    /// Converts the `Digit` to a `bool` in HT logic.
356    ///
357    /// - Returns:
358    ///     - `true` when `self` is `Digit::Pos`.
359    ///     - `false` when `self` is `Digit::Neg`.
360    ///
361    /// - Panics:
362    ///     - Panics if `self` is `Digit::Zero`, as `Digit::Zero` cannot be directly
363    ///       converted to a boolean value.
364    ///       > Use `Digit::possibly()` or `Digit::necessary()` before calling this method in such cases.
365    pub fn ht_bool(&self) -> bool {
366        match self {
367            Digit::Neg => false,
368            Digit::Zero => panic!(
369                "Cannot convert a Digit::Zero to a bool. \
370                 Use Digit::possibly()->to_bool() or Digit::necessary()->to_bool() instead."),
371            Digit::Pos => true,
372        }
373    }
374
375    /// This method maps this `Digit` value to its corresponding unbalanced ternary
376    /// integer representation.
377    ///
378    /// - Returns:
379    ///     - `0` for `Digit::Neg`.
380    ///     - `1` for `Digit::Zero`.
381    ///     - `2` for `Digit::Pos`.
382    ///
383    pub fn to_unbalanced(&self) -> u8 {
384        match self {
385            Digit::Neg => 0,
386            Digit::Zero => 1,
387            Digit::Pos => 2,
388        }
389    }
390    
391
392    /// Creates a `Digit` from an unbalanced ternary integer representation.
393    ///
394    /// # Arguments:
395    /// - `u`: An unsigned 8-bit integer representing an unbalanced ternary value.
396    ///
397    /// # Returns:
398    /// - `Digit::Neg` for `0`.
399    /// - `Digit::Zero` for `1`.
400    /// - `Digit::Pos` for `2`.
401    ///
402    /// # Panics:
403    /// - Panics if the provided value is not `0`, `1`, or `2`, as these are the
404    ///   only valid representations of unbalanced ternary values.
405    pub fn from_unbalanced(u: u8) -> Digit {
406        match u {
407            0 => Digit::Neg,
408            1 => Digit::Zero,
409            2 => Digit::Pos,
410            _ => panic!("Invalid value. A unbalanced ternary value must be either 0, 1 or 2."),
411        }
412    }
413}
414
415impl Neg for Digit {
416    type Output = Self;
417
418    /// Returns the negation of the `Digit`.
419    ///
420    /// - `Digit::Neg` becomes `Digit::Pos`
421    /// - `Digit::Pos` becomes `Digit::Neg`
422    /// - `Digit::Zero` remains `Digit::Zero`
423    fn neg(self) -> Self::Output {
424        match self {
425            Digit::Neg => Digit::Pos,
426            Digit::Zero => Digit::Zero,
427            Digit::Pos => Digit::Neg,
428        }
429    }
430}
431
432impl Not for Digit {
433    type Output = Self;
434    fn not(self) -> Self::Output {
435        -self
436    }
437}
438
439impl Add<Digit> for Digit {
440    type Output = Ternary;
441
442    /// Adds two `Digit` values together and returns a `Ternary` result.
443    ///
444    /// - The rules for addition are based on ternary arithmetic:
445    ///   - For `Digit::Neg`:
446    ///     - Adding `Digit::Neg` results in "underflow" (`Ternary::parse("-+")`).
447    ///     - Adding `Digit::Zero` keeps the result as `Digit::Neg` (`Ternary::parse("-")`).
448    ///     - Adding `Digit::Pos` results in a balance (`Ternary::parse("0")`).
449    ///   - For `Digit::Zero`:
450    ///     - Simply returns the other operand wrapped in a `Ternary` object.
451    ///   - For `Digit::Pos`:
452    ///     - Adding `Digit::Neg` results in balance (`Ternary::parse("0")`).
453    ///     - Adding `Digit::Zero` keeps the result as `Digit::Pos` (`Ternary::parse("+")`).
454    ///     - Adding `Digit::Pos` results in "overflow" (`Ternary::parse("+-")`).
455    ///
456    /// - Returns:
457    ///   - A `Ternary` instance that holds the result of the addition.
458    ///
459    /// - Panics:
460    ///   - This method does not panic under any circumstances.
461    fn add(self, other: Digit) -> Self::Output {
462        match self {
463            Digit::Neg => match other {
464                Digit::Neg => Ternary::parse("-+"),
465                Digit::Zero => Ternary::parse("-"),
466                Digit::Pos => Ternary::parse("0"),
467            },
468            Digit::Zero => Ternary::new(vec![other]),
469            Digit::Pos => match other {
470                Digit::Neg => Ternary::parse("0"),
471                Digit::Zero => Ternary::parse("+"),
472                Digit::Pos => Ternary::parse("+-"),
473            },
474        }
475    }
476}
477
478impl Sub<Digit> for Digit {
479    type Output = Ternary;
480    
481
482    /// Subtracts two `Digit` values and returns a `Ternary` result.
483    ///
484    /// - The rules for subtraction are based on ternary arithmetic:
485    ///   - For `Digit::Neg`:
486    ///     - Subtracting `Digit::Neg` results in balance (`Ternary::parse("0")`).
487    ///     - Subtracting `Digit::Zero` keeps the result as `Digit::Neg` (`Ternary::parse("-")`).
488    ///     - Subtracting `Digit::Pos` results in "underflow" (`Ternary::parse("-+")`).
489    ///   - For `Digit::Zero`:
490    ///     - Simply negates the other operand and returns it wrapped in a `Ternary` object.
491    ///   - For `Digit::Pos`:
492    ///     - Subtracting `Digit::Neg` results in "overflow" (`Ternary::parse("+-")`).
493    ///     - Subtracting `Digit::Zero` keeps the result as `Digit::Pos` (`Ternary::parse("+")`).
494    ///     - Subtracting `Digit::Pos` results in balance (`Ternary::parse("0")`).
495    ///
496    /// - Returns:
497    ///   - A `Ternary` instance that holds the result of the subtraction.
498    ///
499    /// - Panics:
500    ///   - This method does not panic under any circumstances.
501    fn sub(self, other: Digit) -> Self::Output {
502        match self {
503            Digit::Neg => match other {
504                Digit::Neg => Ternary::parse("0"),
505                Digit::Zero => Ternary::parse("-"),
506                Digit::Pos => Ternary::parse("-+"),
507            },
508            Digit::Zero => Ternary::new(vec![-other]),
509            Digit::Pos => match other {
510                Digit::Neg => Ternary::parse("+-"),
511                Digit::Zero => Ternary::parse("+"),
512                Digit::Pos => Ternary::parse("0"),
513            },
514        }
515    }
516}
517
518impl Mul<Digit> for Digit {
519    type Output = Digit;
520
521    
522    /// Multiplies two `Digit` values together and returns the product as a `Digit`.
523    ///
524    /// - The rules for multiplication in this implementation are straightforward:
525    ///   - `Digit::Neg` multiplied by:
526    ///     - `Digit::Neg` results in `Digit::Pos`.
527    ///     - `Digit::Zero` results in `Digit::Zero`.
528    ///     - `Digit::Pos` results in `Digit::Neg`.
529    ///   - `Digit::Zero` multiplied by any `Digit` always results in `Digit::Zero`.
530    ///   - `Digit::Pos` multiplied by:
531    ///     - `Digit::Neg` results in `Digit::Neg`.
532    ///     - `Digit::Zero` results in `Digit::Zero`.
533    ///     - `Digit::Pos` results in `Digit::Pos`.
534    ///
535    /// - Returns:
536    ///   - A `Digit` instance representing the result of the multiplication.
537    fn mul(self, other: Digit) -> Self::Output {
538        match self {
539            Digit::Neg => -other,
540            Digit::Zero => Digit::Zero,
541            Digit::Pos => other,
542        }
543    }
544}
545
546impl Div<Digit> for Digit {
547    type Output = Digit;
548
549    
550    /// Divides one `Digit` value by another and returns the result as a `Digit`.
551    ///
552    /// # Rules for division:
553    /// - For `Digit::Neg`:
554    ///   - Dividing `Digit::Neg` by `Digit::Neg` results in `Digit::Pos`.
555    ///   - Dividing `Digit::Neg` by `Digit::Zero` will panic with "Cannot divide by zero."
556    ///   - Dividing `Digit::Neg` by `Digit::Pos` results in `Digit::Neg`.
557    /// - For `Digit::Zero`:
558    ///   - Dividing `Digit::Zero` by `Digit::Neg` results in `Digit::Zero`.
559    ///   - Dividing `Digit::Zero` by `Digit::Zero` will panic with "Cannot divide by zero."
560    ///   - Dividing `Digit::Zero` by `Digit::Pos` results in `Digit::Zero`.
561    /// - For `Digit::Pos`:
562    ///   - Dividing `Digit::Pos` by `Digit::Neg` results in `Digit::Neg`.
563    ///   - Dividing `Digit::Pos` by `Digit::Zero` will panic with "Cannot divide by zero."
564    ///   - Dividing `Digit::Pos` by `Digit::Pos` results in `Digit::Pos`.
565    ///
566    /// # Returns:
567    /// - A `Digit` value representing the result of the division.
568    ///
569    /// # Panics:
570    /// - Panics with "Cannot divide by zero." if the `other` operand is `Digit::Zero`.
571    fn div(self, other: Digit) -> Self::Output {
572        match self {
573            Digit::Neg => match other {
574                Digit::Neg => Digit::Pos,
575                Digit::Zero => panic!("Cannot divide by zero."),
576                Digit::Pos => Digit::Neg,
577            },
578            Digit::Zero => match other {
579                Digit::Neg => Digit::Zero,
580                Digit::Zero => panic!("Cannot divide by zero."),
581                Digit::Pos => Digit::Zero,
582            },
583            Digit::Pos => match other {
584                Digit::Neg => Digit::Neg,
585                Digit::Zero => panic!("Cannot divide by zero."),
586                Digit::Pos => Digit::Pos,
587            },
588        }
589    }
590}
591
592impl BitAnd for Digit {
593    type Output = Self;
594    
595    /// Performs a bitwise AND operation between two `Digit` values and returns the result.
596    ///
597    /// - The rules for the bitwise AND (`&`) operation are:
598    ///   - If `self` is `Digit::Neg`, the result is always `Digit::Neg`.
599    ///   - If `self` is `Digit::Zero`, the result depends on the value of `other`:
600    ///     - `Digit::Neg` results in `Digit::Neg`.
601    ///     - Otherwise, the result is `Digit::Zero`.
602    ///   - If `self` is `Digit::Pos`, the result is simply `other`.
603    ///
604    /// # Returns:
605    /// - A `Digit` value that is the result of the bitwise AND operation.
606    ///
607    /// # Examples:
608    /// ```
609    /// use balanced_ternary::Digit;
610    /// use Digit::{Neg, Pos, Zero};
611    ///
612    /// assert_eq!(Neg & Pos, Neg);
613    /// assert_eq!(Zero & Neg, Neg);
614    /// assert_eq!(Zero & Pos, Zero);
615    /// assert_eq!(Pos & Zero, Zero);
616    /// ```
617    fn bitand(self, other: Self) -> Self::Output {
618        match self {
619            Digit::Neg => Digit::Neg,
620            Digit::Zero => match other {
621                Digit::Neg => Digit::Neg,
622                _ => Digit::Zero,
623            },
624            Digit::Pos => other,
625        }
626    }
627}
628
629impl BitOr for Digit {
630    type Output = Self;
631
632
633    /// Performs a bitwise OR operation between two `Digit` values and returns the result.
634    ///
635    /// - The rules for the bitwise OR (`|`) operation are as follows:
636    ///   - If `self` is `Digit::Neg`, the result is always the value of `other`.
637    ///   - If `self` is `Digit::Zero`, the result depends on the value of `other`:
638    ///     - `Digit::Pos` results in `Digit::Pos`.
639    ///     - Otherwise, the result is `Digit::Zero`.
640    ///   - If `self` is `Digit::Pos`, the result is always `Digit::Pos`.
641    ///
642    /// # Returns:
643    /// - A `Digit` value that is the result of the bitwise OR operation.
644    ///
645    /// # Examples:
646    /// ```
647    /// use balanced_ternary::Digit;
648    /// use Digit::{Neg, Pos, Zero};
649    ///
650    /// assert_eq!(Neg | Pos, Pos);
651    /// assert_eq!(Zero | Neg, Zero);
652    /// assert_eq!(Zero | Pos, Pos);
653    /// assert_eq!(Pos | Zero, Pos);
654    /// ```
655    fn bitor(self, other: Self) -> Self::Output {
656        match self {
657            Digit::Neg => other,
658            Digit::Zero => match other {
659                Digit::Pos => Digit::Pos,
660                _ => Digit::Zero,
661            },
662            Digit::Pos => Digit::Pos,
663        }
664    }
665}
666
667impl BitXor for Digit {
668    type Output = Self;
669
670    /// Performs a bitwise XOR (exclusive OR) operation between two `Digit` values.
671    ///
672    /// - The rules for the bitwise XOR (`^`) operation are as follows:
673    ///   - If `self` is `Digit::Neg`, the result is always the value of `rhs`.
674    ///   - If `self` is `Digit::Zero`, the result is always `Digit::Zero`.
675    ///   - If `self` is `Digit::Pos`, the result is the negation of `rhs`:
676    ///     - `Digit::Neg` becomes `Digit::Pos`.
677    ///     - `Digit::Zero` becomes `Digit::Zero`.
678    ///     - `Digit::Pos` becomes `Digit::Neg`.
679    ///
680    /// # Returns:
681    /// - A `Digit` value that is the result of the bitwise XOR operation.
682    ///
683    /// # Examples:
684    /// ```
685    /// use balanced_ternary::Digit;
686    /// use Digit::{Neg, Pos, Zero};
687    ///
688    /// assert_eq!(Neg ^ Pos, Pos);
689    /// assert_eq!(Zero ^ Neg, Zero);
690    /// assert_eq!(Pos ^ Pos, Neg);
691    /// ```
692    fn bitxor(self, rhs: Self) -> Self::Output {
693        match self {
694            Digit::Neg => rhs,
695            Digit::Zero => Digit::Zero,
696            Digit::Pos => -rhs,
697        }
698    }
699}