#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[allow(clippy::mut_range_bound)]
fn factorize(mut n: u32) -> Vec<u32> {
let mut result = Vec::new();
'outer: while n > 1 {
let last = result.last().cloned();
for i in last.unwrap_or(2)..n {
if n % i == 0 {
if last != Some(i) {
result.push(i)
}
n /= i;
continue 'outer;
}
if i * i > n {
break;
}
}
if result.last() != Some(&n) {
result.push(n)
}
break;
}
result
}
pub fn generate_a(m_base: u32) -> u32 {
let factors = factorize(m_base);
let mut prod = factors.into_iter().rfold(1, |lhs, rhs| lhs * rhs);
if m_base % 2 == 0 {
prod *= 2
}
prod + 1
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct LinearCongruentMultiplier {
first: u64,
next: u64,
pub m: u64,
c: u64,
a: u64,
exhausted: bool,
}
impl LinearCongruentMultiplier {
pub fn new(seed: u64, m: u64, c: u64, a: u64) -> Self {
Self {
first: seed,
next: seed,
m,
c,
a,
exhausted: false,
}
}
pub fn next(&mut self) -> u64 {
let value = self.next;
self.next = (self.a * self.next + self.c) % self.m;
if self.next == self.first {
self.exhausted = true;
}
value
}
pub fn exhausted(&self) -> bool {
self.exhausted
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_factorize() {
assert_eq!(vec![2], factorize(2));
assert_eq!(vec![3], factorize(3));
assert_eq!(vec![2], factorize(4));
assert_eq!(vec![2, 5], factorize(10));
assert_eq!(vec![3, 5], factorize(15));
assert_eq!(vec![3], factorize(27));
assert_eq!(vec![3, 37], factorize(111));
assert_eq!(vec![269], factorize(269));
}
#[test]
fn test_generate_a() {
assert_eq!(13, generate_a(6));
assert_eq!(8, generate_a(7));
assert_eq!(34, generate_a(99));
assert_eq!(53, generate_a(26));
}
}