Skip to content

Commit

Permalink
divisors
Browse files Browse the repository at this point in the history
  • Loading branch information
rsk0315 committed Feb 12, 2024
1 parent 0d508d1 commit e9a54ed
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 0 deletions.
1 change: 1 addition & 0 deletions nekolib-src/math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ edition = "2021"
inner = { path = "../inner" }
modint = { path = "modint" }
linear_sieve = { path = "linear_sieve" }
divisors = { path = "divisors" }
6 changes: 6 additions & 0 deletions nekolib-src/math/divisors/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "divisors"
version = "0.1.0"
edition = "2021"

[dependencies]
44 changes: 44 additions & 0 deletions nekolib-src/math/divisors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
trait Divisors {
fn divisors(self) -> impl Iterator<Item = Self>;
}

macro_rules! impl_uint {
( $($ty:ty)* ) => { $(
impl Divisors for $ty {
fn divisors(self) -> impl Iterator<Item = Self> {
let n = self;
std::iter::successors(
(n >= 1).then_some((1, true)),
move |&(i, asc)| {
if asc {
if let Some(j) = (i + 1..)
.take_while(|j| j * j <= n)
.find(|j| n % j == 0)
{
return Some((j, true));
} else if n / i != i {
return Some((i, false));
}
}
let j = (1..i).rev().find(|&j| n % j == 0)?;
Some((j, false))
},
)
.map(move |(i, asc)| if asc { i } else { n / i })
}
}
)* };
}

impl_uint! { u8 u16 u32 u64 u128 usize }

#[test]
fn sanity_check() {
assert!(0_u32.divisors().eq(None));

for n in 1_u32..=10000 {
let expected = (1..=n).filter(|i| n % i == 0);
let actual = n.divisors();
assert!(actual.eq(expected));
}
}
1 change: 1 addition & 0 deletions nekolib-src/math/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use inner::doc_inline_reexport;

doc_inline_reexport! {
divisors,
linear_sieve,
modint,
}

0 comments on commit e9a54ed

Please sign in to comment.