use beetle_nonzero::NonZeroUnchecked;
use crate::{divide_while_even, Collatz};
pub fn alpha<T: Collatz>(n: NonZeroUnchecked<T>) -> u32 {
let mut steps = 0;
let mut n = n.value;
while !n.is_one() {
if n.is_odd() {
n = n + n + n + T::one();
steps += 1;
}
n = n / (T::one() + T::one());
steps += 1;
}
steps
}
pub fn omega<T: Collatz>(n: NonZeroUnchecked<T>) -> Option<u32> {
if n.value.is_odd() {
omega_n_is_odd(n)
} else {
omega_n_is_even(n)
}
}
pub fn omega_n_is_even<T: Collatz>(n: NonZeroUnchecked<T>) -> Option<u32> {
let mut steps = n.value.trailing_zeros();
let n = divide_while_even(n)?;
steps += omega_n_is_odd(n)?;
Some(steps)
}
pub fn omega_n_is_odd<T: Collatz>(n: NonZeroUnchecked<T>) -> Option<u32> {
let mut steps = 0;
let mut n = n.value;
while !n.is_one() {
let m = n + n + n + T::one();
let zeros = m.trailing_zeros();
n = m >> zeros.try_into().ok()?;
steps += zeros + 1;
}
Some(steps)
}