use bencher::*;
use tailcall::*;
fn is_even_loop(x: u128) -> bool {
let mut i: u128 = x;
let mut even = true;
while i > 0 {
i -= 1;
even = !even;
}
even
}
fn is_odd_loop(x: u128) -> bool {
!is_even_loop(x)
}
#[tailcall]
fn is_odd_rec_go(x: u128, odd: bool) -> bool {
if x > 0 {
tailcall::call! { is_odd_rec_go(x - 1, !odd) }
} else {
odd
}
}
fn is_odd_rec(x: u128) -> bool {
is_odd_rec_go(x, false)
}
#[tailcall]
fn is_odd_rec_res_go(x: u128, odd: Result<bool, ()>) -> Result<bool, ()> {
if x > 0 {
match odd {
Ok(odd) => tailcall::call! { is_odd_rec_res_go(x - 1, Ok(!odd)) },
Err(err) => Err(err),
}
} else {
odd
}
}
fn is_odd_res_rec(x: u128) -> bool {
is_odd_rec_res_go(x, Ok(false)).unwrap()
}
fn is_odd_boom_go(x: u128, odd: bool) -> bool {
if x > 0 {
is_odd_boom_go(x - 1, !odd)
} else {
odd
}
}
fn is_odd_boom(x: u128) -> bool {
is_odd_boom_go(x, false)
}
#[tailcall]
fn is_even_mutrec(x: u128) -> bool {
if x > 0 {
tailcall::call! { is_odd_mutrec(x - 1) }
} else {
true
}
}
#[tailcall]
fn is_odd_mutrec(x: u128) -> bool {
if x > 0 {
tailcall::call! { is_even_mutrec(x - 1) }
} else {
false
}
}
const ODD_TEST_NUM: u128 = 1000000;
fn bench_oddness_loop(b: &mut Bencher) {
let mut val: u128 = ODD_TEST_NUM;
b.iter(|| {
is_odd_loop(val);
val += 1;
});
}
fn bench_oddness_rec(b: &mut Bencher) {
let mut val: u128 = ODD_TEST_NUM;
b.iter(|| {
is_odd_rec(val);
val += 1;
});
}
fn bench_oddness_res_rec(b: &mut Bencher) {
let mut val: u128 = ODD_TEST_NUM;
b.iter(|| {
is_odd_res_rec(val);
val += 1;
});
}
fn bench_oddness_boom(b: &mut Bencher) {
let mut val: u128 = ODD_TEST_NUM;
b.iter(|| {
is_odd_boom(val);
val += 1;
});
}
fn bench_oddness_mutrec(b: &mut Bencher) {
let mut val: u128 = ODD_TEST_NUM;
b.iter(|| {
is_odd_mutrec(val);
val += 1;
});
}
benchmark_group!(
benches,
bench_oddness_loop,
bench_oddness_rec,
bench_oddness_res_rec,
bench_oddness_boom,
bench_oddness_mutrec
);
benchmark_main!(benches);