Skip to main content

stern_bijection/
lib.rs

1#![no_std]
2
3use num_integer::Integer;
4use num_rational::Ratio;
5use num_traits::One;
6pub fn stern<I: Integer + Clone, J: Integer>(i: I) -> J {
7    if i == I::one() {
8        return J::one();
9    }
10    let i2 = i.clone() / (I::one() + I::one());
11    let j2 = stern(i2.clone());
12    let j2 = if i2.clone() * (I::one() + I::one()) == i {
13        j2
14    } else {
15        j2 + stern(i2 + I::one())
16    };
17    return j2;
18}
19pub fn stern_ratio<I: Integer + Clone, J: Integer>(i: I) -> Ratio<J> {
20    Ratio::new_raw(stern(i.clone()), stern(i + I::one()))
21}
22pub fn destern_ratio<I: Integer + Clone, J: Integer + Clone>(i: Ratio<I>) -> J {
23    match i.numer().cmp(i.denom()) {
24        core::cmp::Ordering::Less => match i.clone() / (Ratio::<I>::one() - i) {
25            x => match destern_ratio::<I, J>(x) {
26                v => v.clone() + v,
27            },
28        },
29        core::cmp::Ordering::Equal => J::one(),
30        core::cmp::Ordering::Greater => match destern_ratio::<I, J>(i - Ratio::<I>::one()) {
31            v => v.clone() + v + J::one(),
32        },
33    }
34}