export to file directly; add a new trait for export

This commit is contained in:
Hantao Hui 2022-02-03 11:49:15 +01:00
parent d511e372de
commit 8904c01c7b
2 changed files with 104 additions and 14 deletions

View File

@ -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<T: SupportedMatrixMarketScalar> {
/// iterate over triplets
fn triplet_iter(&self) -> Box<dyn Iterator<Item = (usize, usize, &T)> + '_>;
/// 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<T: MatrixMarketScalar>:
internal::SupportedMatrixMarketExport<T>
{
}
macro_rules! mm_matrix_impl {
($T_MATRIX:ty) => {
impl<T: MatrixMarketScalar> MatrixMarketExport<T> for $T_MATRIX {}
impl<T: internal::SupportedMatrixMarketScalar> internal::SupportedMatrixMarketExport<T>
for $T_MATRIX
{
#[inline]
fn triplet_iter(&self) -> Box<dyn Iterator<Item = (usize, usize, &T)> + '_> {
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<T>);
mm_matrix_impl!(CsrMatrix<T>);
mm_matrix_impl!(CscMatrix<T>);
#[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::<i32>(&generated_matrixmarket_string).unwrap();
/// assert_matrix_eq!(matrix,generated_matrixmarket);
/// ```
pub fn write_to_matrix_market_str<T: MatrixMarketScalar, S: SparseAccess<T>>(
pub fn write_to_matrix_market_str<T: MatrixMarketScalar, S: MatrixMarketExport<T>>(
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<T: MatrixMarketScalar, S: SparseAccess<T>>(
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<T: MatrixMarketScalar, S: SparseAccess<T>>(
/// let matrix = load_coo_from_matrix_market_str::<i32>(&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<T: MatrixMarketScalar, S: SparseAccess<T>, P: AsRef<Path>>(
matrix: &S,
pub fn write_to_matrix_market_file<
T: MatrixMarketScalar,
S: MatrixMarketExport<T>,
P: AsRef<Path>,
>(
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(())
}

View File

@ -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;