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!();