|
|
|
@ -4,7 +4,6 @@
|
|
|
|
|
use crate::coo::CooMatrix;
|
|
|
|
|
use crate::SparseFormatError;
|
|
|
|
|
use crate::SparseFormatErrorKind;
|
|
|
|
|
use nalgebra::base::Scalar;
|
|
|
|
|
use nalgebra::Complex;
|
|
|
|
|
use pest::iterators::Pairs;
|
|
|
|
|
use pest::Parser;
|
|
|
|
@ -27,11 +26,12 @@ pub struct MatrixMarketError {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Errors produced by functions that expect well-formed matrix market format data.
|
|
|
|
|
/// > _NOTE:_ Since the matrix market design didn't mention if multiple sparse entries with the same coordiantes are allowed or not, so, it's allowed here.
|
|
|
|
|
#[non_exhaustive]
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
|
|
|
pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// Indicates that some word is not known to MM format
|
|
|
|
|
/// Parsing failure.
|
|
|
|
|
///
|
|
|
|
|
/// Indicates that the parser failed, for example due to an unexpected string.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -39,17 +39,17 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// # use nalgebra_sparse::io::load_coo_from_matrix_market_str;
|
|
|
|
|
/// # use nalgebra_sparse::io::MatrixMarketErrorKind;
|
|
|
|
|
/// let str = r#"
|
|
|
|
|
/// %%MatrixMarket whatever whatever whatever whatever
|
|
|
|
|
/// %%MatrixMarket invalid invalid invalid invalid
|
|
|
|
|
/// 1 1 1
|
|
|
|
|
/// 1 1 5
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::ParsingError);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(), MatrixMarketErrorKind::ParsingError);
|
|
|
|
|
/// ```
|
|
|
|
|
ParsingError,
|
|
|
|
|
|
|
|
|
|
/// Indicates that header is not valid
|
|
|
|
|
/// Indicates that the matrix market header is invalid.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -62,13 +62,13 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 1 1 1
|
|
|
|
|
/// 1 1 5
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::InvalidHeader);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::InvalidHeader);
|
|
|
|
|
/// ```
|
|
|
|
|
InvalidHeader,
|
|
|
|
|
|
|
|
|
|
/// Indicates that the data entries in .mtx file are more or less than entries specified in .mtx file
|
|
|
|
|
/// Indicates that the number of data entries in the matrix market file does not match the header.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -82,13 +82,14 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 2 2 2
|
|
|
|
|
/// 2 3 2
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::EntryNumUnmatched);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::EntryMismatch);
|
|
|
|
|
/// ```
|
|
|
|
|
EntryNumUnmatched,
|
|
|
|
|
EntryMismatch,
|
|
|
|
|
|
|
|
|
|
/// Indicates that the type T is not matched with the function it called.
|
|
|
|
|
/// Indicates that the scalar type requested is not compatible with the scalar type stored
|
|
|
|
|
/// in the matrix market file.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -97,18 +98,20 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// # use nalgebra_sparse::io::MatrixMarketErrorKind;
|
|
|
|
|
/// let str = r#"
|
|
|
|
|
/// %%matrixmarket matrix coordinate real general
|
|
|
|
|
/// % it should be called by load_coo_from_matrix_market_str::<f64>(str), or f32;
|
|
|
|
|
/// % it should be loaded with load_coo_from_matrix_market_str::<f64>(str) (or f32)
|
|
|
|
|
/// 3 3 2
|
|
|
|
|
/// 2 2 2.22
|
|
|
|
|
/// 2 3 2.22
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<i32>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::TypeUnmatched);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<i32>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::TypeMismatch);
|
|
|
|
|
/// ```
|
|
|
|
|
TypeUnmatched,
|
|
|
|
|
TypeMismatch,
|
|
|
|
|
|
|
|
|
|
/// Indicates that zero has been used as an index in the data, or the shape of the matrix, which is not allowed.
|
|
|
|
|
/// Indicates that zero has been used as an index in the data.
|
|
|
|
|
///
|
|
|
|
|
/// **Note**: The matrix market format uses 1-based indexing.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -120,13 +123,14 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 1 1 1
|
|
|
|
|
/// 0 0 10
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::ZeroError);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::ZeroError);
|
|
|
|
|
/// ```
|
|
|
|
|
ZeroError,
|
|
|
|
|
|
|
|
|
|
/// Indicates [SparseFormatError], while creating the sparse matrix.
|
|
|
|
|
/// Indicates [SparseFormatError] while creating the sparse matrix.
|
|
|
|
|
///
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -139,13 +143,14 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 1 1 1
|
|
|
|
|
/// 4 2 10
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::SparseFormatError(SparseFormatErrorKind::IndexOutOfBounds));
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),
|
|
|
|
|
/// MatrixMarketErrorKind::SparseFormatError(SparseFormatErrorKind::IndexOutOfBounds));
|
|
|
|
|
/// ```
|
|
|
|
|
SparseFormatError(SparseFormatErrorKind),
|
|
|
|
|
|
|
|
|
|
/// Indicates that a wrong diagonal element has been provieded to the matrix
|
|
|
|
|
/// Indicates that a wrong diagonal element has been provided to the matrix.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -160,9 +165,9 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 1 1 10
|
|
|
|
|
/// 2 1 5
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::DiagonalError);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<f64>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::DiagonalError);
|
|
|
|
|
///
|
|
|
|
|
/// let str = r#"
|
|
|
|
|
/// %%matrixmarket matrix coordinate complex hermitian
|
|
|
|
@ -171,28 +176,27 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 1 1 10 2
|
|
|
|
|
/// 2 1 5 2
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<Complex<f64>>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::DiagonalError);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<Complex<f64>>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::DiagonalError);
|
|
|
|
|
/// ```
|
|
|
|
|
/// Here the skew matrix shouldn't have an element on the diagonal
|
|
|
|
|
/// Here the skew matrix shouldn't have an element on the diagonal.
|
|
|
|
|
DiagonalError,
|
|
|
|
|
|
|
|
|
|
/// Indicates [io error](`std::io::Error`), while reading the data from file.
|
|
|
|
|
/// Indicates an [IO error](`std::io::Error`) while reading the data from file.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// # use nalgebra_sparse::io::load_coo_from_matrix_market_file;
|
|
|
|
|
/// # use nalgebra_sparse::io::MatrixMarketErrorKind;
|
|
|
|
|
/// let file_name = "whatever.mtx";
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_file::<f64,_>(file_name);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::IOError(std::io::ErrorKind::NotFound));
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_file::<f64,_>("matrix.mtx");
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::IOError(std::io::ErrorKind::NotFound));
|
|
|
|
|
/// ```
|
|
|
|
|
IOError(std::io::ErrorKind),
|
|
|
|
|
|
|
|
|
|
/// Indicates (skew-)symmetric (or hermitian) matrix is not lower triangle matrix.
|
|
|
|
|
/// Indicates that a (skew-)symmetric (or hermitian) matrix is not a lower triangular matrix.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -205,13 +209,13 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 1 1 10
|
|
|
|
|
/// 2 3 5
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<i32>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::NotLowerTriangle);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<i32>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::NotLowerTriangle);
|
|
|
|
|
/// ```
|
|
|
|
|
NotLowerTriangle,
|
|
|
|
|
|
|
|
|
|
/// Indicates (skew-)symmetric (or hermitian) matrix is not square matrix.
|
|
|
|
|
/// Indicates that a (skew-)symmetric (or hermitian) matrix is not a square matrix.
|
|
|
|
|
///
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
@ -224,11 +228,11 @@ pub enum MatrixMarketErrorKind {
|
|
|
|
|
/// 1 1 10
|
|
|
|
|
/// 2 3 5
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix_error = load_coo_from_matrix_market_str::<i32>(str);
|
|
|
|
|
/// assert_eq!(matrix_error.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_error.unwrap_err().kind(),MatrixMarketErrorKind::NotSquareMatrix);
|
|
|
|
|
/// let matrix_result = load_coo_from_matrix_market_str::<i32>(str);
|
|
|
|
|
/// assert_eq!(matrix_result.is_err(), true);
|
|
|
|
|
/// assert_eq!(matrix_result.unwrap_err().kind(),MatrixMarketErrorKind::NonSquare);
|
|
|
|
|
/// ```
|
|
|
|
|
NotSquareMatrix,
|
|
|
|
|
NonSquare,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MatrixMarketError {
|
|
|
|
@ -239,7 +243,7 @@ impl MatrixMarketError {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The operation error kind.
|
|
|
|
|
/// The matrix market error kind.
|
|
|
|
|
#[must_use]
|
|
|
|
|
pub fn kind(&self) -> MatrixMarketErrorKind {
|
|
|
|
|
self.error_kind
|
|
|
|
@ -254,7 +258,7 @@ impl MatrixMarketError {
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for MatrixMarketError {
|
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
|
write!(f, "Matrix Market load error: ")?;
|
|
|
|
|
write!(f, "Matrix Market error: ")?;
|
|
|
|
|
match self.kind() {
|
|
|
|
|
MatrixMarketErrorKind::ParsingError => {
|
|
|
|
|
write!(f, "ParsingError,")?;
|
|
|
|
@ -262,11 +266,11 @@ impl fmt::Display for MatrixMarketError {
|
|
|
|
|
MatrixMarketErrorKind::InvalidHeader => {
|
|
|
|
|
write!(f, "InvalidHeader,")?;
|
|
|
|
|
}
|
|
|
|
|
MatrixMarketErrorKind::EntryNumUnmatched => {
|
|
|
|
|
MatrixMarketErrorKind::EntryMismatch => {
|
|
|
|
|
write!(f, "EntryNumUnmatched,")?;
|
|
|
|
|
}
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched => {
|
|
|
|
|
write!(f, "TypeUnmatched,")?;
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch => {
|
|
|
|
|
write!(f, "TypeMismatch,")?;
|
|
|
|
|
}
|
|
|
|
|
MatrixMarketErrorKind::SparseFormatError(_) => {
|
|
|
|
|
write!(f, "SparseFormatError,")?;
|
|
|
|
@ -283,23 +287,24 @@ impl fmt::Display for MatrixMarketError {
|
|
|
|
|
MatrixMarketErrorKind::NotLowerTriangle => {
|
|
|
|
|
write!(f, "NotLowerTriangle,")?;
|
|
|
|
|
}
|
|
|
|
|
MatrixMarketErrorKind::NotSquareMatrix => {
|
|
|
|
|
MatrixMarketErrorKind::NonSquare => {
|
|
|
|
|
write!(f, "NotSquareMatrix,")?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
write!(f, " Message: {}", self.message)
|
|
|
|
|
write!(f, " message: {}", self.message)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::error::Error for MatrixMarketError {}
|
|
|
|
|
|
|
|
|
|
impl<T: fmt::Debug + std::hash::Hash + std::marker::Copy + Ord> From<pest::error::Error<T>>
|
|
|
|
|
for MatrixMarketError
|
|
|
|
|
impl MatrixMarketError {
|
|
|
|
|
fn from_pest_error<T>(error: pest::error::Error<T>) -> Self
|
|
|
|
|
where
|
|
|
|
|
T: fmt::Debug + std::hash::Hash + std::marker::Copy + Ord
|
|
|
|
|
{
|
|
|
|
|
fn from(err: pest::error::Error<T>) -> Self {
|
|
|
|
|
Self::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::ParsingError,
|
|
|
|
|
format!("Can't parse the data.\n Error: {}", err),
|
|
|
|
|
format!("Can't parse the data.\n Error: {}", error),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -334,9 +339,9 @@ impl From<std::io::Error> for MatrixMarketError {
|
|
|
|
|
impl From<TryFromIntError> for MatrixMarketError {
|
|
|
|
|
fn from(err: TryFromIntError) -> Self {
|
|
|
|
|
Self::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!(
|
|
|
|
|
"Please consider using a larger integery type. Error message: {}",
|
|
|
|
|
"Please consider using a larger integer type. Error message: {}",
|
|
|
|
|
&err
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
@ -348,7 +353,7 @@ impl From<TryFromIntError> for MatrixMarketError {
|
|
|
|
|
impl From<Infallible> for MatrixMarketError {
|
|
|
|
|
fn from(_err: Infallible) -> Self {
|
|
|
|
|
Self::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("This won't happen"),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
@ -431,7 +436,11 @@ impl FromStr for StorageScheme {
|
|
|
|
|
|
|
|
|
|
/// Precheck if it's a valid header.
|
|
|
|
|
///
|
|
|
|
|
/// For more details, please check Boisvert, Ronald F., Roldan Pozo, and Karin A. Remington. The matrix market formats: Initial design. Technical report, Applied and Computational Mathematics Division, NIST, 1996. Section 3.
|
|
|
|
|
/// For more details, please check
|
|
|
|
|
///
|
|
|
|
|
/// Boisvert, Ronald F., Roldan Pozo, and Karin A. Remington.
|
|
|
|
|
/// The matrix market formats: Initial design.
|
|
|
|
|
/// Technical report, Applied and Computational Mathematics Division, NIST, 1996. Section 3.
|
|
|
|
|
fn typecode_precheck(tc: &Typecode) -> Result<(), MatrixMarketError> {
|
|
|
|
|
match tc {
|
|
|
|
|
Typecode {
|
|
|
|
@ -479,13 +488,17 @@ fn typecode_precheck(tc: &Typecode) -> Result<(), MatrixMarketError> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Base trait for matrix market types.
|
|
|
|
|
pub trait MatrixMarketScalar: Scalar {
|
|
|
|
|
/// When matrix is an Integer matrix, it will convert a [i128] number to this type.
|
|
|
|
|
/// Scalar types supported by the matrix market parser.
|
|
|
|
|
mod internal {
|
|
|
|
|
use crate::io::MatrixMarketError;
|
|
|
|
|
use na::{Complex, Scalar};
|
|
|
|
|
|
|
|
|
|
pub trait SupportedMatrixMarketScalar: Scalar {
|
|
|
|
|
/// When the matrix is an integer matrix, it will convert a [i128] number to this type.
|
|
|
|
|
fn from_i128(i: i128) -> Result<Self, MatrixMarketError>;
|
|
|
|
|
/// When matrix is a Real matrix, it will convert a [f64] number to this type.
|
|
|
|
|
fn from_f64(f: f64) -> Result<Self, MatrixMarketError>;
|
|
|
|
|
/// When matrix is a Complx matrix, it will convert a [Complex<f64>] number to this type.
|
|
|
|
|
/// When matrix is a Complex matrix, it will convert a [Complex<f64>] number to this type.
|
|
|
|
|
fn from_c64(c: Complex<f64>) -> Result<Self, MatrixMarketError>;
|
|
|
|
|
/// When matrix is a Pattern matrix, it will convert a unit type [unit] to this type.
|
|
|
|
|
fn from_pattern(p: ()) -> Result<Self, MatrixMarketError>;
|
|
|
|
@ -494,10 +507,20 @@ pub trait MatrixMarketScalar: Scalar {
|
|
|
|
|
/// When matrix is a Hermitian matrix, it will convert itself to its conjugate.
|
|
|
|
|
fn conjugate(self) -> Result<Self, MatrixMarketError>;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A marker trait for supported matrix market scalars.
|
|
|
|
|
///
|
|
|
|
|
/// 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 MatrixMarketScalar: internal::SupportedMatrixMarketScalar {}
|
|
|
|
|
|
|
|
|
|
/// Implement MatrixMarketScalar for primitive integer types.
|
|
|
|
|
macro_rules! mm_int_impl {
|
|
|
|
|
($T:ty) => {
|
|
|
|
|
impl MatrixMarketScalar for $T {
|
|
|
|
|
impl MatrixMarketScalar for $T {}
|
|
|
|
|
|
|
|
|
|
impl internal::SupportedMatrixMarketScalar for $T {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_i128(i: i128) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Ok(Self::try_from(i)?)
|
|
|
|
@ -505,28 +528,28 @@ macro_rules! mm_int_impl {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_f64(_f: f64) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Int type can't be parsed from f64"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_c64(_c: Complex<f64>) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Int type can't be parsed from Complex<f64>"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_pattern(_p: ()) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Int type can't be parsed from ()"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn conjugate(self) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Int type has no conjugate"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
@ -540,11 +563,13 @@ macro_rules! mm_int_impl {
|
|
|
|
|
/// Implement MatrixMarketScalar for primitive real types.
|
|
|
|
|
macro_rules! mm_real_impl {
|
|
|
|
|
($T:ty) => {
|
|
|
|
|
impl MatrixMarketScalar for $T {
|
|
|
|
|
impl MatrixMarketScalar for $T {}
|
|
|
|
|
|
|
|
|
|
impl internal::SupportedMatrixMarketScalar for $T {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_i128(_i: i128) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("real type can't be parsed from i128"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
@ -555,21 +580,21 @@ macro_rules! mm_real_impl {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_c64(_c: Complex<f64>) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("real type can't be parsed from Complex<f64>"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_pattern(_p: ()) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("real type can't be parsed from ()"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn conjugate(self) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("real type has no conjugate"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
@ -580,21 +605,24 @@ macro_rules! mm_real_impl {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Implement MatrixMarketScalar for primitive complex types.
|
|
|
|
|
macro_rules! mm_complex_impl {
|
|
|
|
|
($T:ty) => {
|
|
|
|
|
impl MatrixMarketScalar for Complex<$T> {
|
|
|
|
|
impl MatrixMarketScalar for Complex<$T> {}
|
|
|
|
|
|
|
|
|
|
impl internal::SupportedMatrixMarketScalar for Complex<$T> {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_i128(_i: i128) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Complex type can't be parsed from i128"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_f64(_f: f64) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Complex type can't be parsed from f64"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
@ -608,7 +636,7 @@ macro_rules! mm_complex_impl {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_pattern(_p: ()) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Complex type can't be parsed from ()"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
@ -626,25 +654,27 @@ macro_rules! mm_complex_impl {
|
|
|
|
|
/// Implement MatrixMarketScalar for primitive unit types.
|
|
|
|
|
macro_rules! mm_pattern_impl {
|
|
|
|
|
($T:ty) => {
|
|
|
|
|
impl MatrixMarketScalar for $T {
|
|
|
|
|
impl MatrixMarketScalar for $T {}
|
|
|
|
|
|
|
|
|
|
impl internal::SupportedMatrixMarketScalar for $T {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_i128(_i: i128) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Pattern type can't be parsed from i128"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_f64(_f: f64) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Pattern type can't be parsed from f64"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn from_c64(_c: Complex<f64>) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Pattern type can't be parsed from Complex<f64>"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
@ -656,14 +686,14 @@ macro_rules! mm_pattern_impl {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn conjugate(self) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Pattern type has no conjugate"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
#[inline]
|
|
|
|
|
fn negative(self) -> Result<Self, MatrixMarketError> {
|
|
|
|
|
Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::TypeUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::TypeMismatch,
|
|
|
|
|
format!("Pattern type has no negative"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
@ -687,16 +717,31 @@ mm_pattern_impl!(());
|
|
|
|
|
|
|
|
|
|
#[derive(Parser)]
|
|
|
|
|
#[grammar = "io/matrix_market.pest"]
|
|
|
|
|
struct MMParser;
|
|
|
|
|
struct MatrixMarketParser;
|
|
|
|
|
|
|
|
|
|
/// Parses a Matrix Market file at the given path, and returns the corresponding sparse matrix as CooMatrix format.
|
|
|
|
|
/// Parses a Matrix Market file at the given path as a `CooMatrix`.
|
|
|
|
|
///
|
|
|
|
|
/// The matrix market format specification does not clarify whether duplicate entries are allowed. Our importer
|
|
|
|
|
/// assumes that this is permitted and produces a `CooMatrix` with possibly duplicate entries.
|
|
|
|
|
///
|
|
|
|
|
/// **Note**: A current restriction of the importer is that you must use a compatible scalar type when importing.
|
|
|
|
|
/// For example, in order to import a matrix stored as `integer` in the matrix market format, you must
|
|
|
|
|
/// import it as an integer matrix, otherwise a [TypeMismatch](MatrixMarketErrorKind::TypeMismatch) error
|
|
|
|
|
/// will be returned. This restriction may be lifted in the future, and is
|
|
|
|
|
/// tracked by issue [#1038](https://github.com/dimforge/nalgebra/issues/1038).
|
|
|
|
|
///
|
|
|
|
|
/// Errors
|
|
|
|
|
/// --------
|
|
|
|
|
///
|
|
|
|
|
/// See [MatrixMarketErrorKind] for a list of possible error conditions.
|
|
|
|
|
///
|
|
|
|
|
/// > _NOTE:_ Here uses strong type requirements, which means if the matrix is an integer matrix, e.g. `%%matrixmarket matrix cooridnate integer general`, then you have to load it by `load_coo_from_matrix_market_file<T>`, where T is an integer type. Trying `load_coo_from_matrix_market_file<f64>` will give [TypeUnmatched](MatrixMarketErrorKind::TypeUnmatched) Error. After loading it, you can cast it into a `f64` matrix, by calling [cast](`nalgebra::base::Matrix::cast()`), but be aware of accuracy lose.
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
|
/// ```
|
|
|
|
|
/// use nalgebra_sparse::io::load_coo_from_matrix_market_file;
|
|
|
|
|
/// // Use e.g. `f64` for floating-point matrices
|
|
|
|
|
/// let matrix = load_coo_from_matrix_market_file::<i32>("path/to/matrix.mtx")?;
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn load_coo_from_matrix_market_file<T, P: AsRef<Path>>(
|
|
|
|
|
path: P,
|
|
|
|
|
) -> Result<CooMatrix<T>, MatrixMarketError>
|
|
|
|
@ -707,21 +752,36 @@ where
|
|
|
|
|
load_coo_from_matrix_market_str(&file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parses a Matrix Market file described by the given string, and returns the corresponding as CooMatrix format.
|
|
|
|
|
/// Parses a Matrix Market file described by the given string as a `CooMatrix`.
|
|
|
|
|
///
|
|
|
|
|
/// See [load_coo_from_matrix_market_file] for more information.
|
|
|
|
|
///
|
|
|
|
|
/// Errors
|
|
|
|
|
/// --------
|
|
|
|
|
///
|
|
|
|
|
/// See [MatrixMarketErrorKind] for a list of possible error conditions.
|
|
|
|
|
///
|
|
|
|
|
/// > _NOTE:_ Here uses strong type requirements, which means if the matrix is an integer matrix, e.g. `%%matrixmarket matrix cooridnate integer general`, then you have to load it by `load_coo_from_matrix_market_str<T>`, where T is an integer type. Trying `load_coo_from_matrix_market_str<f64>` will give [TypeUnmatched](MatrixMarketErrorKind::TypeUnmatched) Error. After loading it, you can cast it into a `f64` matrix, by calling [cast](`nalgebra::base::Matrix::cast()`),but be aware of accuracy lose.
|
|
|
|
|
|
|
|
|
|
/// Examples
|
|
|
|
|
/// --------
|
|
|
|
|
/// ```
|
|
|
|
|
/// # use nalgebra_sparse::io::load_coo_from_matrix_market_str;
|
|
|
|
|
/// # use nalgebra_sparse::io::MatrixMarketErrorKind;
|
|
|
|
|
/// let str = r#"
|
|
|
|
|
/// %%matrixmarket matrix coordinate integer symmetric
|
|
|
|
|
/// 5 4 2
|
|
|
|
|
/// 1 1 10
|
|
|
|
|
/// 2 3 5
|
|
|
|
|
/// "#;
|
|
|
|
|
/// let matrix = load_coo_from_matrix_market_str::<i32>(str)?;
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn load_coo_from_matrix_market_str<T>(data: &str) -> Result<CooMatrix<T>, MatrixMarketError>
|
|
|
|
|
where
|
|
|
|
|
T: MatrixMarketScalar,
|
|
|
|
|
{
|
|
|
|
|
// unwrap() in this function are guaranteed by parsing the data
|
|
|
|
|
let file = MMParser::parse(Rule::Document, data)?.next().unwrap();
|
|
|
|
|
let file = MatrixMarketParser::parse(Rule::Document, data)
|
|
|
|
|
.map_err(MatrixMarketError::from_pest_error)?
|
|
|
|
|
.next().unwrap();
|
|
|
|
|
|
|
|
|
|
let mut rows: Vec<usize> = Vec::new();
|
|
|
|
|
let mut cols: Vec<usize> = Vec::new();
|
|
|
|
@ -746,16 +806,16 @@ where
|
|
|
|
|
|
|
|
|
|
// used when constructing dense matrix.
|
|
|
|
|
// If it's sparse matrix, it has no effect.
|
|
|
|
|
let mut current_dense_coordiante: (usize, usize) = (0, 0);
|
|
|
|
|
let mut current_dense_coordinate: (usize, usize) = (0, 0);
|
|
|
|
|
if header_type.storagescheme == StorageScheme::Skew {
|
|
|
|
|
// for skew dense matrix, the first element starts from (1,0)
|
|
|
|
|
current_dense_coordiante = (1, 0);
|
|
|
|
|
current_dense_coordinate = (1, 0);
|
|
|
|
|
}
|
|
|
|
|
// count how many entries in the matrix data
|
|
|
|
|
let count = lines.clone().count();
|
|
|
|
|
if count != shape.2 {
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::EntryNumUnmatched,
|
|
|
|
|
MatrixMarketErrorKind::EntryMismatch,
|
|
|
|
|
format!(
|
|
|
|
|
"{} entries required for the matrix, but {} was provided",
|
|
|
|
|
shape.2, count,
|
|
|
|
@ -800,12 +860,12 @@ where
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
entry = (
|
|
|
|
|
current_dense_coordiante.0,
|
|
|
|
|
current_dense_coordiante.1,
|
|
|
|
|
current_dense_coordinate.0,
|
|
|
|
|
current_dense_coordinate.1,
|
|
|
|
|
parse_dense_complex::<T>(&mut data_line.into_inner())?,
|
|
|
|
|
);
|
|
|
|
|
next_dense_coordiante(
|
|
|
|
|
&mut current_dense_coordiante,
|
|
|
|
|
next_dense_coordinate(
|
|
|
|
|
&mut current_dense_coordinate,
|
|
|
|
|
shape,
|
|
|
|
|
&header_type.storagescheme,
|
|
|
|
|
);
|
|
|
|
@ -816,13 +876,13 @@ where
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
entry = (
|
|
|
|
|
current_dense_coordiante.0,
|
|
|
|
|
current_dense_coordiante.1,
|
|
|
|
|
current_dense_coordinate.0,
|
|
|
|
|
current_dense_coordinate.1,
|
|
|
|
|
parse_dense_real::<T>(&mut data_line.into_inner())?,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
next_dense_coordiante(
|
|
|
|
|
&mut current_dense_coordiante,
|
|
|
|
|
next_dense_coordinate(
|
|
|
|
|
&mut current_dense_coordinate,
|
|
|
|
|
shape,
|
|
|
|
|
&header_type.storagescheme,
|
|
|
|
|
);
|
|
|
|
@ -833,12 +893,12 @@ where
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
entry = (
|
|
|
|
|
current_dense_coordiante.0,
|
|
|
|
|
current_dense_coordiante.1,
|
|
|
|
|
current_dense_coordinate.0,
|
|
|
|
|
current_dense_coordinate.1,
|
|
|
|
|
parse_dense_int::<T>(&mut data_line.into_inner())?,
|
|
|
|
|
);
|
|
|
|
|
next_dense_coordiante(
|
|
|
|
|
&mut current_dense_coordiante,
|
|
|
|
|
next_dense_coordinate(
|
|
|
|
|
&mut current_dense_coordinate,
|
|
|
|
|
shape,
|
|
|
|
|
&header_type.storagescheme,
|
|
|
|
|
);
|
|
|
|
@ -963,7 +1023,7 @@ fn parse_header(inner: &mut Pairs<'_, Rule>) -> Typecode {
|
|
|
|
|
|
|
|
|
|
// Parse shape starts here-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/// Parse a pest structure to sparse shape information, including 3 int, which are number of rols, cols and non-zeros.
|
|
|
|
|
/// Parse a pest structure to sparse shape information, including 3 int, which are number of rows, cols and non-zeros.
|
|
|
|
|
fn parse_sparse_shape(
|
|
|
|
|
inner: &mut Pairs<'_, Rule>,
|
|
|
|
|
storagescheme: &StorageScheme,
|
|
|
|
@ -994,15 +1054,15 @@ fn parse_sparse_shape(
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check for square matirx, when it's not a general matrix
|
|
|
|
|
// check for square matrix, when it's not a general matrix
|
|
|
|
|
if *storagescheme != StorageScheme::General && r != c {
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(MatrixMarketErrorKind::NotSquareMatrix,format!("(Skew-)Symmetric or hermitian matrix should be square matrix, but it has dimension {} and {}",r,c)));
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(MatrixMarketErrorKind::NonSquare, format!("(Skew-)Symmetric or hermitian matrix should be square matrix, but it has dimension {} and {}", r, c)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok((r, c, nnz))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse a pest structure to dense shape information, including 2 int, which are number of rols, cols.
|
|
|
|
|
/// Parse a pest structure to dense shape information, including 2 int, which are number of rows, cols.
|
|
|
|
|
fn parse_dense_shape(
|
|
|
|
|
inner: &mut Pairs<'_, Rule>,
|
|
|
|
|
storagescheme: &StorageScheme,
|
|
|
|
@ -1030,9 +1090,9 @@ fn parse_dense_shape(
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check for square matirx, when it's not a general matrix
|
|
|
|
|
// check for square matrix, when it's not a general matrix
|
|
|
|
|
if *storagescheme != StorageScheme::General && r != c {
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(MatrixMarketErrorKind::NotSquareMatrix,format!("(Skew-)Symmetric or hermitian matrix should be square matrix, but it has dimension {} and {}",r,c)));
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(MatrixMarketErrorKind::NonSquare, format!("(Skew-)Symmetric or hermitian matrix should be square matrix, but it has dimension {} and {}", r, c)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let n: usize;
|
|
|
|
@ -1061,7 +1121,7 @@ fn parse_dense_shape(
|
|
|
|
|
|
|
|
|
|
// Parse entry starts here-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/// Parse a pest structure to sparse real entry, including 2 int, which are number of rols, cols, and a real number as data
|
|
|
|
|
/// Parse a pest structure to sparse real entry, including 2 int, which are number of rows, cols, and a real number as data
|
|
|
|
|
fn parse_sparse_real<T>(inner: &mut Pairs<'_, Rule>) -> Result<(usize, usize, T), MatrixMarketError>
|
|
|
|
|
where
|
|
|
|
|
T: MatrixMarketScalar,
|
|
|
|
@ -1070,17 +1130,17 @@ where
|
|
|
|
|
let entry_inner = inner.next().unwrap();
|
|
|
|
|
if entry_inner.as_rule() != Rule::SparseReal {
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(MatrixMarketErrorKind::ParsingError,format!("
|
|
|
|
|
Spare real matrix requires 2 int number as coordiantes and 1 real number as data, but line {} was provided.
|
|
|
|
|
Spare real matrix requires 2 int number as coordinates and 1 real number as data, but line {} was provided.
|
|
|
|
|
",entry_inner.as_str() )));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut inner = entry_inner.into_inner();
|
|
|
|
|
let (r, c) = parse_sparse_coordiante(&mut inner)?;
|
|
|
|
|
let (r, c) = parse_sparse_coordinate(&mut inner)?;
|
|
|
|
|
let d = inner.next().unwrap().as_str().parse::<f64>().unwrap();
|
|
|
|
|
Ok((r, c, T::from_f64(d)?))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse a pest structure to sparse integer entry, including 2 int, which are number of rols, cols, and a int number as data
|
|
|
|
|
/// Parse a pest structure to sparse integer entry, including 2 int, which are number of rows, cols, and a int number as data
|
|
|
|
|
fn parse_sparse_int<T>(inner: &mut Pairs<'_, Rule>) -> Result<(usize, usize, T), MatrixMarketError>
|
|
|
|
|
where
|
|
|
|
|
T: MatrixMarketScalar,
|
|
|
|
@ -1093,20 +1153,20 @@ where
|
|
|
|
|
MatrixMarketErrorKind::ParsingError,
|
|
|
|
|
format!(
|
|
|
|
|
"
|
|
|
|
|
Spare real matrix requires 3 int number as coordiantes and data, but line {} was provided.
|
|
|
|
|
Spare real matrix requires 3 int number as coordinates and data, but line {} was provided.
|
|
|
|
|
",
|
|
|
|
|
entry_inner.as_str()
|
|
|
|
|
),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
let mut inner = entry_inner.into_inner();
|
|
|
|
|
let (r, c) = parse_sparse_coordiante(&mut inner)?;
|
|
|
|
|
let (r, c) = parse_sparse_coordinate(&mut inner)?;
|
|
|
|
|
// Here to guarantee it is an integer number
|
|
|
|
|
let d = inner.next().unwrap().as_str().parse::<i128>()?;
|
|
|
|
|
Ok((r, c, T::from_i128(d)?))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse a pest structure to sparse pattern entry, including 2 int, which are number of rols, cols
|
|
|
|
|
/// Parse a pest structure to sparse pattern entry, including 2 int, which are number of rows, cols
|
|
|
|
|
fn parse_sparse_pattern<T>(
|
|
|
|
|
inner: &mut Pairs<'_, Rule>,
|
|
|
|
|
) -> Result<(usize, usize, T), MatrixMarketError>
|
|
|
|
@ -1120,18 +1180,18 @@ where
|
|
|
|
|
MatrixMarketErrorKind::ParsingError,
|
|
|
|
|
format!(
|
|
|
|
|
"
|
|
|
|
|
Spare real matrix requires 2 int number as coordiantes, but line {} was provided.
|
|
|
|
|
Spare real matrix requires 2 int number as coordinates, but line {} was provided.
|
|
|
|
|
",
|
|
|
|
|
entry_inner.as_str()
|
|
|
|
|
),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
let mut inner = entry_inner.into_inner();
|
|
|
|
|
let (r, c) = parse_sparse_coordiante(&mut inner)?;
|
|
|
|
|
let (r, c) = parse_sparse_coordinate(&mut inner)?;
|
|
|
|
|
Ok((r, c, T::from_pattern(())?))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse a pest structure to sparse complex entry, including 2 int, which are number of rols, cols, and 2 real number as complex data
|
|
|
|
|
/// Parse a pest structure to sparse complex entry, including 2 int, which are number of rows, cols, and 2 real number as complex data
|
|
|
|
|
fn parse_sparse_complex<T>(
|
|
|
|
|
inner: &mut Pairs<'_, Rule>,
|
|
|
|
|
) -> Result<(usize, usize, T), MatrixMarketError>
|
|
|
|
@ -1142,11 +1202,11 @@ where
|
|
|
|
|
let entry_inner = inner.next().unwrap();
|
|
|
|
|
if entry_inner.as_rule() != Rule::SparseComplex {
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(MatrixMarketErrorKind::ParsingError,format!("
|
|
|
|
|
Spare real matrix requires 2 int number as coordiantes and 2 real number as complex data, but line {} was provided.
|
|
|
|
|
Spare real matrix requires 2 int number as coordinates and 2 real number as complex data, but line {} was provided.
|
|
|
|
|
",entry_inner.as_str() )));
|
|
|
|
|
}
|
|
|
|
|
let mut inner = entry_inner.into_inner();
|
|
|
|
|
let (r, c) = parse_sparse_coordiante(&mut inner)?;
|
|
|
|
|
let (r, c) = parse_sparse_coordinate(&mut inner)?;
|
|
|
|
|
let real = inner.next().unwrap().as_str().parse::<f64>().unwrap();
|
|
|
|
|
let imag = inner.next().unwrap().as_str().parse::<f64>().unwrap();
|
|
|
|
|
let complex = Complex::<f64>::new(real, imag);
|
|
|
|
@ -1232,8 +1292,8 @@ where
|
|
|
|
|
|
|
|
|
|
// Parse entry ends here-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/// Parse the coordiantes information used for sparse matrix
|
|
|
|
|
fn parse_sparse_coordiante(
|
|
|
|
|
/// Parse the coordinates information used for sparse matrix
|
|
|
|
|
fn parse_sparse_coordinate(
|
|
|
|
|
inner: &mut Pairs<'_, Rule>,
|
|
|
|
|
) -> Result<(usize, usize), MatrixMarketError> {
|
|
|
|
|
// unwrap() in this function are guaranteed by parsing the data
|
|
|
|
@ -1242,51 +1302,51 @@ fn parse_sparse_coordiante(
|
|
|
|
|
if r * c == 0 {
|
|
|
|
|
return Err(MatrixMarketError::from_kind_and_message(
|
|
|
|
|
MatrixMarketErrorKind::ZeroError,
|
|
|
|
|
String::from("The data has to be one-indixed"),
|
|
|
|
|
String::from("The data has to be one-indexed"),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
// The coordiantes in matrix market is one-based, but in CooMatrix is zero-based.
|
|
|
|
|
// The coordinates in matrix market is one-based, but in CooMatrix is zero-based.
|
|
|
|
|
Ok((r - 1, c - 1))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Calculate the next coordiantes used for dense matrix
|
|
|
|
|
fn next_dense_coordiante(
|
|
|
|
|
current_dense_coordiante: &mut (usize, usize),
|
|
|
|
|
/// Calculate the next coordinates used for dense matrix
|
|
|
|
|
fn next_dense_coordinate(
|
|
|
|
|
current_dense_coordinate: &mut (usize, usize),
|
|
|
|
|
shape: (usize, usize, usize),
|
|
|
|
|
storagescheme: &StorageScheme,
|
|
|
|
|
) {
|
|
|
|
|
// matrix market is column based format.
|
|
|
|
|
// so it follows the order (0,0) -> (1,0) -> ... -> (row, 0) -> (0,1) -> ... ->(row,col)
|
|
|
|
|
// current_dense_coordiante is (row, column)
|
|
|
|
|
// current_dense_coordinate is (row, column)
|
|
|
|
|
match storagescheme {
|
|
|
|
|
StorageScheme::General => {
|
|
|
|
|
if current_dense_coordiante.0 < shape.0 - 1 {
|
|
|
|
|
current_dense_coordiante.0 += 1
|
|
|
|
|
if current_dense_coordinate.0 < shape.0 - 1 {
|
|
|
|
|
current_dense_coordinate.0 += 1
|
|
|
|
|
} else {
|
|
|
|
|
// jump to next column, reset row to 1, column add 1
|
|
|
|
|
current_dense_coordiante.0 = 0;
|
|
|
|
|
current_dense_coordiante.1 += 1;
|
|
|
|
|
current_dense_coordinate.0 = 0;
|
|
|
|
|
current_dense_coordinate.1 += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
StorageScheme::Symmetric | StorageScheme::Hermitian => {
|
|
|
|
|
if current_dense_coordiante.0 < shape.0 - 1 {
|
|
|
|
|
current_dense_coordiante.0 += 1
|
|
|
|
|
if current_dense_coordinate.0 < shape.0 - 1 {
|
|
|
|
|
current_dense_coordinate.0 += 1
|
|
|
|
|
} else {
|
|
|
|
|
// jump to next column, column add 1, then set row equals to current column
|
|
|
|
|
// for example (0,0) -> (1,0) -> ... -> (row, 0) -> (1,1) -> ...
|
|
|
|
|
current_dense_coordiante.1 += 1;
|
|
|
|
|
current_dense_coordiante.0 = current_dense_coordiante.1;
|
|
|
|
|
current_dense_coordinate.1 += 1;
|
|
|
|
|
current_dense_coordinate.0 = current_dense_coordinate.1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
StorageScheme::Skew => {
|
|
|
|
|
if current_dense_coordiante.0 < shape.0 - 1 {
|
|
|
|
|
current_dense_coordiante.0 += 1;
|
|
|
|
|
if current_dense_coordinate.0 < shape.0 - 1 {
|
|
|
|
|
current_dense_coordinate.0 += 1;
|
|
|
|
|
} else {
|
|
|
|
|
// jump to next column, set row equals to current column, then column add 1
|
|
|
|
|
// skew matrix doesn't have element on diagonal
|
|
|
|
|
// for example (1,0) -> (2,0) -> ... -> (row, 0) -> (2,1) -> ...
|
|
|
|
|
current_dense_coordiante.1 += 1;
|
|
|
|
|
current_dense_coordiante.0 = current_dense_coordiante.1 + 1;
|
|
|
|
|
current_dense_coordinate.1 += 1;
|
|
|
|
|
current_dense_coordinate.0 = current_dense_coordinate.1 + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|