12#ifndef EIGEN_SPARSE_MARKET_IO_H
13#define EIGEN_SPARSE_MARKET_IO_H
19#include "./InternalHeaderCheck.h"
24template <
typename Scalar,
typename StorageIndex>
25inline void GetMarketLine(
const char* line, StorageIndex& i, StorageIndex& j, Scalar& value) {
26 std::stringstream sline(line);
27 sline >> i >> j >> value;
31inline void GetMarketLine(
const char* line,
int& i,
int& j,
float& value) {
32 std::sscanf(line,
"%d %d %g", &i, &j, &value);
36inline void GetMarketLine(
const char* line,
int& i,
int& j,
double& value) {
37 std::sscanf(line,
"%d %d %lg", &i, &j, &value);
41inline void GetMarketLine(
const char* line,
int& i,
int& j, std::complex<float>& value) {
42 std::sscanf(line,
"%d %d %g %g", &i, &j, &numext::real_ref(value), &numext::imag_ref(value));
46inline void GetMarketLine(
const char* line,
int& i,
int& j, std::complex<double>& value) {
47 std::sscanf(line,
"%d %d %lg %lg", &i, &j, &numext::real_ref(value), &numext::imag_ref(value));
50template <
typename Scalar,
typename StorageIndex>
51inline void GetMarketLine(
const char* line, StorageIndex& i, StorageIndex& j, std::complex<Scalar>& value) {
52 std::stringstream sline(line);
54 sline >> i >> j >> valR >> valI;
55 value = std::complex<Scalar>(valR, valI);
58template <
typename RealScalar>
59inline void GetDenseElt(
const std::string& line, RealScalar& val) {
60 std::istringstream newline(line);
64template <
typename RealScalar>
65inline void GetDenseElt(
const std::string& line, std::complex<RealScalar>& val) {
66 RealScalar valR, valI;
67 std::istringstream newline(line);
68 newline >> valR >> valI;
69 val = std::complex<RealScalar>(valR, valI);
72template <
typename Scalar>
73inline void putMarketHeader(std::string& header,
int sym) {
74 header =
"%%MatrixMarket matrix coordinate ";
75 EIGEN_IF_CONSTEXPR ((std::is_same<Scalar, std::complex<float> >::value ||
76 std::is_same<Scalar, std::complex<double> >::value)) {
79 header +=
" symmetric";
81 header +=
" Hermitian";
87 header +=
" symmetric";
93template <
typename Scalar,
typename StorageIndex>
94inline void PutMatrixElt(Scalar value, StorageIndex row, StorageIndex col, std::ofstream& out) {
95 out << row <<
" " << col <<
" " << value <<
"\n";
97template <
typename Scalar,
typename StorageIndex>
98inline void PutMatrixElt(std::complex<Scalar> value, StorageIndex row, StorageIndex col, std::ofstream& out) {
99 out << row <<
" " << col <<
" " << value.real() <<
" " << value.imag() <<
"\n";
102template <
typename Scalar>
103inline void putDenseElt(Scalar value, std::ofstream& out) {
104 out << value <<
"\n";
106template <
typename Scalar>
107inline void putDenseElt(std::complex<Scalar> value, std::ofstream& out) {
108 out << value.real() <<
" " << value.imag() <<
"\n";
123inline bool getMarketHeader(
const std::string& filename,
int& sym,
bool& iscomplex,
bool& isdense) {
127 std::ifstream in(filename.c_str(), std::ios::in);
128 if (!in)
return false;
132 std::getline(in, line);
133 eigen_assert(in.good());
135 std::stringstream fmtline(line);
136 std::string substr[5];
137 fmtline >> substr[0] >> substr[1] >> substr[2] >> substr[3] >> substr[4];
138 if (substr[2].compare(
"array") == 0) isdense =
true;
139 if (substr[3].compare(
"complex") == 0) iscomplex =
true;
140 if (substr[4].compare(
"symmetric") == 0)
142 else if (substr[4].compare(
"Hermitian") == 0)
156template <
typename SparseMatrixType>
157bool loadMarket(SparseMatrixType& mat,
const std::string& filename) {
158 typedef typename SparseMatrixType::Scalar Scalar;
159 typedef typename SparseMatrixType::StorageIndex StorageIndex;
160 std::ifstream input(filename.c_str(), std::ios::in);
161 if (!input)
return false;
164 input.rdbuf()->pubsetbuf(rdbuffer, 4096);
166 const int maxBuffersize = 2048;
167 char buffer[maxBuffersize];
169 bool readsizes =
false;
172 std::vector<T> elements;
174 Index M(-1), N(-1), NNZ(-1);
176 while (input.getline(buffer, maxBuffersize)) {
179 if (buffer[0] ==
'%')
continue;
182 std::stringstream line(buffer);
183 line >> M >> N >> NNZ;
184 if (M > 0 && N > 0) {
188 elements.reserve(NNZ);
191 StorageIndex i(-1), j(-1);
193 internal::GetMarketLine(buffer, i, j, value);
197 if (i >= 0 && j >= 0 && i < M && j < N) {
199 elements.push_back(T(i, j, value));
201 std::cerr <<
"Invalid read: " << i <<
"," << j <<
"\n";
207 mat.setFromTriplets(elements.begin(), elements.end());
209 std::cerr << count <<
"!=" << NNZ <<
"\n";
226template <
typename DenseType>
228 typedef typename DenseType::Scalar Scalar;
229 std::ifstream in(filename.c_str(), std::ios::in);
230 if (!in)
return false;
233 Index rows(0), cols(0);
235 std::getline(in, line);
236 eigen_assert(in.good());
237 }
while (line[0] ==
'%');
238 std::istringstream newline(line);
239 newline >> rows >> cols;
241 bool sizes_not_positive = (rows < 1 || cols < 1);
242 bool wrong_input_rows = (DenseType::MaxRowsAtCompileTime != Dynamic && rows > DenseType::MaxRowsAtCompileTime) ||
243 (DenseType::RowsAtCompileTime != Dynamic && rows != DenseType::RowsAtCompileTime);
244 bool wrong_input_cols = (DenseType::MaxColsAtCompileTime != Dynamic && cols > DenseType::MaxColsAtCompileTime) ||
245 (DenseType::ColsAtCompileTime != Dynamic && cols != DenseType::ColsAtCompileTime);
247 if (sizes_not_positive || wrong_input_rows || wrong_input_cols) {
248 if (sizes_not_positive) {
249 std::cerr <<
"non-positive row or column size in file" << filename <<
"\n";
251 std::cerr <<
"Input matrix can not be resized to" << rows <<
" x " << cols <<
"as given in " << filename <<
"\n";
257 mat.resize(rows, cols);
262 while (std::getline(in, line) && (row < rows) && (col < cols)) {
263 internal::GetDenseElt(line, value);
265 mat(row, col) = value;
274 if (n != mat.size()) {
275 std::cerr <<
"Unable to read all elements from file " << filename <<
"\n";
284template <
typename VectorType>
299template <
typename SparseMatrixType>
300bool saveMarket(
const SparseMatrixType& mat,
const std::string& filename,
int sym = 0) {
301 typedef typename SparseMatrixType::Scalar Scalar;
302 typedef typename SparseMatrixType::RealScalar RealScalar;
303 std::ofstream out(filename.c_str(), std::ios::out);
304 if (!out)
return false;
306 out.flags(std::ios_base::scientific);
307 out.precision(std::numeric_limits<RealScalar>::digits10 + 2);
309 internal::putMarketHeader<Scalar>(header, sym);
310 out << header << std::endl;
311 out << mat.rows() <<
" " << mat.cols() <<
" " << mat.nonZeros() <<
"\n";
313 EIGEN_UNUSED_VARIABLE(count);
314 for (
int j = 0; j < mat.outerSize(); ++j)
315 for (
typename SparseMatrixType::InnerIterator it(mat, j); it; ++it) {
317 internal::PutMatrixElt(it.value(), it.row() + 1, it.col() + 1, out);
333template <
typename DenseType>
335 typedef typename DenseType::Scalar Scalar;
336 typedef typename DenseType::RealScalar RealScalar;
337 std::ofstream out(filename.c_str(), std::ios::out);
338 if (!out)
return false;
340 out.flags(std::ios_base::scientific);
341 out.precision(std::numeric_limits<RealScalar>::digits10 + 2);
342 EIGEN_IF_CONSTEXPR ((std::is_same<Scalar, std::complex<float> >::value ||
343 std::is_same<Scalar, std::complex<double> >::value)) {
344 out <<
"%%MatrixMarket matrix array complex general\n";
346 out <<
"%%MatrixMarket matrix array real general\n";
348 out << mat.rows() <<
" " << mat.cols() <<
"\n";
349 for (Index i = 0; i < mat.cols(); i++) {
350 for (Index j = 0; j < mat.rows(); j++) {
351 internal::putDenseElt(mat(j, i), out);
362template <
typename VectorType>
Namespace containing all symbols from the Eigen library.