use num_integer::Roots;
use num_traits::{PrimInt, Unsigned};
pub fn factor<T: PrimInt + Unsigned + Roots>(n: T) -> Vec<T> {
let mut factors: Vec<T> = Vec::new();
let zero = T::zero();
let one = T::one();
let two = one + one;
if n == zero {
return factors;
}
factors.push(one);
let root_n = n.sqrt();
let mut factor = two;
while factor <= root_n {
if n % factor == zero {
factors.push(factor);
}
factor = factor + one;
}
let is_square = root_n * root_n == n;
let mid = factors.len();
for index in (0..mid).rev() {
let factor = factors[index];
if !(is_square && factor == root_n) {
factors.push(n / factor);
}
}
factors
}
pub fn proper_factor<T: PrimInt + Unsigned + Roots>(n: T) -> Vec<T> {
let mut factors: Vec<T> = Vec::new();
let zero = T::zero();
let one = T::one();
let two = one + one;
if n < two {
return factors;
}
factors.push(one);
let root_n = n.sqrt();
let mut factor = two;
while factor <= root_n {
if n % factor == zero {
factors.push(factor);
}
factor = factor + one;
}
let is_square = root_n * root_n == n;
let mid = factors.len();
for index in (1..mid).rev() {
let factor = factors[index];
if !(is_square && factor == root_n) {
factors.push(n / factor);
}
}
factors
}
pub fn exclusive_factor<T: PrimInt + Unsigned + Roots>(n: T) -> Vec<T> {
let mut factors: Vec<T> = Vec::new();
let zero = T::zero();
let one = T::one();
let two = one + one;
if n < two + two {
return factors;
}
let root_n = n.sqrt();
let mut factor = two;
while factor <= root_n {
if n % factor == zero {
factors.push(factor);
}
factor = factor + one;
}
let is_square = root_n * root_n == n;
let mid = factors.len();
for index in (0..mid).rev() {
let factor = factors[index];
if !(is_square && factor == root_n) {
factors.push(n / factor);
}
}
factors
}
pub fn is_prime<T: PrimInt + Unsigned + Roots>(n: T) -> bool {
let zero = T::zero();
let one = T::one();
let two = one + one;
if n < two {
return false;
}
let root_n = n.sqrt();
let mut factor = two;
while factor <= root_n {
if n % factor == zero {
return false;
}
factor = factor + one;
}
true
}