1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//! Contains functions that apply the rules of the collatz conjecture until a number reaches one
use beetle_nonzero::NonZeroUnchecked;

use crate::Collatz;

/**
Applies the rules of the collatz conjecture until a number reaches one,
returning whether it succeeds or not.
Success is marked by a number reaching one, and no errors along the way.

This exists for benchmarking other faster functions' speed relative this one.
This aims to always be a correct implementation, but not very fast.
Do not use if performance is important to you.
*/
pub fn alpha<T: Collatz>(mut n: NonZeroUnchecked<T>) -> bool {
    while !n.value.is_one() {
        // If rules::basic returns None,
        // return false immediately,
        // because it means something has gone wrong.
        if let Some(m) = crate::rules::basic(n) {
            n = m;
        } else {
            return false;
        }
    }
    true
}

/**
fall::alpha but MUCH FASTER.
Assumes you have already checked all numbers < START
*/
pub fn omega<T: Collatz>(start: NonZeroUnchecked<T>) -> bool {
    let start = start.value;
    let mut n = start;
    while n >= start {
        let trailing_zeros: usize;
        if let Ok(tz) = usize::try_from(n.trailing_zeros()) {
            trailing_zeros = tz;
        } else {
            return false;
        }
        n = n >> trailing_zeros;
        n = n + n + n + T::one();
    }
    true
}