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}