conspire 0.7.2

The Rust interface to conspire.
Documentation
use super::{
    E, erf, erfc, inverse_langevin, lambert_w, langevin, rosenbrock, rosenbrock_derivative,
};
use crate::math::assert::Assert;
use crate::math::{Vector, assert::AssertionError};

const LENGTH: usize = 10_000;

mod erf {
    use super::*;
    #[test]
    fn zero() -> Result<(), AssertionError> {
        Assert::eq(erf(0.0), &0.0)
    }
    #[test]
    fn odd_symmetry() -> Result<(), AssertionError> {
        let mut x = 0.0;
        let dx = 10.0 / ((LENGTH + 1) as f64);
        (0..LENGTH).try_for_each(|_| {
            x += dx;
            Assert::default().eq_within_tols(erf(-x), &-erf(x))
        })
    }
    #[test]
    fn saturates_positive() -> Result<(), AssertionError> {
        Assert::eq(erf(1e3), &1.0)
    }
    #[test]
    fn saturates_negative() -> Result<(), AssertionError> {
        Assert::eq(erf(-1e3), &-1.0)
    }
    #[test]
    fn no_overflow_region() -> Result<(), AssertionError> {
        let mut x = -1e3;
        let dx = (1e3 - 27.0) / ((LENGTH + 1) as f64);
        (0..LENGTH).try_for_each(|_| {
            x += dx;
            Assert::eq(erf(x), &-1.0)
        })
    }
}

mod erfc {
    use super::*;
    #[test]
    fn zero() -> Result<(), AssertionError> {
        Assert::eq(erfc(0.0), &1.0)
    }
    #[test]
    fn relation_to_erf() -> Result<(), AssertionError> {
        let mut x = -10.0;
        let dx = 20.0 / ((LENGTH + 1) as f64);
        (0..LENGTH).try_for_each(|_| {
            x += dx;
            Assert::default().eq_within_tols(erfc(x), &(1.0 - erf(x)))
        })
    }
    #[test]
    fn saturates_positive() -> Result<(), AssertionError> {
        Assert::eq(erfc(1e3), &0.0)
    }
    #[test]
    fn saturates_negative() -> Result<(), AssertionError> {
        Assert::eq(erfc(-1e3), &2.0)
    }
    #[test]
    fn no_overflow_region() -> Result<(), AssertionError> {
        let mut x = -1e3;
        let dx = (1e3 - 27.0) / ((LENGTH + 1) as f64);
        (0..LENGTH).try_for_each(|_| {
            x += dx;
            Assert::eq(erfc(x), &2.0)
        })
    }
}

mod inverse_langevin {
    use super::*;
    #[test]
    #[should_panic]
    fn above_one() {
        inverse_langevin(1.3);
    }
    #[test]
    #[should_panic]
    fn one() {
        inverse_langevin(1.0);
    }
    #[test]
    fn range() -> Result<(), AssertionError> {
        let mut x = -1.0;
        let dx = 2.0 / ((LENGTH + 1) as f64);
        (0..LENGTH).try_for_each(|_| {
            x += dx;
            Assert::default().eq_within_tols(langevin(inverse_langevin(x)), &x)
        })
    }
    #[test]
    fn zero() -> Result<(), AssertionError> {
        Assert::zero(&inverse_langevin(0.0))
    }
}

mod lambert_w {
    use super::*;
    #[test]
    fn end() -> Result<(), AssertionError> {
        Assert::eq(lambert_w(-1.0 / E), &-1.0)
    }
    #[test]
    fn euler() -> Result<(), AssertionError> {
        Assert::eq(lambert_w(E), &1.0)
    }
    #[test]
    #[should_panic]
    fn panic() {
        let _ = lambert_w(-10.0);
    }
    #[test]
    fn range() -> Result<(), AssertionError> {
        let mut x = -1.0 / E;
        let dx = (6.0 - x) / ((LENGTH + 1) as f64);
        let mut w = 0.0;
        (0..LENGTH).try_for_each(|_| {
            x += dx;
            w = lambert_w(x);
            Assert::default().eq_within_tols(w * w.exp(), &x)
        })
    }
    #[test]
    fn zero() -> Result<(), AssertionError> {
        Assert::zero(&lambert_w(0.0))
    }
}

mod langevin {
    use super::*;
    #[test]
    fn zero() -> Result<(), AssertionError> {
        Assert::zero(&langevin(0.0))
    }
}

mod rosenbrock {
    use super::*;
    #[test]
    fn zero() -> Result<(), AssertionError> {
        Assert::zero(&rosenbrock(&Vector::from([1.0; 3]), 1.0, 1.0))
    }
    mod derivative {
        use super::*;
        #[test]
        fn zero() -> Result<(), AssertionError> {
            Assert::eq(
                rosenbrock_derivative(&Vector::from([1.0; 3]), 1.0, 1.0),
                &Vector::from([0.0; 3]),
            )
        }
    }
}