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}