diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4f9fd9cd..42099b38 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,34 +6,55 @@ on: pull_request: branches: [ master ] +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + jobs: + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust stable with clippy + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Run cargo clippy + run: cargo clippy --all-targets + + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust nightly with rustfmt + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt + + - name: Run rustfmt --check + run: cargo fmt -- --check + test: - name: Test + needs: [clippy, fmt] runs-on: ${{ matrix.os }} strategy: - fail-fast: false matrix: - include: - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - toolchain: stable - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - toolchain: nightly + os: [ubuntu-latest, macos-latest, windows-latest] + toolchain: [stable, nightly] + steps: - - uses: actions/checkout@v2 - - name: Install toolchain - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - name: Install Rust ${{ matrix.toolchain }} + uses: dtolnay/rust-toolchain@master with: - profile: minimal - target: ${{ matrix.target }} toolchain: ${{ matrix.toolchain }} - override: true - - name: Test nightly feature (if possible) - if: ${{ matrix.toolchain == 'nightly' }} - run: | - cargo test --target ${{ matrix.target }} --features=nightly - cargo test --target ${{ matrix.target }} --benches --features=nightly + + - name: Test nightly feature + if: matrix.toolchain == 'nightly' + run: cargo test --all-targets --features=nightly + - name: Test default features - run: | - cargo test --target ${{ matrix.target }} \ No newline at end of file + if: matrix.toolchain != 'nightly' + run: cargo test --all-targets + diff --git a/src/distribution/bernoulli.rs b/src/distribution/bernoulli.rs index 0af2f101..d0b6e219 100644 --- a/src/distribution/bernoulli.rs +++ b/src/distribution/bernoulli.rs @@ -257,7 +257,7 @@ impl Discrete for Bernoulli { } #[rustfmt::skip] -#[cfg(all(test, feature = "nightly"))] +#[cfg(test)] mod testing { use std::fmt::Debug; use crate::distribution::DiscreteCDF; diff --git a/src/distribution/cauchy.rs b/src/distribution/cauchy.rs index d66a9747..3af0ca63 100644 --- a/src/distribution/cauchy.rs +++ b/src/distribution/cauchy.rs @@ -432,7 +432,7 @@ mod tests { test_almost(0.0, 0.1, 0.9936346508990272, 1e-16, sf(-5.0)); test_almost(0.0, 0.1, 0.9682744825694465, 1e-16, sf(-1.0)); test_case(0.0, 0.1, 0.5, sf(0.0)); - test_case(0.0, 0.1, 0.03172551743055352, sf(1.0)); + test_almost(0.0, 0.1, 0.03172551743055352, 1e-16, sf(1.0)); test_case(0.0, 0.1, 0.006365349100972806, sf(5.0)); test_almost(0.0, 1.0, 0.9371670418109989, 1e-16, sf(-5.0)); test_case(0.0, 1.0, 0.75, sf(-1.0)); diff --git a/src/distribution/dirac.rs b/src/distribution/dirac.rs index 9a66e5e0..c781fa72 100644 --- a/src/distribution/dirac.rs +++ b/src/distribution/dirac.rs @@ -185,7 +185,7 @@ impl Mode> for Dirac { } #[rustfmt::skip] -#[cfg(all(test, feature = "nightly"))] +#[cfg(test)] mod tests { use crate::statistics::*; use crate::distribution::{ContinuousCDF, Continuous, Dirac}; diff --git a/src/distribution/dirichlet.rs b/src/distribution/dirichlet.rs index 0f703056..f47a0cfd 100644 --- a/src/distribution/dirichlet.rs +++ b/src/distribution/dirichlet.rs @@ -301,7 +301,7 @@ fn is_valid_alpha(a: &[f64]) -> bool { } #[rustfmt::skip] -#[cfg(all(test, feature = "nightly"))] +#[cfg(test)] mod tests { use super::*; use nalgebra::{DVector}; diff --git a/src/distribution/discrete_uniform.rs b/src/distribution/discrete_uniform.rs index 59b0da4e..a128d9d3 100644 --- a/src/distribution/discrete_uniform.rs +++ b/src/distribution/discrete_uniform.rs @@ -248,7 +248,7 @@ impl Discrete for DiscreteUniform { } #[rustfmt::skip] -#[cfg(all(test, feature = "nightly"))] +#[cfg(test)] mod tests { use std::fmt::Debug; use crate::statistics::*; diff --git a/src/distribution/empirical.rs b/src/distribution/empirical.rs index 0e8c964a..b22b78be 100644 --- a/src/distribution/empirical.rs +++ b/src/distribution/empirical.rs @@ -206,7 +206,7 @@ impl ContinuousCDF for Empirical { } } -#[cfg(all(test, feature = "nightly"))] +#[cfg(test)] mod tests { use super::*; #[test] diff --git a/src/distribution/laplace.rs b/src/distribution/laplace.rs index f04306f1..bcaaae08 100644 --- a/src/distribution/laplace.rs +++ b/src/distribution/laplace.rs @@ -291,7 +291,7 @@ impl Continuous for Laplace { } } -#[cfg(all(test, feature = "nightly"))] +#[cfg(test)] mod tests { use super::*; use rand::thread_rng; diff --git a/src/distribution/multivariate_normal.rs b/src/distribution/multivariate_normal.rs index 368da0ec..e50ac3ac 100644 --- a/src/distribution/multivariate_normal.rs +++ b/src/distribution/multivariate_normal.rs @@ -242,7 +242,7 @@ impl Continuous, f64> for MultivariateNormal { } #[rustfmt::skip] -#[cfg(all(test, feature = "nightly"))] +#[cfg(test)] mod tests { use crate::distribution::{Continuous, MultivariateNormal}; use crate::statistics::*; diff --git a/src/distribution/normal.rs b/src/distribution/normal.rs index 5624a5c1..4d540eee 100644 --- a/src/distribution/normal.rs +++ b/src/distribution/normal.rs @@ -51,6 +51,24 @@ impl Normal { Ok(Normal { mean, std_dev }) } } + + /// Constructs a new standard normal distribution with a mean of 0 + /// and a standard deviation of 1. + /// + /// + /// # Examples + /// + /// ``` + /// use statrs::distribution::Normal; + /// + /// let mut result = Normal::standard(); + /// ``` + pub fn standard() -> Normal { + Normal { + mean: 0.0, + std_dev: 1.0, + } + } } impl ::rand::distributions::Distribution for Normal { @@ -292,6 +310,15 @@ pub fn sample_unchecked(rng: &mut R, mean: f64, std_dev: f64) - mean + std_dev * ziggurat::sample_std_normal(rng) } + +impl std::default::Default for Normal { + /// Returns the standard normal distribution with a mean of 0 + /// and a standard deviation of 1. + fn default() -> Self { + Self::standard() + } +} + #[rustfmt::skip] #[cfg(all(test, feature = "nightly"))] mod tests { @@ -512,4 +539,17 @@ mod tests { test_almost(5.0, 2.0, 10.0, 1e-14, inverse_cdf(0.9937903346742238648330218954258077788721022530769078)); test_case(5.0, 2.0, f64::INFINITY, inverse_cdf(1.0)); } + + #[test] + fn test_default() { + let n = Normal::default(); + + let n_mean = n.mean().unwrap(); + let n_std = n.std_dev().unwrap(); + + // Check that the mean of the distribution is close to 0 + assert_almost_eq!(n_mean, 0.0, 1e-15); + // Check that the standard deviation of the distribution is close to 1 + assert_almost_eq!(n_std, 1.0, 1e-15); + } } diff --git a/src/error.rs b/src/error.rs index ce0bb1a4..faa74fad 100644 --- a/src/error.rs +++ b/src/error.rs @@ -118,7 +118,7 @@ mod tests { #[test] fn test_sync_send() { // Error types should implement Sync and Send - let _ = assert_sync::(); - let _ = assert_send::(); + assert_sync::(); + assert_send::(); } }