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