diff --git a/nalgebra-sparse/src/io/matrix_market.rs b/nalgebra-sparse/src/io/matrix_market.rs index 924efcf8..d00a873d 100644 --- a/nalgebra-sparse/src/io/matrix_market.rs +++ b/nalgebra-sparse/src/io/matrix_market.rs @@ -1,10 +1,9 @@ //! Implementation of matrix market io code. //! //! See the [website](https://math.nist.gov/MatrixMarket/formats.html) or the [paper](https://www.researchgate.net/publication/2630533_The_Matrix_Market_Exchange_Formats_Initial_Design) for more details about matrix market. -use crate::CooMatrix; use crate::SparseFormatError; use crate::SparseFormatErrorKind; -use matrixcompare_core::SparseAccess; +use crate::{CooMatrix, CscMatrix, CsrMatrix}; use nalgebra::Complex; use pest::iterators::Pairs; use pest::Parser; @@ -513,6 +512,17 @@ mod internal { /// Convert the data to string fn to_matrixmarket_string(&self) -> String; } + + pub trait SupportedMatrixMarketExport { + /// iterate over triplets + fn triplet_iter(&self) -> Box + '_>; + /// number of rows + fn nrows(&self) -> usize; + /// number of columns + fn ncols(&self) -> usize; + /// number of non-zeros + fn nnz(&self) -> usize; + } } /// A marker trait for supported matrix market scalars. @@ -754,6 +764,46 @@ mm_complex_impl!(f64); mm_pattern_impl!(()); +/// A marker trait for supported sparse matrix types. +/// +/// This is a sealed trait; it cannot be implemented by external crates. This is done in order to prevent leaking +/// some of the implementation details we currently rely on. We may relax this restriction in the future. +pub trait MatrixMarketExport: + internal::SupportedMatrixMarketExport +{ +} + +macro_rules! mm_matrix_impl { + ($T_MATRIX:ty) => { + impl MatrixMarketExport for $T_MATRIX {} + + impl internal::SupportedMatrixMarketExport + for $T_MATRIX + { + #[inline] + fn triplet_iter(&self) -> Box + '_> { + Box::new(self.triplet_iter()) + } + #[inline] + fn nrows(&self) -> usize { + self.nrows() + } + #[inline] + fn ncols(&self) -> usize { + self.ncols() + } + #[inline] + fn nnz(&self) -> usize { + self.nnz() + } + } + }; +} + +mm_matrix_impl!(CooMatrix); +mm_matrix_impl!(CsrMatrix); +mm_matrix_impl!(CscMatrix); + #[derive(Parser)] #[grammar = "io/matrix_market.pest"] struct MatrixMarketParser; @@ -1391,23 +1441,29 @@ fn next_dense_coordinate( /// let generated_matrixmarket = load_coo_from_matrix_market_str::(&generated_matrixmarket_string).unwrap(); /// assert_matrix_eq!(matrix,generated_matrixmarket); /// ``` -pub fn write_to_matrix_market_str>( +pub fn write_to_matrix_market_str>( sparse_matrix: &S, ) -> String { let mut matrixmarket_string = String::new(); + // write header matrixmarket_string.push_str("%%matrixmarket matrix coordinate "); matrixmarket_string.push_str(T::typename()); - matrixmarket_string.push_str(" general\n% matrixmarket file generated by nalgebra-sparse.\n"); + matrixmarket_string.push_str(" general\n"); + + //write comment + matrixmarket_string.push_str("% matrixmarket file generated by nalgebra-sparse.\n"); + // write shape information - matrixmarket_string.push_str(&sparse_matrix.rows().to_string()); + matrixmarket_string.push_str(&sparse_matrix.nrows().to_string()); matrixmarket_string.push(' '); - matrixmarket_string.push_str(&sparse_matrix.cols().to_string()); + matrixmarket_string.push_str(&sparse_matrix.ncols().to_string()); matrixmarket_string.push(' '); matrixmarket_string.push_str(&sparse_matrix.nnz().to_string()); matrixmarket_string.push('\n'); - for (r, c, d) in sparse_matrix.fetch_triplets() { + //write triplets + for (r, c, d) in sparse_matrix.triplet_iter() { matrixmarket_string.push_str(&(r + 1).to_string()); matrixmarket_string.push_str(" "); matrixmarket_string.push_str(&(c + 1).to_string()); @@ -1415,7 +1471,6 @@ pub fn write_to_matrix_market_str>( matrixmarket_string.push_str(&d.to_matrixmarket_string()); matrixmarket_string.push_str("\n"); } - matrixmarket_string } @@ -1442,15 +1497,49 @@ pub fn write_to_matrix_market_str>( /// let matrix = load_coo_from_matrix_market_str::(&str).unwrap(); /// let res = write_to_matrix_market_file(&matrix,"path/to/matrix.mtx"); /// if res.is_err(){ -/// // do something +/// // do something /// } /// ``` -pub fn write_to_matrix_market_file, P: AsRef>( - matrix: &S, +pub fn write_to_matrix_market_file< + T: MatrixMarketScalar, + S: MatrixMarketExport, + P: AsRef, +>( + sparse_matrix: &S, path: P, ) -> Result<(), MatrixMarketError> { - let matrixmarket_string = write_to_matrix_market_str(matrix); + // The code is basically the same as write_to_matrix_market_str, but write the matrix into file instead. let mut file = File::create(path)?; - write!(file, "{}", matrixmarket_string)?; + + // write header + write!( + file, + "%%matrixmarket matrix coordinate {} general\n", + T::typename() + )?; + + // write comments + write!(file, "% matrixmarket file generated by nalgebra-sparse.\n",)?; + + // write shape information + write!( + file, + "{} {} {}\n", + sparse_matrix.nrows(), + sparse_matrix.ncols(), + sparse_matrix.nnz() + )?; + + // write triplets + for (r, c, d) in sparse_matrix.triplet_iter() { + write!( + file, + "{} {} {}\n", + r + 1, + c + 1, + d.to_matrixmarket_string() + )?; + } + Ok(()) } diff --git a/nalgebra-sparse/src/io/mod.rs b/nalgebra-sparse/src/io/mod.rs index ff61fb6c..52fe4446 100644 --- a/nalgebra-sparse/src/io/mod.rs +++ b/nalgebra-sparse/src/io/mod.rs @@ -33,6 +33,7 @@ pub use self::matrix_market::{ load_coo_from_matrix_market_file, load_coo_from_matrix_market_str, write_to_matrix_market_file, - write_to_matrix_market_str, MatrixMarketError, MatrixMarketErrorKind, MatrixMarketScalar, + write_to_matrix_market_str, MatrixMarketError, MatrixMarketErrorKind, MatrixMarketExport, + MatrixMarketScalar, }; mod matrix_market;