1pub trait Factors: Sized {
2 fn factors(self) -> impl Iterator<Item = ((Self, u32), Self)>;
3}
4
5pub trait FactorsDup: Sized {
6 fn factors_dup(self) -> impl Iterator<Item = Self>;
7}
8
9macro_rules! impl_uint {
10 ( $($ty:ty)* ) => { $(
11 impl Factors for $ty {
12 fn factors(self) -> impl Iterator<Item = ((Self, u32), Self)> {
13 let n = self;
14 std::iter::successors(
15 (n >= 1).then_some((((1, 0), 1), n)),
16 move |&(((i, _), _), n)| {
17 if let Some(j) =
18 (i + 1..).take_while(|j| j * j <= n).find(|j| n % j == 0)
19 {
20 let (jj, e) =
21 std::iter::successors(Some((j, 1)), |&(jj, e)| {
22 (n / jj % j == 0).then(|| (jj * j, e + 1))
23 })
24 .last()
25 .unwrap();
26 Some((((j, e), jj), n / jj))
27 } else if n > 1 {
28 Some((((n, 1), n), 1))
29 } else {
30 None
31 }
32 },
33 )
34 .skip(1)
35 .map(move |(i, _)| i)
36 }
37 }
38
39 impl FactorsDup for $ty {
40 fn factors_dup(self) -> impl Iterator<Item = Self> {
41 let n = self;
42 std::iter::successors((n >= 1).then_some((1, n)), move |&(i, n)| {
43 if let Some(j) =
44 (i.max(2)..).take_while(|j| j * j <= n).find(|j| n % j == 0)
45 {
46 Some((j, n / j))
47 } else if n > 1 {
48 Some((n, 1))
49 } else {
50 None
51 }
52 })
53 .skip(1)
54 .map(move |(i, _)| i)
55 }
56 }
57 )* };
58}
59
60impl_uint! { u8 u16 u32 u64 u128 usize }
61
62#[test]
63fn sanity_check() {
64 assert!(0_u32.factors_dup().eq(None));
65
66 let n_max = 10000;
67 let primes: Vec<_> = {
68 let mut is_prime = vec![true; n_max + 1];
69 is_prime[0] = false;
70 is_prime[1] = false;
71 for n in 2..=n_max {
72 for i in n..=n_max / n {
73 is_prime[i * n] = false;
74 }
75 }
76 (2..=n_max).filter(|&n| is_prime[n]).collect()
77 };
78 let expected = {
79 let mut res = vec![vec![]; n_max + 1];
80 for n in 2..=n_max {
81 let mut n_ = n;
82 for &p in &primes {
83 while n_ % p == 0 {
84 n_ /= p;
85 res[n].push(p);
86 }
87 }
88 }
89 res
90 };
91
92 for n in 1..=n_max {
93 let actual = n.factors_dup();
94 assert!(actual.eq(expected[n].iter().copied()));
95
96 let expected_dedup = {
97 let mut tmp: Vec<_> = n.factors_dup().collect();
98 tmp.dedup();
99 tmp
100 };
101 let actual_dedup = n.factors().map(|((p, _), _)| p);
102 assert!(actual_dedup.eq(expected_dedup));
103
104 for ((p, e), pp) in n.factors() {
105 assert_eq!(n / (pp / p) % p, 0);
106 assert_ne!(n / pp % p, 0);
107 assert_eq!(pp, p.pow(e));
108 }
109 }
110}