1pub trait Divisors: Sized {
2 fn divisors(self) -> impl Iterator<Item = Self>;
3}
4
5macro_rules! impl_uint {
6 ( $($ty:ty)* ) => { $(
7 impl Divisors for $ty {
8 fn divisors(self) -> impl Iterator<Item = Self> {
9 let n = self;
10 std::iter::successors(
11 (n >= 1).then_some((1, true)),
12 move |&(i, asc)| {
13 if asc {
14 if let Some(j) = (i + 1..)
15 .take_while(|j| j * j <= n)
16 .find(|j| n % j == 0)
17 {
18 return Some((j, true));
19 } else if n / i != i {
20 return Some((i, false));
21 }
22 }
23 let j = (1..i).rev().find(|&j| n % j == 0)?;
24 Some((j, false))
25 },
26 )
27 .map(move |(i, asc)| if asc { i } else { n / i })
28 }
29 }
30 )* };
31}
32
33impl_uint! { u8 u16 u32 u64 u128 usize }
34
35#[test]
36fn sanity_check() {
37 assert!(0_u32.divisors().eq(None));
38
39 for n in 1_u32..=10000 {
40 let expected = (1..=n).filter(|i| n % i == 0);
41 let actual = n.divisors();
42 assert!(actual.eq(expected));
43 }
44}