#[expect(clippy::needless_pass_by_value)]
pub fn floyd_partial<T, FS>(start: T, successor: FS) -> (usize, T, usize)
where
T: Clone + PartialEq,
FS: Fn(T) -> T,
{
let mut tortoise = successor(start.clone());
let mut hare = successor(successor(start.clone()));
let mut tortoise_steps = 1;
while tortoise != hare {
(tortoise, hare) = (successor(tortoise), successor(successor(hare)));
tortoise_steps += 1;
}
let mut lam = 1;
hare = successor(tortoise.clone());
while tortoise != hare {
(hare, lam) = (successor(hare), lam + 1);
}
let mu_tilde = if tortoise == start { 0 } else { tortoise_steps };
(lam, tortoise, mu_tilde)
}
pub fn floyd<T, FS>(start: T, successor: FS) -> (usize, T, usize)
where
T: Clone + PartialEq,
FS: Fn(T) -> T,
{
let (lam, mut hare, _) = floyd_partial(start.clone(), &successor);
let (mut mu, mut tortoise) = (0, start);
while tortoise != hare {
(tortoise, hare, mu) = (successor(tortoise), successor(hare), mu + 1);
}
(lam, tortoise, mu)
}
pub fn brent_partial<T, FS>(start: T, successor: FS) -> (usize, T, usize)
where
T: Clone + PartialEq,
FS: Fn(T) -> T,
{
let mut power = 1;
let mut lam = 1;
let mut tortoise = start.clone();
let mut hare = successor(start);
let mut hare_steps = 1;
while tortoise != hare {
if power == lam {
(tortoise, power, lam) = (hare.clone(), power * 2, 0);
}
(hare, lam) = (successor(hare), lam + 1);
hare_steps += 1;
}
(lam, hare, hare_steps)
}
pub fn brent<T, FS>(start: T, successor: FS) -> (usize, T, usize)
where
T: Clone + PartialEq,
FS: Fn(T) -> T,
{
let (lam, _hare, _hare_steps) = brent_partial(start.clone(), &successor);
let mut mu = 0;
let mut tortoise = start.clone();
let mut hare = (0..lam).fold(start, |x, _| successor(x));
while tortoise != hare {
(tortoise, hare, mu) = (successor(tortoise), successor(hare), mu + 1);
}
(lam, hare, mu)
}