2018-11-07 01:31:04 +08:00
|
|
|
use std::fs;
|
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
use pest::Parser;
|
2019-03-23 21:29:07 +08:00
|
|
|
use crate::sparse::CsMatrix;
|
|
|
|
use crate::Real;
|
2018-11-07 01:31:04 +08:00
|
|
|
|
|
|
|
#[derive(Parser)]
|
|
|
|
#[grammar = "io/matrix_market.pest"]
|
|
|
|
struct MatrixMarketParser;
|
|
|
|
|
|
|
|
// FIXME: return an Error instead of an Option.
|
2019-02-03 21:18:55 +08:00
|
|
|
/// Parses a Matrix Market file at the given path, and returns the corresponding sparse matrix.
|
2018-11-07 01:31:04 +08:00
|
|
|
pub fn cs_matrix_from_matrix_market<N: Real, P: AsRef<Path>>(path: P) -> Option<CsMatrix<N>> {
|
|
|
|
let file = fs::read_to_string(path).ok()?;
|
|
|
|
cs_matrix_from_matrix_market_str(&file)
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: return an Error instead of an Option.
|
2019-02-03 21:18:55 +08:00
|
|
|
/// Parses a Matrix Market file described by the given string, and returns the corresponding sparse matrix.
|
2018-11-07 01:31:04 +08:00
|
|
|
pub fn cs_matrix_from_matrix_market_str<N: Real>(data: &str) -> Option<CsMatrix<N>> {
|
|
|
|
let file = MatrixMarketParser::parse(Rule::Document, data)
|
|
|
|
.unwrap()
|
|
|
|
.next()?;
|
|
|
|
let mut shape = (0, 0, 0);
|
|
|
|
let mut rows: Vec<usize> = Vec::new();
|
|
|
|
let mut cols: Vec<usize> = Vec::new();
|
|
|
|
let mut data: Vec<N> = Vec::new();
|
|
|
|
|
|
|
|
for line in file.into_inner() {
|
|
|
|
match line.as_rule() {
|
|
|
|
Rule::Header => {}
|
|
|
|
Rule::Shape => {
|
|
|
|
let mut inner = line.into_inner();
|
|
|
|
shape.0 = inner.next()?.as_str().parse::<usize>().ok()?;
|
|
|
|
shape.1 = inner.next()?.as_str().parse::<usize>().ok()?;
|
|
|
|
shape.2 = inner.next()?.as_str().parse::<usize>().ok()?;
|
|
|
|
}
|
|
|
|
Rule::Entry => {
|
|
|
|
let mut inner = line.into_inner();
|
|
|
|
// NOTE: indices are 1-based.
|
|
|
|
rows.push(inner.next()?.as_str().parse::<usize>().ok()? - 1);
|
|
|
|
cols.push(inner.next()?.as_str().parse::<usize>().ok()? - 1);
|
2019-03-23 21:29:07 +08:00
|
|
|
data.push(crate::convert(inner.next()?.as_str().parse::<f64>().ok()?));
|
2018-11-07 01:31:04 +08:00
|
|
|
}
|
|
|
|
_ => return None, // FIXME: return an Err instead.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(CsMatrix::from_triplet(
|
|
|
|
shape.0, shape.1, &rows, &cols, &data,
|
|
|
|
))
|
|
|
|
}
|