use rspl::streams::infinite_lists::InfiniteList;
use rspl::streams::print;
use rspl::streams::Stream;
use rspl::StreamProcessor;
#[test]
fn test_demands() {
const IMPORTANT_NUMBER_REFERENCE: f64 = 12.077_005_857;
const EPS: f64 = 0.001;
const STEPS_SQRT2: usize = 10;
const STEPS_PI: usize = 5;
const STEPS_EXP: usize = 10;
fn babylon2<'a>(x: f64) -> StreamProcessor<'a, (), f64> {
StreamProcessor::put(x, move || babylon2((x + 2.0 / x) / 2.0))
}
fn bbp<'a>(partial_sum: f64, k: u32) -> StreamProcessor<'a, (), f64> {
let bbp_sequence = |k| {
(1.0 / f64::from(i32::pow(16, k)))
* (4.0 / f64::from(8 * k + 1)
- 2.0 / f64::from(8 * k + 4)
- 1.0 / f64::from(8 * k + 5)
- 1.0 / f64::from(8 * k + 6))
};
StreamProcessor::put(partial_sum, move || {
bbp(partial_sum + bbp_sequence(k), k + 1)
})
}
fn euler<'a>(partial_sum: f64, k: u32, kfac: u32) -> StreamProcessor<'a, (), f64> {
let euler_sequence = |kfac| 1.0 / f64::from(kfac);
StreamProcessor::put(partial_sum, move || {
euler(partial_sum + euler_sequence(kfac), k + 1, kfac * (k + 1))
})
}
let sqrt2 = *print(babylon2(1.0).eval(InfiniteList::constant(())), STEPS_SQRT2).head();
let pi = *print(bbp(0.0, 0).eval(InfiniteList::constant(())), STEPS_PI).head();
let exp = *print(euler(1.0, 1, 1).eval(InfiniteList::constant(())), STEPS_EXP).head();
let important_number = sqrt2 * pi * exp;
assert!(f64::abs(important_number - IMPORTANT_NUMBER_REFERENCE) < EPS);
}