balanced_ternary/
concepts.rs

1use crate::Digit;
2use alloc::vec::Vec;
3
4pub trait DigitOperate {
5    /// Returns every individual [Digit] of this [DigitOperate] object.
6    fn to_digits(&self) -> Vec<Digit>;
7
8    /// Returns one individual [Digit] ot this [DigitOperate] object if it exists.
9    fn digit(&self, index: usize) -> Option<Digit>;
10
11    /// Applies a transformation function to each digit of the balanced ternary number,
12    /// returning a new `DigitOperate` object with the transformed digits.
13    ///
14    /// ### Arguments
15    ///
16    /// * `f` - A closure or function that takes a `Digit` and returns a transformed `Digit`.
17    ///
18    /// ### Returns
19    ///
20    /// * `Self` - A new `DigitOperate` object containing the transformed digits.
21    ///
22    /// ### Digit transformations
23    ///
24    /// These methods (unary operators) from the [Digit] type can be called directly.
25    ///
26    /// * Returns either `Pos` or `Neg`:
27    ///     * [Digit::possibly]
28    ///     * [Digit::necessary]
29    ///     * [Digit::contingently]
30    ///     * [Digit::ht_not]
31    /// * Returns either `Zero` or `Pos` or `Neg`.
32    ///     * [Digit::pre]
33    ///     * [Digit::post]
34    ///     * `Digit::not`
35    ///     * `Digit::neg`
36    ///     * [Digit::absolute_positive]
37    ///     * [Digit::positive]
38    ///     * [Digit::not_negative]
39    ///     * [Digit::not_positive]
40    ///     * [Digit::negative]
41    ///     * [Digit::absolute_negative]
42    ///
43    /// ### Examples with [crate::Ternary]
44    /// ```
45    /// use balanced_ternary::{Ternary, Digit};
46    /// use balanced_ternary::concepts::DigitOperate;
47    ///
48    /// let orig_ternary = Ternary::parse("+0-");
49    /// let transformed = orig_ternary.each(Digit::necessary);
50    /// assert_eq!(transformed.to_string(), "+--");
51    /// let transformed = orig_ternary.each(Digit::positive);
52    /// assert_eq!(transformed.to_string(), "+00");
53    /// let transformed = orig_ternary.each(Digit::not_negative);
54    /// assert_eq!(transformed.to_string(), "++0");
55    /// let transformed = orig_ternary.each(Digit::absolute_negative);
56    /// assert_eq!(transformed.to_string(), "-0-");
57    /// ```
58    fn each(&self, f: impl Fn(Digit) -> Digit) -> Self
59    where
60        Self: Sized;
61
62    /// Applies a transformation function to each digit of the balanced ternary number,
63    /// using an additional parameter for the transformation process, returning a new `DigitOperate`
64    /// object with the transformed digits.
65    ///
66    /// ### Arguments
67    ///
68    /// * `f` - A closure or function that takes a `Digit` and an additional `Digit`,
69    ///         and returns a transformed `Digit`.
70    /// * `other` - An additional `Digit` to be passed to the transformation function `f`.
71    ///
72    /// ### Returns
73    ///
74    /// * `Self` - A new `DigitOperate` object containing the transformed digits.
75    ///
76    /// ### Digit transformations
77    ///
78    /// These methods (binary operators) from the [Digit] type can be called directly.
79    ///
80    /// * `Digit::add`
81    /// * `Digit::sub`
82    /// * `Digit::mul`
83    /// * `Digit::div`
84    /// * `Digit::bitand` (k3/l3 and)
85    /// * [Digit::bi3_and]
86    /// * `Digit::bitor`  (k3/l3 or)
87    /// * [Digit::bi3_or]
88    /// * `Digit::bitxor` (k3/l3 xor)
89    /// * [Digit::k3_imply]
90    /// * [Digit::k3_equiv]
91    /// * [Digit::bi3_imply]
92    /// * [Digit::l3_imply]
93    /// * [Digit::rm3_imply]
94    /// * [Digit::ht_imply]
95    ///
96    /// ### Examples with [crate::Ternary]
97    /// ```
98    /// use std::ops::Mul;
99    /// use balanced_ternary::{Ternary, Digit};
100    /// use balanced_ternary::concepts::DigitOperate;
101    ///
102    /// let original = Ternary::parse("+-0");
103    /// let transformed = original.each_with(Digit::mul, Digit::Neg);
104    /// assert_eq!(transformed.to_string(), "-+0");
105    /// ```
106    fn each_with(&self, f: impl Fn(Digit, Digit) -> Digit, other: Digit) -> Self
107    where
108        Self: Sized;
109
110    /// Applies a transformation function to each digit of the balanced ternary number,
111    /// along with a corresponding digit from another `DigitOperate` number.
112    ///
113    /// ### Arguments
114    ///
115    /// * `f` - A closure or function that takes two arguments:
116    ///     * a `Digit` from the current `Ternary`,
117    ///     * a `Digit` from the corresponding position in the `other` `Ternary`.
118    ///     * The function must return a transformed `Digit`.
119    /// * `other` - A `DigitOperate` object with digits to process alongside the digits of the current object.
120    ///
121    /// ### Returns
122    ///
123    /// * `Self` - A new `DigitOperate` object containing the transformed digits.
124    ///
125    /// ### Examples with [crate::Ternary]
126    ///
127    /// ```
128    /// use std::ops::Mul;
129    /// use balanced_ternary::{Ternary, Digit};
130    /// use balanced_ternary::concepts::DigitOperate;
131    ///
132    /// let ternary1 = Ternary::parse("-+0-+0-+0");
133    /// let ternary2 = Ternary::parse("---000+++");
134    ///
135    /// let result = ternary1.each_zip(Digit::mul, ternary2.clone());
136    /// assert_eq!(result.to_string(), "+-0000-+0");
137    ///
138    /// let result = ternary1.each_zip(Digit::k3_imply, ternary2.clone());
139    /// assert_eq!(result.to_string(), "+-0+00+++");
140    /// let result = ternary1.each_zip(Digit::bi3_imply, ternary2.clone());
141    /// assert_eq!(result.to_string(), "+-0000++0");
142    /// let result = ternary1.each_zip(Digit::ht_imply, ternary2.clone());
143    /// assert_eq!(result.to_string(), "+--+0++++");
144    /// ```
145    fn each_zip(&self, f: impl Fn(Digit, Digit) -> Digit, other: Self) -> Self
146    where
147        Self: Sized;
148
149    /// Applies a transformation function to each digit of the balanced ternary number,
150    /// along with a corresponding digit from another `DigitOperate` number, and a carry digit.
151    ///
152    /// ### Arguments
153    ///
154    /// * `f` - A closure or function that takes three arguments:
155    ///     * a `Digit` from the current `DigitOperate`,
156    ///     * a `Digit` from the corresponding position in the `other` `DigitOperate`,
157    ///     * and the current carry `Digit`.
158    ///     * The function must return a tuple containing `(carry: Digit, transformed: Digit)`.
159    /// * `other` - A `DigitOperate` object with digits to process alongside the digits of the current object.
160    ///
161    /// ### Returns
162    ///
163    /// * `Self` - A new `DigitOperate` object containing the transformed digits.
164    ///
165    /// ### Examples with [crate::Ternary]
166    ///
167    /// ```
168    /// use balanced_ternary::{Digit, Ternary};
169    /// use balanced_ternary::concepts::DigitOperate;
170    ///
171    /// let ternary1 = Ternary::parse("+-0");
172    /// let ternary2 = Ternary::parse("-+0");
173    ///
174    /// // Transformation function that adds digits with a carry digit
175    /// let combine = |d1: Digit, d2: Digit, carry: Digit| -> (Digit, Digit) {
176    ///     // Simple example operation: this just illustrates transforming with carry.
177    ///     // Replace with meaningful logic as needed for your application.
178    ///     let sum = d1.to_i8() + d2.to_i8() + carry.to_i8();
179    ///     (Digit::from_i8(sum / 3), Digit::from_i8(sum % 3))
180    /// };
181    ///
182    /// let result = ternary1.each_zip_carry(combine, ternary2.clone()).trim();
183    /// assert_eq!(result.to_string(), (&ternary1 + &ternary2).to_string());
184    /// ```
185    fn each_zip_carry(
186        &self,
187        f: impl Fn(Digit, Digit, Digit) -> (Digit, Digit),
188        other: Self,
189    ) -> Self
190    where
191        Self: Sized;
192}