devela/num/int/wrapper/impl_factors.rs
1// devela::num::int::wrapper::impl_factors
2//
3//! Implements factors-related methods for [`Int`].
4//
5// TOC
6// - signed|unsigned:
7// - allocating:
8// - factors
9// - factors_proper
10// - factors_prime
11// - factors_prime_unique
12// - factors_prime_unique_exp
13// - non_allocating:
14// - factors_prime_count
15// - factors_prime_unique_count
16// - factors_buf
17// - factors_proper_buf
18// - factors_prime_buf
19// - factors_prime_unique_buf
20// - factors_prime_unique_exp_buf
21// - factors_prime_unique_plus_buf
22//
23// TODO MAYBE BENCH implementing another factorization solution
24// - https://www.reddit.com/r/matheducation/comments/1iog8xg/covering_the_basics_how_to_find_factors_gcse_math/
25// 2 arrays (subdivide, first, last next, corresponding, etc. )
26// could be 2 mutable parts of the same array, with split_mut.
27
28use crate::{iif, paste, Int, NumError::MismatchedSizes, NumResult as Result};
29#[cfg(feature = "alloc")]
30use crate::{vec_ as vec, BTreeSet, Hook, Vec};
31
32/// Implements factors-related methods for [`Int`].
33///
34/// # Args.
35/// $t: the input/output type
36/// $cap: the capability feature that enables the given implementation. E.g "_int_i8"
37///
38/// $d: the doclink suffix for the method name
39macro_rules! impl_factors {
40 () => {
41 impl_factors![signed
42 i8 :"_int_i8" |"",
43 i16 :"_int_i16" |"-1",
44 i32 :"_int_i32" |"-2",
45 i64 :"_int_i64" |"-3",
46 i128 :"_int_i128" |"-4",
47 isize :"_int_isize" |"-5"
48 ];
49 impl_factors![unsigned
50 u8 :"_int_u8" |"-6",
51 u16 :"_int_u16" |"-7",
52 u32 :"_int_u32" |"-8",
53 u64 :"_int_u64" |"-9",
54 u128 :"_int_u128" |"-10",
55 usize :"_int_usize" |"-11"
56 ];
57 };
58 (signed $( $t:ty : $cap:literal | $d:literal ),+) => {
59 $( impl_factors![@signed $t:$cap |$d]; )+
60 };
61 (unsigned $( $t:ty : $cap:literal | $d:literal ),+) => {
62 $( impl_factors![@unsigned $t:$cap |$d]; )+
63 };
64 (
65 // implements signed ops
66 @signed $t:ty : $cap:literal | $d:literal) => { paste! {
67 #[doc = crate::doc_availability!(feature = $cap)]
68 ///
69 #[doc = "# Integer factors related methods for `" $t "`\n\n"]
70 /// - Allocating:
71 #[doc = " - [factors](#method.factors" $d ")"]
72 #[doc = " - [factors_proper](#method.factors_proper" $d ")"]
73 #[doc = " - [factors_prime](#method.factors_prime" $d ")"]
74 #[doc = " - [factors_prime_unique](#method.factors_prime_unique" $d ")"]
75 /// - Not allocating:
76 #[doc = " - [factors_buf](#method.factors_buf" $d ")"]
77 #[doc = " - [factors_proper_buf](#method.factors_proper_buf" $d ")"]
78 #[doc = " - [factors_prime_buf](#method.factors_prime_buf" $d ")"]
79 #[doc = " - [factors_prime_unique_buf](#method.factors_prime_unique_buf" $d ")"]
80 ///
81 #[cfg(feature = $cap )]
82 impl Int<$t> {
83 /* signed factors alloc */
84
85 /// Returns the factors (including 1 and self).
86 ///
87 /// # Examples
88 /// ```
89 /// # use devela::Int;
90 #[doc = "assert_eq![Int(24_" $t ").factors(), vec![1, 2, 3, 4, 6, 8, 12, 24]];"]
91 #[doc = "assert_eq![Int(-24_" $t ").factors(), vec![1, 2, 3, 4, 6, 8, 12, 24]];"]
92 #[doc = "assert![Int(0_" $t ").factors().is_empty()];"]
93 #[doc = "assert_eq![Int(1_" $t ").factors(), vec![1]];"]
94 #[doc = "assert_eq![Int(7_" $t ").factors(), vec![1, 7]];"]
95 /// ```
96 #[must_use]
97 #[cfg(feature = "alloc")]
98 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
99 pub fn factors(self) -> Vec<$t> {
100 let n = self.0.abs();
101 iif![n == 0; return vec![];
102 iif![n == 1; return vec![1]]];
103 let mut set = BTreeSet::new();
104 set.insert(1);
105 for p in self.factors_prime_unique() {
106 let temp = set.clone();
107 let mut x = p;
108 while x <= n {
109 for &num in &temp {
110 let new_num = num * x;
111 iif!{n % new_num == 0; {set.insert(new_num);} }
112 }
113 x *= p;
114 }
115 }
116 set.into_iter().collect()
117 }
118
119 /// Returns the proper factors.
120 ///
121 /// # Examples
122 /// ```
123 /// # use devela::Int;
124 #[doc = "assert_eq![Int(24_" $t ").factors_proper(), vec![2, 3, 4, 6, 8, 12]];"]
125 #[doc = "assert_eq![Int(-24_" $t ").factors_proper(), vec![2, 3, 4, 6, 8, 12]];"]
126 #[doc = "assert![Int(0_" $t ").factors_proper().is_empty()];"]
127 #[doc = "assert![Int(1_" $t ").factors_proper().is_empty()];"]
128
129 #[doc = "assert![Int(7_" $t ").factors_proper().is_empty()];"]
130 /// ```
131 #[must_use]
132 #[cfg(feature = "alloc")]
133 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
134 pub fn factors_proper(self) -> Vec<$t> {
135 let n = self.0.abs();
136 iif![n == 0; return vec![]];
137 let mut set = BTreeSet::new();
138 set.insert(1);
139 for p in self.factors_prime_unique() {
140 let temp = set.clone();
141 let mut x = p;
142 while x <= n {
143 for &num in &temp {
144 let new_num = num * x;
145 if n % new_num == 0 {
146 set.insert(new_num);
147 }
148 }
149 x *= p;
150 }
151 }
152 set.remove(&1);
153 set.remove(&n);
154 set.into_iter().collect()
155 }
156
157 /// Returns the prime factors.
158 ///
159 /// # Examples
160 /// ```
161 /// # use devela::Int;
162 #[doc = "assert_eq![Int(24_" $t ").factors_prime(), vec![2, 2, 2, 3]];"]
163 #[doc = "assert_eq![Int(-24_" $t ").factors_prime(), vec![2, 2, 2, 3]];"]
164 #[doc = "assert![Int(0_" $t ").factors_prime().is_empty()];"]
165 #[doc = "assert![Int(1_" $t ").factors_prime().is_empty()];"]
166 #[doc = "assert_eq![Int(7_" $t ").factors_prime(), vec![7]];"]
167 /// ```
168 #[must_use]
169 #[cfg(feature = "alloc")]
170 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
171 pub fn factors_prime(self) -> Vec<$t> {
172 let mut factors = Vec::new();
173 let mut n = self.0.abs();
174 iif![n == 0; return factors];
175
176 // Divide by 2 until the number is odd
177 while n % 2 == 0 {
178 factors.push(2);
179 n /= 2;
180 }
181 // Divide by odd numbers starting from 3
182 let mut i = 3;
183 while i * i <= n {
184 while n % i == 0 {
185 factors.push(i);
186 n /= i;
187 }
188 i += 2;
189 }
190 // If the remaining number is greater than 2, it's a prime factor
191 iif![n > 2; factors.push(n)];
192 factors
193 }
194
195 /// Returns the unique prime factors.
196 ///
197 /// # Examples
198 /// ```
199 /// # use devela::Int;
200 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique(), vec![2, 3]];"]
201 #[doc = "assert_eq![Int(-24_" $t ").factors_prime_unique(), vec![2, 3]];"]
202 /// ```
203 #[must_use]
204 #[cfg(feature = "alloc")]
205 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
206 pub fn factors_prime_unique(self) -> Vec<$t> {
207 self.factors_prime().hook_mut(|v| v.dedup())
208 }
209
210 /// Returns the unique prime factors with its exponent.
211 ///
212 /// # Examples
213 /// ```
214 /// # use devela::Int;
215 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique_exp(), vec![(2, 3), (3, 1)]];"]
216 #[doc = "assert_eq![Int(-24_" $t ").factors_prime_unique_exp(), vec![(2, 3), (3, 1)]];"]
217 #[doc = "assert![Int(0_" $t ").factors_prime_unique_exp().is_empty()];"]
218 #[doc = "assert![Int(1_" $t ").factors_prime_unique_exp().is_empty()];"]
219 #[doc = "assert_eq![Int(7_" $t ").factors_prime_unique_exp(), vec![(7, 1)]];"]
220 /// ```
221 #[must_use]
222 #[cfg(feature = "alloc")]
223 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
224 pub fn factors_prime_unique_exp(self) -> Vec<($t, u32)> {
225 let mut factors = Vec::new();
226 let mut current = None;
227 let mut count = 0;
228
229 for prime in self.factors_prime() {
230 match current {
231 Some(f) if f == prime => {
232 count += 1;
233 },
234 _ => {
235 if let Some(f) = current {
236 factors.push((f, count));
237 }
238 current = Some(prime);
239 count = 1;
240 },
241 }
242 }
243 if let Some(f) = current {
244 factors.push((f, count));
245 }
246 factors
247 }
248
249 /* signed factors non_alloc */
250
251 /// Returns the count of prime factors.
252 ///
253 /// # Examples
254 /// ```
255 /// # use devela::Int;
256 #[doc = "assert_eq![Int(24_" $t ").factors_prime_count(), 4];"]
257 #[doc = "assert_eq![Int(-24_" $t ").factors_prime_count(), 4];"]
258 #[doc = "assert_eq![Int(0_" $t ").factors_prime_count(), 0];"]
259 #[doc = "assert_eq![Int(1_" $t ").factors_prime_count(), 0];"]
260 #[doc = "assert_eq![Int(7_" $t ").factors_prime_count(), 1];"]
261 /// ```
262 #[must_use]
263 pub fn factors_prime_count(self) -> usize {
264 let mut n = self.0.abs();
265 iif![n == 0; return 0];
266 let mut count = 0;
267 // Divide by 2 until the number is odd
268 while n % 2 == 0 {
269 count += 1;
270 n /= 2;
271 }
272 // Divide by odd numbers starting from 3
273 let mut i = 3;
274 while i * i <= n {
275 while n % i == 0 {
276 count += 1;
277 n /= i;
278 }
279 i += 2;
280 }
281 // If the remaining number is greater than 2, it's a prime factor
282 iif![n > 2; count += 1];
283 count
284 }
285
286 /// Returns the count of unique prime factors.
287 ///
288 /// # Examples
289 /// ```
290 /// # use devela::Int;
291 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique_count(), 2];"]
292 #[doc = "assert_eq![Int(-24_" $t ").factors_prime_unique_count(), 2];"]
293 /// ```
294 #[must_use]
295 pub fn factors_prime_unique_count(self) -> usize {
296 let mut n = self.0.abs();
297 iif![n == 0; return 0];
298 let mut count = 0;
299 let mut last = 0;
300
301 // Divide by 2 until the number is odd
302 while n % 2 == 0 {
303 iif![last != 2; { count += 1; last = 2 }];
304 n /= 2;
305 }
306 // Divide by odd numbers starting from 3
307 let mut i = 3;
308 while i * i <= n {
309 while n % i == 0 {
310 iif![last != i; { count += 1; last = i }];
311 n /= i;
312 }
313 i += 2;
314 }
315 // If the remaining number is greater than 2,
316 // and not the same as the last factor, it's a prime factor
317 if n > 2 && last != n {
318 count += 1;
319 }
320 count
321 }
322
323 /// Writes the factors in `fbuf`, and the unique prime factors in `upfbuf`.
324 ///
325 /// Returns a tuple with the number of factors and unique prime factors found.
326 ///
327 /// # Errors
328 /// Returns [`MismatchedSizes`] if the total number of factors is greater
329 /// than the length of any buffer.
330 ///
331 /// # Examples
332 /// ```
333 /// # use devela::Int;
334 /// let (mut fbuf, mut upbuf) = ([0; 20], [0; 20]);
335 #[doc = "assert_eq![Int(24_" $t ").factors_buf(&mut fbuf, &mut upbuf), Ok((8, 2))];"]
336 ///
337 /// assert_eq![fbuf[..8], [1, 2, 3, 4, 6, 8, 12, 24]];
338 /// assert_eq![upbuf[..2], [2, 3]];
339 /// ```
340 pub fn factors_buf(self, fbuf: &mut [$t], upfbuf: &mut [$t])
341 -> Result<(usize, usize)> {
342 let n = self.0.abs();
343 iif![n == 0; return Ok((0, 0))];
344 iif![n == 1; { fbuf[0] = 1; return Ok((1, 0)); }];
345 let mut f_count = 0;
346 fbuf[f_count] = 1;
347 f_count += 1;
348 let prime_factors_count = self.factors_prime_unique_buf(upfbuf)?;
349 for i in 2..=n {
350 if n % i == 0 {
351 if f_count < fbuf.len() {
352 fbuf[f_count] = i;
353 f_count += 1;
354 } else {
355 return Err(MismatchedSizes);
356 }
357 }
358 }
359 Ok((f_count, prime_factors_count))
360 }
361
362 /// Writes the proper factors in `fbuf`, and the unique prime factors in `upfbuf`.
363 ///
364 /// Returns a tuple with the number of factors and unique prime factors found.
365 ///
366 /// # Errors
367 /// Returns [`MismatchedSizes`] if the total number of factors is greater
368 /// than the length of any buffer.
369 ///
370 /// # Examples
371 /// ```
372 /// # use devela::Int;
373 /// let (mut fbuf, mut upbuf) = ([0; 20], [0; 20]);
374 #[doc = "assert_eq![Int(24_" $t
375 ").factors_proper_buf(&mut fbuf, &mut upbuf), Ok((6, 2))];"]
376 ///
377 /// assert_eq![fbuf[..6], [2, 3, 4, 6, 8, 12,]];
378 /// assert_eq![upbuf[..2], [2, 3]];
379 /// ```
380 pub fn factors_proper_buf(self, fbuf: &mut [$t], upfbuf: &mut [$t])
381 -> Result<(usize, usize)> {
382 let n = self.0.abs();
383 iif![n == 0; return Ok((0, 0))];
384 iif![n == 1; { fbuf[0] = 1; return Ok((1, 0)); }];
385 let mut f_count = 0;
386 let prime_factors_count = self.factors_prime_unique_buf(upfbuf)?;
387 for i in 2..n {
388 if n % i == 0 {
389 if f_count < fbuf.len() {
390 fbuf[f_count] = i;
391 f_count += 1;
392 } else {
393 return Err(MismatchedSizes);
394 }
395 }
396 }
397 Ok((f_count, prime_factors_count))
398 }
399
400 /// Writes the prime factors in the given `buffer`.
401 ///
402 /// Returns the number of factors found
403 ///
404 /// # Errors
405 /// Returns [`MismatchedSizes`] if the total number of factors
406 /// is greater than the length of the `buffer`.
407 ///
408 /// # Examples
409 /// ```
410 /// # use devela::Int;
411 /// let mut buf = [0; 5];
412 #[doc = "assert_eq![Int(24_" $t ").factors_prime_buf(&mut buf), Ok(4)];"]
413 ///
414 /// assert_eq![buf[..4], [2, 2, 2, 3]];
415 #[doc = "assert![Int(24_" $t " * 4).factors_prime_buf(&mut buf).is_err()];"]
416 /// assert_eq![buf, [2, 2, 2, 2, 2]]; // the factor of 3 didn't fit
417 ///
418 #[doc = "assert_eq![Int(0_" $t ").factors_prime_buf(&mut buf), Ok(0)];"]
419 #[doc = "assert_eq![Int(1_" $t ").factors_prime_buf(&mut buf), Ok(0)];"]
420 #[doc = "assert_eq![Int(7_" $t ").factors_prime_buf(&mut buf), Ok(1)];"]
421 /// assert_eq![buf[..1], [7]];
422 /// ```
423 pub fn factors_prime_buf(self, buffer: &mut [$t]) -> Result<usize> {
424 iif![self.0 == 0; return Ok(0)];
425 let (mut n, mut idx) = (self.0.abs(), 0);
426 while n % 2 == 0 {
427 if idx < buffer.len() {
428 buffer[idx] = 2; idx += 1; n /= 2;
429 } else {
430 return Err(MismatchedSizes);
431 }
432 }
433 let mut i = 3;
434 while i * i <= n {
435 while n % i == 0 {
436 if idx < buffer.len() {
437 buffer[idx] = i; idx += 1; n /= i;
438 } else {
439 return Err(MismatchedSizes);
440 }
441 }
442 i += 2;
443 }
444 if n > 2 {
445 if idx < buffer.len() {
446 buffer[idx] = n; idx += 1;
447 } else {
448 return Err(MismatchedSizes);
449 }
450 }
451 Ok(idx)
452 }
453
454 /// Writes the prime factors in the given `buffer`.
455 ///
456 /// The `buffer` must be large enough to hold all the non-unique factors of `n`.
457 /// In that case the function will return the number of unique factors found.
458 ///
459 /// # Errors
460 /// Returns [`MismatchedSizes`] otherwise. In that case the buffer
461 /// will only contain the non-unique factors that could fit, same as
462 #[doc = "[`factors_prime_buf`](#method.factors_prime_buf" $d ")."]
463 ///
464 /// # Examples
465 /// ```
466 /// # use devela::Int;
467 /// let mut uniq = [0; 5];
468 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique_buf(&mut uniq), Ok(2)];"]
469 /// assert_eq![uniq, [2, 3, 2, 3, 0]];
470 /// ```
471 pub fn factors_prime_unique_buf(self, buffer: &mut [$t]) -> Result<usize> {
472 let prime_factors_count = self.factors_prime_buf(buffer)?;
473 let mut unique_count = 1;
474 let mut last_unique = buffer[0];
475 for i in 1..prime_factors_count {
476 if buffer[i] != last_unique {
477 if unique_count < buffer.len() {
478 buffer[unique_count] = buffer[i];
479 last_unique = buffer[i];
480 unique_count += 1;
481 } else {
482 return Err(MismatchedSizes);
483 }
484 }
485 }
486 Ok(unique_count)
487 }
488
489 /// Writes the unique prime factors in the given `fbuffer`, and the
490 /// associated exponent in the given `ebuffer` at the same index.
491 ///
492 /// The `fbuffer` must be large enough to hold all the non-unique factors of `n`.
493 /// In that case the function will return the number of unique factors found.
494 ///
495 /// # Errors
496 /// Returns [`MismatchedSizes`] otherwise. In that case the buffer
497 /// will only contain the non-unique factors that could fit, same as
498 #[doc = "[`factors_prime_buf`](#method.factors_prime_buf" $d ")."]
499 ///
500 /// Returns [`MismatchedSizes`] if `ebuffer` is not large enough as well.
501 /// In that case the number of unique factors will equal `ebuffer.len()`.
502 ///
503 /// # Examples
504 /// ```
505 /// # use devela::Int;
506 /// let mut fbuf = [0; 4];
507 /// let mut ebuf = [0; 2];
508 #[doc = "assert_eq![Int(40_" $t
509 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(2)];"]
510 /// assert_eq![fbuf[..2], [2, 5]]; // 2^3, 5^1, …
511 /// assert_eq![ebuf[..2], [3, 1]];
512 ///
513 #[doc = "assert_eq![Int(0_" $t
514 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(0)];"]
515 #[doc = "assert_eq![Int(1_" $t
516 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(0)];"]
517 #[doc = "assert_eq![Int(7_" $t
518 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(1)];"]
519 /// assert_eq![fbuf[..1], [7]]; // 7^1
520 /// assert_eq![ebuf[..1], [1]];
521 ///
522 /// // When `fbuffer` is not large enough:
523 /// let mut fbuf = [0; 3];
524 /// let mut ebuf = [0; 2];
525 #[doc = "assert![Int(24_" $t
526 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf).is_err()];"]
527 /// assert_eq![fbuf, [2, 2, 2]]; // the factor of 5 didn't fit
528 /// assert_eq![ebuf, [0, 0]]; // the exponents didn't get written
529 ///
530 /// // When `ebuffer` is not large enough:
531 /// let mut fbuf = [0; 4];
532 /// let mut ebuf = [0; 1];
533 #[doc = "assert![Int(24_" $t
534 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf).is_err()];"]
535 /// assert_eq![fbuf[..ebuf.len()], [2]]; // 2^3, Err, …
536 /// assert_eq![ebuf[..], [3]];
537 /// ```
538 // IMPROVE: differenciate between both errors more clearly.
539 pub fn factors_prime_unique_exp_buf(self, fbuffer: &mut [$t], ebuffer: &mut [u32])
540 -> Result<usize> {
541 let prime_factors_count = self.factors_prime_buf(fbuffer)?;
542 iif![prime_factors_count == 0; return Ok(0)];
543
544 let mut current_factor = fbuffer[0]; // current factor
545 let mut unique_idx = 0; // current unique factor index
546 let mut exp_count = 1; //
547
548 for i in 1..prime_factors_count {
549 // Same factor as before, increment the exponent count
550 if fbuffer[i] == current_factor {
551 exp_count += 1;
552 } else {
553 // New factor found, store the previous factor and its exp_count
554 fbuffer[unique_idx] = current_factor;
555 iif![unique_idx >= ebuffer.len(); return Err(MismatchedSizes)];
556 ebuffer[unique_idx] = exp_count;
557 unique_idx += 1; // Move to the next unique factor
558
559 // Reset for the new factor
560 current_factor = fbuffer[i];
561 exp_count = 1;
562 }
563 }
564 // Store the last factor and its exponent count
565 if unique_idx < fbuffer.len() && unique_idx < ebuffer.len() {
566 fbuffer[unique_idx] = current_factor;
567 ebuffer[unique_idx] = exp_count;
568 unique_idx += 1; // increment the index to represent the unique count
569 } else {
570 return Err(MismatchedSizes);
571 }
572 Ok(unique_idx)
573 }
574
575 /// Writes the prime factors in `pfbuf`, and the unique prime factors in `upfbuf`.
576 ///
577 /// Returns the number of factors found.
578 ///
579 /// # Errors
580 /// Returns `MismatchedSizes` if the total number of factors
581 /// is greater than the length of the `buffer`.
582 ///
583 /// # Examples
584 /// ```
585 /// # use devela::Int;
586 /// let (mut fac, mut uniq) = ([0; 5], [0; 5]);
587 #[doc = "assert_eq![Int(24_" $t
588 ").factors_prime_unique_plus_buf(&mut fac, &mut uniq), Ok((4, 2))];"]
589 /// assert_eq![fac, [2, 2, 2, 3, 0]];
590 /// assert_eq![uniq, [2, 3, 0, 0, 0]];
591 /// ```
592 pub fn factors_prime_unique_plus_buf(self, pfbuf: &mut [$t], upfbuf: &mut [$t]
593 ) -> Result<(usize, usize)> {
594 let prime_factors_count = self.factors_prime_buf(pfbuf)?;
595 let mut unique_count = 0;
596 for i in 0..prime_factors_count {
597 let mut unique = true;
598 for j in 0..unique_count {
599 if pfbuf[i] == upfbuf[j] {
600 unique = false;
601 break;
602 }
603 }
604 if unique {
605 if unique_count < upfbuf.len() {
606 upfbuf[unique_count] = pfbuf[i];
607 unique_count += 1;
608 } else {
609 return Err(MismatchedSizes);
610 }
611 }
612 }
613 Ok((prime_factors_count, unique_count))
614 }
615 }
616 }};
617 (
618 // implements unsigned ops
619 @unsigned $t:ty : $cap:literal | $d:literal) => { paste! {
620 #[doc = crate::doc_availability!(feature = $cap)]
621 ///
622 #[doc = "# Integer factors related methods for `" $t "`\n\n"]
623 /// - Allocating:
624 #[doc = " - [factors](#method.factors" $d ")"]
625 #[doc = " - [factors_proper](#method.factors_proper" $d ")"]
626 #[doc = " - [factors_prime](#method.factors_prime" $d ")"]
627 #[doc = " - [factors_prime_unique](#method.factors_prime_unique" $d ")"]
628 /// - Not allocating:
629 #[doc = " - [factors_buf](#method.factors_buf" $d ")"]
630 #[doc = " - [factors_proper_buf](#method.factors_proper_buf" $d ")"]
631 #[doc = " - [factors_prime_buf](#method.factors_prime_buf" $d ")"]
632 #[doc = " - [factors_prime_unique_buf](#method.factors_prime_unique_buf" $d ")"]
633 ///
634 #[cfg(feature = $cap )]
635 impl Int<$t> {
636 /* unsigned factors alloc */
637
638 /// Returns the factors (including 1 and self).
639 ///
640 /// # Examples
641 /// ```
642 /// # use devela::Int;
643 #[doc = "assert_eq![Int(24_" $t ").factors(), vec![1, 2, 3, 4, 6, 8, 12, 24]];"]
644 #[doc = "assert![Int(0_" $t ").factors().is_empty()];"]
645 #[doc = "assert_eq![Int(1_" $t ").factors(), vec![1]];"]
646 #[doc = "assert_eq![Int(7_" $t ").factors(), vec![1, 7]];"]
647 /// ```
648 #[must_use]
649 #[cfg(feature = "alloc")]
650 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
651 pub fn factors(self) -> Vec<$t> {
652 let n = self.0;
653 iif![n == 0; return vec![]; iif![n == 1; return vec![1]]];
654 let mut set = BTreeSet::new();
655 set.insert(1);
656 for p in self.factors_prime_unique() {
657 let temp = set.clone();
658 let mut x = p;
659 while x <= n {
660 for &num in &temp {
661 let new_num = num * x;
662 if n % new_num == 0 {
663 set.insert(new_num);
664 }
665 }
666 x *= p;
667 }
668 }
669 set.into_iter().collect()
670 }
671
672 /// Returns the proper factors.
673 ///
674 /// # Examples
675 /// ```
676 /// # use devela::Int;
677 #[doc = "assert_eq![Int(24_" $t ").factors_proper(), vec![2, 3, 4, 6, 8, 12]];"]
678 #[doc = "assert![Int(0_" $t ").factors_proper().is_empty()];"]
679 #[doc = "assert![Int(1_" $t ").factors_proper().is_empty()];"]
680 #[doc = "assert![Int(7_" $t ").factors_proper().is_empty()];"]
681 /// ```
682 #[must_use]
683 #[cfg(feature = "alloc")]
684 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
685 pub fn factors_proper(self) -> Vec<$t> {
686 let n = self.0;
687 iif![n == 0; return vec![]];
688 let mut set = BTreeSet::new();
689 set.insert(1);
690 for p in self.factors_prime_unique() {
691 let temp = set.clone();
692 let mut x = p;
693 while x <= n {
694 for &num in &temp {
695 let new_num = num * x;
696 if n % new_num == 0 {
697 set.insert(new_num);
698 }
699 }
700 x *= p;
701 }
702 }
703 set.remove(&1);
704 set.remove(&n);
705 set.into_iter().collect()
706 }
707
708 /// Returns the prime factors.
709 ///
710 /// # Examples
711 /// ```
712 /// # use devela::Int;
713 #[doc = "assert_eq![Int(24_" $t ").factors_prime(), vec![2, 2, 2, 3]];"]
714 #[doc = "assert![Int(0_" $t ").factors_prime().is_empty()];"]
715 #[doc = "assert![Int(1_" $t ").factors_prime().is_empty()];"]
716 #[doc = "assert_eq![Int(7_" $t ").factors_prime(), vec![7]];"]
717 /// ```
718 #[must_use]
719 #[cfg(feature = "alloc")]
720 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
721 pub fn factors_prime(self) -> Vec<$t> {
722 let mut factors = Vec::new();
723 let mut n = self.0;
724 iif![n == 0; return factors];
725
726 // Divide by 2 until the number is odd
727 while n % 2 == 0 {
728 factors.push(2);
729 n /= 2;
730 }
731 // Divide by odd numbers starting from 3
732 let mut i = 3;
733 while i * i <= n {
734 while n % i == 0 {
735 factors.push(i);
736 n /= i;
737 }
738 i += 2;
739 }
740 // If the remaining number is greater than 2, it's a prime factor
741 iif![n > 2; factors.push(n)];
742 factors
743 }
744
745 /// Returns the unique prime factors.
746 ///
747 /// # Examples
748 /// ```
749 /// # use devela::Int;
750 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique(), vec![2, 3]];"]
751 /// ```
752 #[must_use]
753 #[cfg(feature = "alloc")]
754 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
755 pub fn factors_prime_unique(self) -> Vec<$t> {
756 self.factors_prime().hook_mut(|v| v.dedup())
757 }
758
759 /// Returns the unique prime factors with its exponent.
760 ///
761 /// # Examples
762 /// ```
763 /// # use devela::Int;
764 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique_exp(), vec![(2, 3), (3, 1)]];"]
765 #[doc = "assert![Int(0_" $t ").factors_prime_unique_exp().is_empty()];"]
766 #[doc = "assert![Int(1_" $t ").factors_prime_unique_exp().is_empty()];"]
767 #[doc = "assert_eq![Int(7_" $t ").factors_prime_unique_exp(), vec![(7, 1)]];"]
768 /// ```
769 #[must_use]
770 #[cfg(feature = "alloc")]
771 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
772 pub fn factors_prime_unique_exp(self) -> Vec<($t, u32)> {
773 let mut factors = Vec::new();
774 let mut current = None;
775 let mut count = 0;
776
777 for prime in self.factors_prime() {
778 match current {
779 Some(f) if f == prime => {
780 count += 1;
781 },
782 _ => {
783 if let Some(f) = current {
784 factors.push((f, count));
785 }
786 current = Some(prime);
787 count = 1;
788 },
789 }
790 }
791 if let Some(f) = current {
792 factors.push((f, count));
793 }
794 factors
795 }
796
797 /* unsigned factors non_alloc */
798
799 /// Returns the count of prime factors.
800 ///
801 /// # Examples
802 /// ```
803 /// # use devela::Int;
804 #[doc = "assert_eq![Int(24_" $t ").factors_prime_count(), 4];"]
805 #[doc = "assert_eq![Int(0_" $t ").factors_prime_count(), 0];"]
806 #[doc = "assert_eq![Int(1_" $t ").factors_prime_count(), 0];"]
807 #[doc = "assert_eq![Int(7_" $t ").factors_prime_count(), 1];"]
808 /// ```
809 #[must_use]
810 pub fn factors_prime_count(self) -> usize {
811 let mut n = self.0;
812 iif![n == 0; return 0];
813 let mut count = 0;
814 // Divide by 2 until the number is odd
815 while n % 2 == 0 {
816 count += 1;
817 n /= 2;
818 }
819 // Divide by odd numbers starting from 3
820 let mut i = 3;
821 while i * i <= n {
822 while n % i == 0 {
823 count += 1;
824 n /= i;
825 }
826 i += 2;
827 }
828 // If the remaining number is greater than 2, it's a prime factor
829 iif![n > 2; count += 1];
830 count
831 }
832
833 /// Returns the count of unique prime factors.
834 ///
835 /// # Examples
836 /// ```
837 /// # use devela::Int;
838 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique_count(), 2];"]
839 /// ```
840 #[must_use]
841 pub fn factors_prime_unique_count(self) -> usize {
842 let mut n = self.0;
843 iif![n == 0; return 0];
844 let mut count = 0;
845 let mut last = 0;
846
847 // Divide by 2 until the number is odd
848 while n % 2 == 0 {
849 iif![last != 2; { count += 1; last = 2 }];
850 n /= 2;
851 }
852 // Divide by odd numbers starting from 3
853 let mut i = 3;
854 while i * i <= n {
855 while n % i == 0 {
856 iif![last != i; { count += 1; last = i }];
857 n /= i;
858 }
859 i += 2;
860 }
861 // If the remaining number is greater than 2,
862 // and not the same as the last factor, it's a prime factor
863 if n > 2 && last != n {
864 count += 1;
865 }
866 count
867 }
868
869 /// Writes the factors in `fbuf`, and the unique prime factors in `upfbuf`.
870 ///
871 /// Returns a tuple with the number of factors and unique prime factors found.
872 ///
873 /// # Errors
874 /// Returns [`MismatchedSizes`] if the total number of factors
875 /// is greater than the length of any buffer.
876 ///
877 /// # Examples
878 /// ```
879 /// # use devela::Int;
880 /// let (mut fbuf, mut upbuf) = ([0; 20], [0; 20]);
881 #[doc = "assert_eq![Int(24_" $t ").factors_buf(&mut fbuf, &mut upbuf), Ok((8, 2))];"]
882 ///
883 /// assert_eq![fbuf[..8], [1, 2, 3, 4, 6, 8, 12, 24]];
884 /// assert_eq![upbuf[..2], [2, 3]];
885 /// ```
886 pub fn factors_buf(self, fbuf: &mut [$t], upfbuf: &mut [$t]) -> Result<(usize, usize)> {
887 let n = self.0;
888 iif![n == 0; return Ok((0, 0))];
889 iif![n == 1; { fbuf[0] = 1; return Ok((1, 0)); }];
890 let mut f_count = 0;
891 fbuf[f_count] = 1;
892 f_count += 1;
893 let prime_factors_count = self.factors_prime_unique_buf(upfbuf)?;
894 for i in 2..=n {
895 if n % i == 0 {
896 if f_count < fbuf.len() {
897 fbuf[f_count] = i; f_count += 1;
898 } else {
899 return Err(MismatchedSizes);
900 }
901 }
902 }
903 Ok((f_count, prime_factors_count))
904 }
905
906 /// Writes the proper factors in `fbuf`, and the unique prime factors in `upfbuf`.
907 ///
908 /// Returns a tuple with the number of factors and unique prime factors found.
909 ///
910 /// # Errors
911 /// Returns [`MismatchedSizes`] if the total number of factors
912 /// is greater than the length of any buffer.
913 ///
914 /// # Examples
915 /// ```
916 /// # use devela::Int;
917 /// let (mut fbuf, mut upbuf) = ([0; 20], [0; 20]);
918 #[doc = "assert_eq![Int(24_" $t
919 ").factors_proper_buf(&mut fbuf, &mut upbuf), Ok((6, 2))];"]
920 ///
921 /// assert_eq![fbuf[..6], [2, 3, 4, 6, 8, 12,]];
922 /// assert_eq![upbuf[..2], [2, 3]];
923 /// ```
924 pub fn factors_proper_buf(self, fbuf: &mut [$t], upfbuf: &mut [$t]
925 ) -> Result<(usize, usize)> {
926 let n = self.0;
927 iif![n == 0; return Ok((0, 0))];
928 iif![n == 1; { fbuf[0] = 1; return Ok((1, 0)); }];
929 let mut f_count = 0;
930 let prime_factors_count = self.factors_prime_unique_buf(upfbuf)?;
931 for i in 2..n {
932 if n % i == 0 {
933 if f_count < fbuf.len() {
934 fbuf[f_count] = i;
935 f_count += 1;
936 } else {
937 return Err(MismatchedSizes);
938 }
939 }
940 }
941 Ok((f_count, prime_factors_count))
942 }
943
944 /// Writes the prime factors in the given `buffer`.
945 ///
946 /// Returns the number of factors found.
947 ///
948 /// # Errors
949 /// Returns [`MismatchedSizes`] if the total number of factors
950 /// is greater than the length of the `buffer`.
951 ///
952 /// # Examples
953 /// ```
954 /// # use devela::Int;
955 /// let mut buf = [0; 5];
956 #[doc = "assert_eq![Int(24_" $t ").factors_prime_buf(&mut buf), Ok(4)];"]
957 ///
958 /// assert_eq![buf[..4], [2, 2, 2, 3]];
959 #[doc = "assert![Int(24_" $t " * 4).factors_prime_buf(&mut buf).is_err()];"]
960 /// assert_eq![buf, [2, 2, 2, 2, 2]]; // the factor of 3 didn't fit
961 ///
962 #[doc = "assert_eq![Int(0_" $t ").factors_prime_buf(&mut buf), Ok(0)];"]
963 #[doc = "assert_eq![Int(1_" $t ").factors_prime_buf(&mut buf), Ok(0)];"]
964 #[doc = "assert_eq![Int(7_" $t ").factors_prime_buf(&mut buf), Ok(1)];"]
965 /// assert_eq![buf[..1], [7]];
966 /// ```
967 pub fn factors_prime_buf(self, buffer: &mut [$t]) -> Result<usize> {
968 let n = self.0;
969 iif![n == 0; return Ok(0)];
970 let (mut n, mut idx) = (n, 0);
971 while n % 2 == 0 {
972 if idx < buffer.len() {
973 buffer[idx] = 2; idx += 1; n /= 2;
974 } else {
975 return Err(MismatchedSizes);
976 }
977 }
978 let mut i = 3;
979 while i * i <= n {
980 while n % i == 0 {
981 if idx < buffer.len() {
982 buffer[idx] = i; idx += 1; n /= i;
983 } else {
984 return Err(MismatchedSizes);
985 }
986 }
987 i += 2;
988 }
989 if n > 2 {
990 if idx < buffer.len() {
991 buffer[idx] = n; idx += 1;
992 } else {
993 return Err(MismatchedSizes);
994 }
995 }
996 Ok(idx)
997 }
998
999 /// Writes the prime factors in the given `buffer`.
1000 ///
1001 /// The `buffer` must be large enough to hold all the non-unique factors of `n`.
1002 /// In that case the function will return the number of unique factors found.
1003 ///
1004 /// # Errors
1005 /// Returns [`MismatchedSizes`] otherwise. In that case the buffer
1006 /// will only contain the non-unique factors that could fit, same as
1007 #[doc = "[`factors_prime_buf`](#method.factors_prime_buf" $d ")."]
1008 ///
1009 /// # Examples
1010 /// ```
1011 /// # use devela::Int;
1012 /// let mut uniq = [0; 5];
1013 #[doc = "assert_eq![Int(24_" $t ").factors_prime_unique_buf(&mut uniq), Ok(2)];"]
1014 /// assert_eq![uniq, [2, 3, 2, 3, 0]];
1015 /// ```
1016 pub fn factors_prime_unique_buf(self, buffer: &mut [$t]) -> Result<usize> {
1017 let prime_factors_count = self.factors_prime_buf(buffer)?;
1018 let mut unique_count = 1;
1019 let mut last_unique = buffer[0];
1020 for i in 1..prime_factors_count {
1021 if buffer[i] != last_unique {
1022 if unique_count < buffer.len() {
1023 buffer[unique_count] = buffer[i];
1024 last_unique = buffer[i];
1025 unique_count += 1;
1026 } else {
1027 return Err(MismatchedSizes);
1028 }
1029 }
1030 }
1031 Ok(unique_count)
1032 }
1033
1034 /// Writes the unique prime factors in the given `fbuffer`, and the
1035 /// associated exponent in the given `ebuffer` at the same index.
1036 ///
1037 /// The `fbuffer` must be large enough to hold all the non-unique factors of `n`.
1038 /// In that case the function will return the number of unique factors found.
1039 ///
1040 /// # Errors
1041 /// Returns [`MismatchedSizes`] otherwise. In that case the buffer
1042 /// will only contain the non-unique factors that could fit, same as
1043 #[doc = "[`factors_prime_buf`](#method.factors_prime_buf" $d ")."]
1044 ///
1045 /// Returns [`MismatchedSizes`] if `ebuffer` is not large enough as well.
1046 /// In that case the number of unique factors will equal `ebuffer.len()`.
1047 ///
1048 /// # Examples
1049 /// ```
1050 /// # use devela::Int;
1051 /// let mut fbuf = [0; 4];
1052 /// let mut ebuf = [0; 2];
1053 #[doc = "assert_eq![Int(40_" $t
1054 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(2)];"]
1055 /// assert_eq![fbuf[..2], [2, 5]]; // 2^3, 5^1, …
1056 /// assert_eq![ebuf[..2], [3, 1]];
1057 ///
1058 #[doc = "assert_eq![Int(0_" $t
1059 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(0)];"]
1060 #[doc = "assert_eq![Int(1_" $t
1061 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(0)];"]
1062 #[doc = "assert_eq![Int(7_" $t
1063 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf), Ok(1)];"]
1064 /// assert_eq![fbuf[..1], [7]]; // 7^1
1065 /// assert_eq![ebuf[..1], [1]];
1066 ///
1067 /// // When `fbuffer` is not large enough:
1068 /// let mut fbuf = [0; 3];
1069 /// let mut ebuf = [0; 2];
1070 #[doc = "assert![Int(24_" $t
1071 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf).is_err()];"]
1072 /// assert_eq![fbuf, [2, 2, 2]]; // the factor of 5 didn't fit
1073 /// assert_eq![ebuf, [0, 0]]; // the exponents didn't get written
1074 ///
1075 /// // When `ebuffer` is not large enough:
1076 /// let mut fbuf = [0; 4];
1077 /// let mut ebuf = [0; 1];
1078 #[doc = "assert![Int(24_" $t
1079 ").factors_prime_unique_exp_buf(&mut fbuf, &mut ebuf).is_err()];"]
1080 /// assert_eq![fbuf[..ebuf.len()], [2]]; // 2^3, Err, …
1081 /// assert_eq![ebuf[..], [3]];
1082 /// ```
1083 // IMPROVE: differenciate between both errors more clearly.
1084 pub fn factors_prime_unique_exp_buf(self, fbuffer: &mut [$t], ebuffer: &mut [u32])
1085 -> Result<usize> {
1086 let prime_factors_count = self.factors_prime_buf(fbuffer)?;
1087 iif![prime_factors_count == 0; return Ok(0)];
1088
1089 let mut current_factor = fbuffer[0]; // current factor
1090 let mut unique_idx = 0; // current unique factor index
1091 let mut exp_count = 1; //
1092
1093 for i in 1..prime_factors_count {
1094 // Same factor as before, increment the exponent count
1095 if fbuffer[i] == current_factor {
1096 exp_count += 1;
1097 } else {
1098 // New factor found, store the previous factor and its exp_count
1099 fbuffer[unique_idx] = current_factor;
1100 iif![unique_idx >= ebuffer.len(); return Err(MismatchedSizes)];
1101 ebuffer[unique_idx] = exp_count;
1102 unique_idx += 1; // Move to the next unique factor
1103
1104 // Reset for the new factor
1105 current_factor = fbuffer[i];
1106 exp_count = 1;
1107 }
1108 }
1109 // Store the last factor and its exponent count
1110 if unique_idx < fbuffer.len() && unique_idx < ebuffer.len() {
1111 fbuffer[unique_idx] = current_factor;
1112 ebuffer[unique_idx] = exp_count;
1113 unique_idx += 1; // increment the index to represent the unique count
1114 } else {
1115 return Err(MismatchedSizes);
1116 }
1117 Ok(unique_idx)
1118 }
1119
1120 /// Writes the prime factors in `pfbuf`, and the unique factors in `upfbuf`.
1121 ///
1122 /// Returns the number of factors found.
1123 ///
1124 /// # Errors
1125 /// Returns [`MismatchedSizes`] if the total number of factors
1126 /// is greater than the length of the `buffer`.
1127 ///
1128 /// # Examples
1129 /// ```
1130 /// # use devela::Int;
1131 /// let (mut fac, mut uniq) = ([0; 5], [0; 5]);
1132 #[doc = "assert_eq![Int(24_" $t
1133 ").factors_prime_unique_plus_buf(&mut fac, &mut uniq), Ok((4, 2))];"]
1134 /// assert_eq![fac, [2, 2, 2, 3, 0]];
1135 /// assert_eq![uniq, [2, 3, 0, 0, 0]];
1136 /// ```
1137 pub fn factors_prime_unique_plus_buf(self, pfbuf: &mut [$t], upfbuf: &mut [$t]
1138 ) -> Result<(usize, usize)> {
1139 let prime_factors_count = self.factors_prime_buf(pfbuf)?;
1140 let mut unique_count = 0;
1141 for i in 0..prime_factors_count {
1142 let mut unique = true;
1143 for j in 0..unique_count {
1144 if pfbuf[i] == upfbuf[j] {
1145 unique = false;
1146 break;
1147 }
1148 }
1149 if unique {
1150 if unique_count < upfbuf.len() {
1151 upfbuf[unique_count] = pfbuf[i];
1152 unique_count += 1;
1153 } else {
1154 return Err(MismatchedSizes);
1155 }
1156 }
1157 }
1158 Ok((prime_factors_count, unique_count))
1159 }
1160 }
1161 }};
1162}
1163impl_factors!();