diff --git a/nalgebra-sparse/Cargo.toml b/nalgebra-sparse/Cargo.toml index 36230993..bf0d3849 100644 --- a/nalgebra-sparse/Cargo.toml +++ b/nalgebra-sparse/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" authors = [ "Andreas Longva", "Sébastien Crozet " ] edition = "2018" +[features] +proptest-support = ["proptest", "nalgebra/proptest"] + [dependencies] nalgebra = { version="0.23", path = "../" } num-traits = { version = "0.2", default-features = false } +proptest = { version = "0.10", optional = true } diff --git a/nalgebra-sparse/src/lib.rs b/nalgebra-sparse/src/lib.rs index e1820b4a..53bc846a 100644 --- a/nalgebra-sparse/src/lib.rs +++ b/nalgebra-sparse/src/lib.rs @@ -81,6 +81,9 @@ pub mod csr; pub mod pattern; pub mod ops; +#[cfg(feature = "proptest-support")] +pub mod proptest; + use std::error::Error; use std::fmt; diff --git a/nalgebra-sparse/src/proptest.rs b/nalgebra-sparse/src/proptest.rs new file mode 100644 index 00000000..59d832e7 --- /dev/null +++ b/nalgebra-sparse/src/proptest.rs @@ -0,0 +1,41 @@ +//! TODO +//! +//! TODO: Clarify that this module needs proptest-support feature + +use crate::coo::CooMatrix; +use proptest::prelude::*; +use proptest::collection::{SizeRange, vec}; +use nalgebra::Scalar; + +/// TODO +pub fn coo( + value_strategy: T, + rows: impl Strategy + 'static, + cols: impl Strategy + 'static, + max_nonzeros: usize) -> BoxedStrategy> +where + T: Strategy + Clone + 'static, + T::Value: Scalar, +{ + (rows, cols, (0 ..= max_nonzeros)) + .prop_flat_map(move |(nrows, ncols, nnz)| { + // If the numbers of rows and columns are small in comparison with the + // max nnz, it will lead to small matrices essentially always turning out to be dense. + // To address this, we correct the nnz by computing the modulo with the + // maximum number of non-zeros (ignoring duplicates) we can have for + // the given dimensions. + // This way we can still generate very sparse matrices for small matrices. + let max_nnz = nrows * ncols; + let nnz = if max_nnz == 0 { 0 } else { nnz % max_nnz }; + let row_index_strategy = if nrows > 0 { 0 .. nrows } else { 0 .. 1 }; + let col_index_strategy = if ncols > 0 { 0 .. ncols } else { 0 .. 1 }; + let row_indices = vec![row_index_strategy.clone(); nnz]; + let col_indices = vec![col_index_strategy.clone(); nnz]; + let values_strategy = vec![value_strategy.clone(); nnz]; + + (Just(nrows), Just(ncols), row_indices, col_indices, values_strategy) + }).prop_map(|(nrows, ncols, row_indices, col_indices, values)| { + CooMatrix::try_from_triplets(nrows, ncols, row_indices, col_indices, values) + .expect("We should always generate valid COO data.") + }).boxed() +} \ No newline at end of file diff --git a/nalgebra-sparse/tests/unit_tests/proptest.rs b/nalgebra-sparse/tests/unit_tests/proptest.rs new file mode 100644 index 00000000..e69de29b