rspl 0.1.3

A stream processor language.
Documentation
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;

    // compute the square root of 2 via the Babylonian method
    fn babylon2<'a>(x: f64) -> StreamProcessor<'a, (), f64> {
        StreamProcessor::put(x, move || babylon2((x + 2.0 / x) / 2.0))
    }

    // compute pi by Bailey-Borwein-Plouffe formula
    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)
        })
    }

    // compute Euler's number
    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);
}