1use crate::graphemes::grapheme_creation::GRAPHEMES;
2
3pub fn vec_to_arr<T, const N: usize>(v: Vec<T>) -> [T; N] {
4 v.try_into()
5 .unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
6}
7
8pub fn from_string(base: u16, number: &str) -> Vec<u16> {
9 if base > GRAPHEMES.len() as u16 {
10 panic!("There are not enough graphemes create number. Use a lower base");
11 }
12 let number = number.trim();
14 let digits: Vec<u16> = number
15 .split("")
16 .filter(|s| s != &"")
17 .map(|s| {
18 let byte_arr = s.as_bytes();
19 let mut byte_vec: Vec<u8> = Vec::new();
20 byte_vec.resize(4 - byte_arr.len(), 0);
22 for byte in byte_arr {
24 byte_vec.push(*byte);
25 }
26
27 let comp_arr = &vec_to_arr(byte_vec);
28
29 if let Some(key) =
31 GRAPHEMES
32 .iter()
33 .find_map(|(key, val)| if val == comp_arr { Some(key) } else { None })
34 {
35 if *key > base - 1 {
36 let error = String::from("value ")
37 + number
38 + " contains graphemes greater than number base "
39 + &base.to_string();
40 panic!("{error}");
41 }
42 *key
43 } else {
44 let error = String::from("value ") + number + " not in valid graphemes";
45 panic!("{error}");
46 }
47 })
48 .collect();
49
50 digits
51}
52
53pub fn add(base: u16, numb1: &[u16], numb2: &[u16]) -> Vec<u16> {
54 let mut numb1 = numb1.to_owned();
55 numb1.reverse();
56 let mut numb2 = numb2.to_owned();
57 numb2.reverse();
58
59 let mut res: Vec<u16> = Vec::new();
60
61 let (greatest, smallest) = if numb1.len() > numb2.len() {
62 (&numb1, &numb2)
63 } else {
64 (&numb2, &numb1)
65 };
66
67 for i in 0..smallest.len() {
68 res.push(greatest[i] + smallest[i]);
69 }
70 for digit in greatest.iter().skip(smallest.len()) {
71 res.push(*digit);
72 }
73
74 for i in 0..res.len() {
75 if res[i] >= base {
76 if i == res.len() - 1 {
78 res.push(1);
79 } else {
80 res[i + 1] += 1;
81 }
82 res[i] -= base;
83 }
84 }
85
86 res.reverse();
87 res
88}
89
90pub fn subtract(base: u16, numb1: &[u16], numb2: &[u16]) -> Vec<u16> {
92 let mut numb1 = numb1.to_owned();
93 numb1.reverse();
94 let mut numb2 = numb2.to_owned();
95 numb2.reverse();
96
97 let mut res: Vec<i32> = Vec::new();
98
99 for i in 0..numb2.len() {
100 res.push(numb1[i] as i32 - numb2[i] as i32);
101 }
102 for digit in numb1.iter().skip(numb2.len()) {
103 res.push(*digit as i32);
104 }
105
106 for i in 0..res.len() {
107 if res[i] < 0 {
108 res[i + 1] -= 1;
109 res[i] += base as i32;
110 }
111 }
112
113 while res.last() == Some(&0_i32) {
114 res.pop();
115 }
116
117 res.reverse();
118
119 res.iter().map(|x| x.to_owned() as u16).collect()
120}
121
122pub fn trim_base_vec(vec: &mut Vec<u16>) -> Vec<u16> {
123 vec.reverse();
124 while vec.last() == Some(&0_u16) {
125 vec.pop();
126 }
127 vec.reverse();
128 vec.to_owned()
129}
130
131pub fn greater_than(numb1: &[u16], numb2: &[u16]) -> bool {
132 let numb1 = trim_base_vec(&mut numb1.to_owned());
133 let numb2 = trim_base_vec(&mut numb2.to_owned());
134 if numb1.len() > numb2.len() {
135 return true;
136 } else if numb1.len() == numb2.len() {
137 for i in 0..numb1.len() {
138 if numb1[i] > numb2[i] {
139 return true;
140 } else if numb2[i] > numb1[i] {
141 return false;
142 }
143 }
144 false
145 } else {
146 false
147 }
148}
149
150fn convert_base10(base: u16, numb: &[u16]) -> u128 {
151 let mut numb = numb.to_owned();
152 numb.reverse();
153 let mut res: u128 = 0;
154 for i in 0..numb.len() {
155 res += numb[i as usize] as u128 * (base as u128).pow(i as u32) as u128;
156 }
157 res
158}
159
160pub fn div(base: u16, numb1: &[u16], numb2: &[u16]) -> (Vec<u16>, Vec<u16>) {
161 let mut numb1 = numb1.to_owned();
162 let mut numb2 = numb2.to_owned();
163
164 trim_base_vec(&mut numb1);
166 trim_base_vec(&mut numb2);
167
168 if greater_than(&numb2, &numb1) {
171 return (vec![0], numb1);
172 }
173
174 let mut quo: Vec<u16> = Vec::new();
175 let mut divident: Vec<u16> = Vec::new();
176 for numb in &numb1 {
177 divident.push(*numb);
178 if greater_than(&numb2, ÷nt) {
179 quo.push(0);
180 } else {
181 let divident_base10 = convert_base10(base, ÷nt);
184 let divisor_base10 = convert_base10(base, &numb2);
185 let res = (divident_base10 / divisor_base10) as u16;
186 quo.push(res);
187
188 divident = subtract(base, ÷nt, &mul(base, &vec![res], &numb2));
190 }
191 }
192
193 let remainder = trim_base_vec(&mut subtract(base, &numb1, &mul(base, &quo, &numb2)));
194
195 (quo, remainder)
196}
197
198pub fn mul(base: u16, number1: &[u16], number2: &[u16]) -> Vec<u16> {
199 let numb1 = if greater_than(number1, number2) {
200 let mut numb1 = number1.to_owned();
201 numb1.reverse();
202 numb1
203 } else {
204 let mut numb2 = number2.to_owned();
205 numb2.reverse();
206 numb2
207 };
208
209 let numb2 = if !greater_than(number1, number2) {
210 let mut numb1 = number1.to_owned();
211 numb1.reverse();
212 numb1
213 } else {
214 let mut numb2 = number2.to_owned();
215 numb2.reverse();
216 numb2
217 };
218
219 let mut mul_pieces: Vec<Vec<u16>> = Vec::new();
220
221 for digit2 in numb2 {
222 let mut mul_piece: Vec<u16> = Vec::new();
223 let mut waiting_value: u16 = 0;
224 let mut placing_value: u16;
225 for digit1 in &numb1 {
226 let product = digit1 * digit2;
227 placing_value = waiting_value + (product - (product / base) * base);
228 waiting_value = product / base;
229
230 if placing_value >= base {
231 placing_value -= base;
232 waiting_value += 1;
233 }
234 mul_piece.push(placing_value);
235 }
236 if waiting_value != 0 {
237 mul_piece.push(waiting_value);
238 }
239 mul_piece.reverse();
240 mul_pieces.push(mul_piece);
241 }
242
243 for (i, piece) in mul_pieces.iter_mut().enumerate() {
244 for _ in 0..i {
245 piece.push(0);
246 }
247 }
248
249 let mut res: Vec<u16> = vec![];
250 for piece in mul_pieces {
251 res = add(base, &res, &piece);
252 }
253
254 trim_base_vec(&mut res)
255}
256
257fn as_base10(base: u16, mut numb: Vec<u16>) -> u16 {
258 let mut res: u128 = 0;
259 numb.reverse();
260
261 for (i, digit) in numb.iter().enumerate() {
262 res += *digit as u128 * (base as u128).pow(i as u32);
263 }
264
265 res as u16
266}
267
268fn from_base10(base: u16, mut numb: u16) -> Vec<u16> {
269 let mut res: Vec<u16> = Vec::new();
270 while numb > 0 {
271 res.push(numb % base);
272 numb /= base;
273 }
274
275 res.reverse();
276 res
277}
278
279pub fn convert(self_base: u16, self_digits: Vec<u16>, base: u16) -> Vec<u16> {
280 if base > GRAPHEMES.len() as u16 {
281 panic!("Cannot convert. Requested base is greater than number of graphemes.");
282 }
283 let mut base_as_self = from_base10(self_base, base);
285
286 let mut res: Vec<u16> = Vec::new();
287
288 let mut numb = self_digits;
289 while greater_than(&numb, &base_as_self)
290 || trim_base_vec(&mut numb) == trim_base_vec(&mut base_as_self)
291 {
292 let (quotient, rem) = div(self_base, &numb, &base_as_self);
293 numb = quotient;
294 res.push(as_base10(self_base, rem));
295 }
296 res.push(as_base10(self_base, numb));
297
298 res.reverse();
299 res
300}