24#ifndef MORPHEUS_MATRIX_MARKET_IMPL_HPP
25#define MORPHEUS_MATRIX_MARKET_IMPL_HPP
34#include <Morpheus_Exceptions.hpp>
35#include <Morpheus_CooMatrix.hpp>
36#include <Morpheus_DenseMatrix.hpp>
37#include <Morpheus_Sort.hpp>
38#include <Morpheus_Copy.hpp>
44inline void tokenize(std::vector<std::string>& tokens,
const std::string& str,
45 const std::string& delimiters =
"\n\r\t ") {
47 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
49 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
51 while (std::string::npos != pos || std::string::npos != lastPos) {
53 tokens.push_back(str.substr(lastPos, pos - lastPos));
55 lastPos = str.find_first_not_of(delimiters, pos);
57 pos = str.find_first_of(delimiters, lastPos);
68template <
typename Stream>
71 std::vector<std::string> tokens;
74 std::getline(input, line);
75 Impl::tokenize(tokens, line);
77 if (tokens.size() != 5 || tokens[0] !=
"%%MatrixMarket" ||
78 tokens[1] !=
"matrix")
81 banner.storage = tokens[2];
82 banner.type = tokens[3];
83 banner.symmetry = tokens[4];
85 if (banner.storage !=
"array" && banner.storage !=
"coordinate")
87 banner.storage +
"]");
89 if (banner.type !=
"complex" && banner.type !=
"real" &&
90 banner.type !=
"integer" && banner.type !=
"pattern")
94 if (banner.symmetry !=
"general" && banner.symmetry !=
"symmetric" &&
95 banner.symmetry !=
"unsymmetric" && banner.symmetry !=
"hermitian" &&
96 banner.symmetry !=
"skew-symmetric")
98 banner.symmetry +
"]");
101template <
typename T,
typename... P,
typename Stream>
103 const matrix_market_banner& banner) {
110 std::getline(input, line);
111 }
while (line[0] ==
'%');
114 std::vector<std::string> tokens;
115 Impl::tokenize(tokens, line);
117 if (tokens.size() != 3)
120 size_type num_rows, num_cols, num_entries;
122 std::istringstream(tokens[0]) >> num_rows;
123 std::istringstream(tokens[1]) >> num_cols;
124 std::istringstream(tokens[2]) >> num_entries;
126 coo.
resize(num_rows, num_cols, num_entries);
128 size_type num_entries_read = 0;
131 if (banner.type ==
"pattern") {
132 while (num_entries_read < coo.
nnnz() && !input.eof()) {
138 auto values_begin = coo.
values().data();
139 auto values_end = coo.
values().data() + coo.
values().size();
140 std::fill(values_begin, values_end, T(1));
141 }
else if (banner.type ==
"real" || banner.type ==
"integer") {
142 while (num_entries_read < coo.
nnnz() && !input.eof()) {
149 coo.
values(num_entries_read) = real;
152 }
else if (banner.type ==
"complex") {
154 "Morpheus does not currently support complex matrices");
160 if (num_entries_read != coo.
nnnz())
162 "unexpected EOF while reading MatrixMarket entries");
165 if (coo.
nnnz() > 0) {
168 size_type min_row_index =
169 *std::min_element(row_indices_begin, row_indices_end);
170 size_type max_row_index =
171 *std::max_element(row_indices_begin, row_indices_end);
174 auto column_indices_end =
176 size_type min_col_index =
177 *std::min_element(column_indices_begin, column_indices_end);
178 size_type max_col_index =
179 *std::max_element(column_indices_begin, column_indices_end);
181 if (min_row_index < 1)
183 if (min_col_index < 1)
185 if (max_row_index > coo.
nrows())
187 if (max_col_index > coo.
ncols())
189 "found invalid column index (index > num_columns)");
193 for (size_type n = 0; n < coo.
nnnz(); n++) {
199 if (banner.symmetry !=
"general") {
200 size_type off_diagonals = 0;
202 for (size_type n = 0; n < coo.
nnnz(); n++)
205 size_type general_num_entries = coo.
nnnz() + off_diagonals;
208 general_num_entries);
210 if (banner.symmetry ==
"symmetric") {
213 for (size_type n = 0; n < coo.
nnnz(); n++) {
217 general.values(nnz) = coo.
values(n);
224 general.values(nnz) = coo.
values(n);
228 }
else if (banner.symmetry ==
"hermitian") {
230 "MatrixMarket I/O does not currently support hermitian matrices");
232 }
else if (banner.symmetry ==
"skew-symmetric") {
234 "MatrixMarket I/O does not currently support skew-symmetric "
243#if defined(MORPHEUS_ENABLE_SERIAL)
245 Morpheus::sort_by_row_and_column<Morpheus::Serial>(coo);
247 Morpheus::sort_by_row_and_column<Morpheus::DefaultHostSpace>(coo);
251template <
typename T,
typename... P,
typename Stream>
253 const matrix_market_banner& banner) {
261 std::getline(input, line);
262 }
while (line[0] ==
'%');
264 std::vector<std::string> tokens;
265 Impl::tokenize(tokens, line);
267 if (tokens.size() != 2)
270 size_type num_rows, num_cols;
272 std::istringstream(tokens[0]) >> num_rows;
273 std::istringstream(tokens[1]) >> num_cols;
277 size_type num_entries = num_rows * num_cols;
278 size_type num_entries_read = 0;
279 size_type nrows = 0, ncols = 0;
282 if (banner.type ==
"pattern") {
284 "pattern array MatrixMarket format is not supported");
285 }
else if (banner.type ==
"real" || banner.type ==
"integer") {
286 while (num_entries_read < num_entries && !input.eof()) {
291 dense(nrows, ncols) = T(real);
295 if (ncols % num_cols == 0) {
300 }
else if (banner.type ==
"complex") {
306 if (num_entries_read != num_entries)
308 "unexpected EOF while reading MatrixMarket entries");
310 if (banner.symmetry !=
"general")
312 "only general array symmetric MatrixMarket format is supported");
317template <
template <
class,
class...>
class Container,
class T,
class... P,
319void read_matrix_market_stream(
320 Container<T, P...>& mtx, Stream& input,
321 typename std::enable_if<
324 matrix_market_banner banner;
325 read_matrix_market_banner(banner, input);
327 if (banner.storage ==
"coordinate") {
329 read_coordinate_stream(temp, input, banner);
333 "only coordinate storage format is supported for reading a "
334 "MatrixMarket file into CooMatrix container");
338template <
template <
class,
class...>
class Container,
class T,
class... P,
340void read_matrix_market_stream(
341 Container<T, P...>& mtx, Stream& input,
342 typename std::enable_if<
345 matrix_market_banner banner;
346 read_matrix_market_banner(banner, input);
348 if (banner.storage ==
"coordinate") {
349 if (mtx.active_index() != Morpheus::COO_FORMAT) {
351 "read_matrix_market_stream: The active state of a DynamicMatrix must "
352 "be set to Morpheus::COO_FORMAT before reading a MatrixMarket "
357 read_coordinate_stream(temp, input, banner);
361 "only coordinate storage format is supported for reading a "
362 "MatrixMarket file into CooMatrix container");
366template <
template <
class,
class...>
class Container,
class T,
class... P,
368void read_matrix_market_stream(
369 Container<T, P...>& container, Stream& input,
370 typename std::enable_if<
373 matrix_market_banner banner;
374 read_matrix_market_banner(banner, input);
376 if (banner.storage ==
"array") {
378 Impl::read_array_stream(temp, input, banner);
383 "only coordinate storage format is supported for reading a "
384 "MatrixMarket file into DenseMatrix container");
388template <
template <
class,
class...>
class Container,
class T,
class... P,
390void read_matrix_market_stream(
391 Container<T, P...>& container, Stream& input,
392 typename std::enable_if<
396 matrix_market_banner banner;
397 read_matrix_market_banner(banner, input);
399 if (banner.storage ==
"array") {
401 Impl::read_array_stream(temp, input, banner);
403 Morpheus::convert<Morpheus::Serial>(temp, container);
406 "only coordinate storage format is supported for reading a "
407 "MatrixMarket file into DenseVector container");
411template <
typename Stream,
typename ScalarType>
412void write_value(Stream& output,
const ScalarType& value) {
416template <
typename T,
typename... P,
typename Stream>
421 if (std::is_floating_point_v<T> || std::is_integral_v<T>) {
422 output <<
"%%MatrixMarket matrix coordinate real general\n";
427 output << coo.
nrows() <<
"\t" << coo.
ncols() <<
"\t" << coo.
nnnz() <<
"\n";
429 for (size_type i = 0; i < coo.
nnnz(); i++) {
432 Impl::write_value(output, coo.
cvalues(i));
437template <
template <
class,
class...>
class Container,
class T,
class... P,
439void write_matrix_market_stream(
440 const Container<T, P...>& mtx, Stream& output,
441 typename std::enable_if<
444 Impl::write_coordinate_stream(mtx, output);
447template <
template <
class,
class...>
class Container,
class T,
class... P,
449void write_matrix_market_stream(
450 const Container<T, P...>& mtx, Stream& output,
451 typename std::enable_if<
454 if (mtx.active_index() != Morpheus::COO_FORMAT) {
456 "write_matrix_market_stream: The active state of a DynamicMatrix must "
457 "be set to Morpheus::COO_FORMAT before writing a MatrixMarket stream!");
460 Impl::write_coordinate_stream(coo, output);
463template <
template <
class,
class...>
class Container,
class T,
class... P,
465void write_matrix_market_stream(
466 const Container<T, P...>& vec, Stream& output,
467 typename std::enable_if<
470 using size_type =
typename Container<T, P...>::size_type;
472 if (std::is_floating_point_v<T> || std::is_integral_v<T>) {
473 output <<
"%%MatrixMarket matrix array real general\n";
478 output << vec.size() <<
"\t1\n";
480 for (size_type i = 0; i < vec.size(); i++) {
481 Impl::write_value(output, vec[i]);
486template <
template <
class,
class...>
class Container,
class T,
class... P,
488void write_matrix_market_stream(
489 const Container<T, P...>& mtx, Stream& output,
490 typename std::enable_if<
493 using size_type =
typename Container<T, P...>::size_type;
495 if (std::is_floating_point_v<T> || std::is_integral_v<T>) {
496 output <<
"%%MatrixMarket matrix array real general\n";
501 output << mtx.nrows() <<
"\t" << mtx.ncols() <<
"\n";
503 for (size_type i = 0; i < (size_t)mtx.nrows(); i++) {
504 for (size_type j = 0; j < (size_t)mtx.ncols(); j++) {
505 Impl::write_value(output, mtx(i, j));
Implementation of the Coordinate (COO) Sparse Matrix Format Representation.
Definition: Morpheus_CooMatrix.hpp:91
MORPHEUS_FORCEINLINE_FUNCTION const index_array_reference ccolumn_indices(size_type n) const
Returns a const-reference to the column index of the matrix with index n.
Definition: Morpheus_CooMatrix.hpp:495
MORPHEUS_FORCEINLINE_FUNCTION index_array_reference column_indices(size_type n)
Returns a reference to the column index of the matrix with index n.
Definition: Morpheus_CooMatrix.hpp:461
MORPHEUS_FORCEINLINE_FUNCTION const value_array_reference cvalues(size_type n) const
Returns a const-reference to the value of the matrix with index n.
Definition: Morpheus_CooMatrix.hpp:506
MORPHEUS_FORCEINLINE_FUNCTION const index_array_reference crow_indices(size_type n) const
Returns a const-reference to the row index of the matrix with index n.
Definition: Morpheus_CooMatrix.hpp:483
void resize(const size_type num_rows, const size_type num_cols, const size_type num_entries)
Resizes CooMatrix with shape of (num_rows, num_cols) and sets number of non-zero entries to num_entri...
Definition: Morpheus_CooMatrix.hpp:363
MORPHEUS_FORCEINLINE_FUNCTION value_array_reference values(size_type n)
Returns a reference to the value of the matrix with index n.
Definition: Morpheus_CooMatrix.hpp:471
MORPHEUS_FORCEINLINE_FUNCTION index_array_reference row_indices(size_type n)
Returns a reference to the row index of the matrix with index n.
Definition: Morpheus_CooMatrix.hpp:449
The DenseMatrix container is a two-dimensional dense container that contains contiguous elements....
Definition: Morpheus_DenseMatrix.hpp:74
Definition: Morpheus_Exceptions.hpp:51
size_type nnnz() const
Number of non-zeros of the matrix.
Definition: Morpheus_MatrixBase.hpp:133
size_type nrows() const
Number of rows of the matrix.
Definition: Morpheus_MatrixBase.hpp:119
size_type ncols() const
Number of columns of the matrix.
Definition: Morpheus_MatrixBase.hpp:126
Definition: Morpheus_Exceptions.hpp:43
Definition: Morpheus_Exceptions.hpp:57
Generic Morpheus interfaces.
Definition: dummy.cpp:24
constexpr bool has_host_memory_space_v
Short-hand to has_host_memory_space.
Definition: Morpheus_SpaceTraits.hpp:314
Definition: Morpheus_MatrixMarket_Impl.hpp:61