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}