12#ifndef ARCCORE_ALINA_IO_H
13#define ARCCORE_ALINA_IO_H
38#include "arccore/alina/AlinaUtils.h"
39#include "arccore/alina/BackendInterface.h"
44namespace Arcane::Alina::IO
59 precondition(f,
"Failed to open file \"" + fname +
"\"");
62 precondition(std::getline(f, line), format_error());
64 std::istringstream is(line);
65 std::string banner, mtx, coord, dtype, storage;
68 is >> banner >> mtx >> coord >> dtype >> storage,
71 precondition(banner ==
"%%MatrixMarket", format_error(
"no banner"));
72 precondition(mtx ==
"matrix", format_error(
"not a matrix"));
74 if (storage ==
"general") {
77 else if (storage ==
"symmetric") {
81 precondition(
false,
"unsupported storage type");
84 if (coord ==
"coordinate") {
87 else if (coord ==
"array") {
91 precondition(
false, format_error(
"unsupported coordinate type"));
94 if (dtype ==
"real") {
98 else if (dtype ==
"complex") {
102 else if (dtype ==
"integer") {
107 precondition(
false, format_error(
"unsupported data type"));
112 precondition(std::getline(f, line), format_error(
"unexpected eof"));
113 }
while (line[0] ==
'%');
118 precondition(is >> nrows >> ncols, format_error());
134 size_t rows()
const {
return nrows; }
137 size_t cols()
const {
return ncols; }
140 template <
typename Idx,
typename Val>
142 std::vector<Idx>& col,
143 std::vector<Val>& val,
144 ptrdiff_t row_beg = -1,
145 ptrdiff_t row_end = -1)
147 precondition(_sparse, format_error(
"not a sparse matrix"));
149 _complex ?
"attempt to read complex values into real vector" :
"attempt to read real values into complex vector");
150 precondition(std::is_integral<Val>::value == _integer,
151 _integer ?
"attempt to read integer values into real vector" :
"attempt to read real values into integer vector");
156 std::istringstream is;
161 precondition(is >> n >> m >> nnz, format_error());
169 precondition(row_beg >= 0 && row_end <= n,
170 "Wrong subset of rows is requested");
172 ptrdiff_t _nnz = _symmetric ? 2 * nnz : nnz;
174 if (row_beg != 0 || row_end != n)
175 _nnz *= 1.2 * (row_end - row_beg) / n;
177 std::vector<Idx> _row;
179 std::vector<Idx> _col;
181 std::vector<Val> _val;
184 ptrdiff_t chunk = row_end - row_beg;
186 ptr.resize(chunk + 1);
187 std::fill(ptr.begin(), ptr.end(), 0);
189 for (
size_t k = 0; k < nnz; ++k) {
190 precondition(std::getline(f, line), format_error(
"unexpected eof"));
197 precondition(is >> i >> j, format_error());
202 v = read_value<Val>(is);
204 if (row_beg <= i && i < row_end) {
205 ++ptr[i - row_beg + 1];
207 _row.push_back(i - row_beg);
212 if (_symmetric && i != j && row_beg <= j && j < row_end) {
213 ++ptr[j - row_beg + 1];
215 _row.push_back(j - row_beg);
221 std::partial_sum(ptr.begin(), ptr.end(), ptr.begin());
223 col.resize(ptr.back());
224 val.resize(ptr.back());
226 for (
size_t k = 0, e = val.size(); k < e; ++k) {
236 std::rotate(ptr.begin(), ptr.end() - 1, ptr.end());
240 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
242 Idx end = ptr[i + 1];
244 Alina::detail::sort_row(&col[0] + beg, &val[0] + beg, end - beg);
248 return std::make_tuple(chunk, m);
252 template <
typename Val>
254 ptrdiff_t row_beg = -1,
255 ptrdiff_t row_end = -1)
257 precondition(!_sparse, format_error(
"not a dense array"));
259 _complex ?
"attempt to read complex values into real vector" :
"attempt to read real values into complex vector");
260 precondition(std::is_integral<Val>::value == _integer,
261 _integer ?
"attempt to read integer values into real vector" :
"attempt to read real values into integer vector");
265 std::istringstream is;
270 precondition(is >> n >> m, format_error());
278 precondition(row_beg >= 0 && row_end <= n,
279 "Wrong subset of rows is requested");
281 val.resize((row_end - row_beg) * m);
283 for (ptrdiff_t j = 0; j < m; ++j) {
284 for (ptrdiff_t i = 0; i < n; ++i) {
285 precondition(std::getline(f, line), format_error(
"unexpected eof"));
286 if (row_beg <= i && i < row_end) {
289 val[(i - row_beg) * m + j] = read_value<Val>(is);
294 return std::make_tuple(row_end - row_beg, m);
309 std::string format_error(
const std::string& msg =
"")
const
311 std::string err_string =
"MatrixMarket format error";
313 err_string +=
" (" + msg +
")";
317 template <
typename T>
318 typename std::enable_if<Alina::is_complex<T>::value, T>::type
319 read_value(std::istream& s)
321 typename math::scalar_of<T>::type x, y;
322 precondition(s >> x >> y, format_error());
326 template <
typename T>
327 typename std::enable_if<!Alina::is_complex<T>::value, T>::type
328 read_value(std::istream& s)
331 if (std::is_same<T, char>::value) {
335 precondition(s >> i, format_error());
336 x =
static_cast<char>(i);
339 precondition(s >> x, format_error());
350 template <
typename Val>
351 typename std::enable_if<is_complex<Val>::value, std::ostream&>::type
352 write_value(std::ostream& s, Val v)
354 return s << std::scientific << std::setprecision(20) << std::real(v) <<
" " << std::imag(v);
357 template <
typename Val>
358 typename std::enable_if<!is_complex<Val>::value, std::ostream&>::type
359 write_value(std::ostream& s, Val v)
361 return s << std::scientific << std::setprecision(20) << v;
370template <
typename Val>
371void mm_write(
const std::string& fname,
376 std::ofstream f(fname.c_str());
377 precondition(f,
"Failed to open file \"" + fname +
"\" for writing");
380 f <<
"%%MatrixMarket matrix array ";
381 if (is_complex<Val>::value) {
384 else if (std::is_integral<Val>::value) {
393 f << rows <<
" " << cols <<
"\n";
396 for (
size_t j = 0; j < cols; ++j) {
397 for (
size_t i = 0; i < rows; ++i) {
398 detail::write_value(f, data[i * cols + j]) <<
"\n";
407template <
class Matrix>
408void mm_write(
const std::string& fname,
const Matrix& A)
410 typedef typename backend::value_type<Matrix>::type Val;
412 const size_t rows = backend::nbRow(A);
413 const size_t cols = backend::nbColumn(A);
414 const size_t nnz = backend::nonzeros(A);
416 std::ofstream f(fname.c_str());
417 precondition(f,
"Failed to open file \"" + fname +
"\" for writing");
420 f <<
"%%MatrixMarket matrix coordinate ";
421 if (is_complex<Val>::value) {
424 else if (std::is_integral<Val>::value) {
433 f << rows <<
" " << cols <<
" " << nnz <<
"\n";
436 for (
size_t i = 0; i < rows; ++i) {
437 for (
auto a = backend::row_begin(A, i); a; ++a) {
438 f << i + 1 <<
" " << a.col() + 1 <<
" ";
439 detail::write_value(f, a.value()) <<
"\n";
449bool read(std::ifstream& f, T& val)
451 return static_cast<bool>(f.read((
char*)&val,
sizeof(T)));
459bool read(std::ifstream& f, std::vector<T>& vec)
461 return static_cast<bool>(f.read((
char*)&vec[0],
sizeof(T) * vec.size()));
468template <
typename IndexType>
469IndexType crs_size(
const std::string& fname)
471 std::ifstream f(fname.c_str(), std::ios::binary);
474 precondition(f,
"Failed to open matrix file");
475 precondition(read(f, n),
"File I/O error");
484template <
typename SizeT,
typename Ptr,
typename Col,
typename Val>
485void read_crs(
const std::string& fname,
487 std::vector<Ptr>& ptr,
488 std::vector<Col>& col,
489 std::vector<Val>& val,
490 ptrdiff_t row_beg = -1,
491 ptrdiff_t row_end = -1)
493 std::ifstream f(fname.c_str(), std::ios::binary);
494 precondition(f,
"Failed to open matrix file");
496 precondition(read(f, n),
"File I/O error");
503 precondition(row_beg >= 0 && row_end <=
static_cast<ptrdiff_t
>(n),
504 "Wrong subset of rows is requested");
506 ptrdiff_t chunk = row_end - row_beg;
508 ptr.resize(chunk + 1);
510 size_t ptr_beg =
sizeof(SizeT);
511 f.seekg(ptr_beg + row_beg *
sizeof(Ptr));
512 precondition(read(f, ptr),
"File I/O error");
515 f.seekg(ptr_beg + n *
sizeof(Ptr));
516 precondition(read(f, nnz),
"File I/O error");
518 SizeT nnz_beg = ptr.front();
523 col.resize(ptr.back());
524 val.resize(ptr.back());
526 size_t col_beg = ptr_beg + (n + 1) *
sizeof(Ptr);
527 f.seekg(col_beg + nnz_beg *
sizeof(Col));
528 precondition(read(f, col),
"File I/O error");
530 f.seekg(col_beg + nnz *
sizeof(Col) + nnz_beg *
sizeof(Val));
531 precondition(read(f, val),
"File I/O error");
534 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
536 Ptr end = ptr[i + 1];
537 Alina::detail::sort_row(&col[beg], &val[beg], end - beg);
545template <
typename SizeT>
546void dense_size(
const std::string& fname, SizeT& n, SizeT& m)
548 std::ifstream f(fname.c_str(), std::ios::binary);
549 precondition(f,
"Failed to open matrix file");
551 precondition(read(f, n),
"File I/O error");
552 precondition(read(f, m),
"File I/O error");
558template <
typename SizeT,
typename Val>
559void read_dense(
const std::string& fname,
560 SizeT& n, SizeT& m, std::vector<Val>& v,
561 ptrdiff_t row_beg = -1, ptrdiff_t row_end = -1)
563 std::ifstream f(fname.c_str(), std::ios::binary);
564 precondition(f,
"Failed to open matrix file");
566 precondition(read(f, n),
"File I/O error");
567 precondition(read(f, m),
"File I/O error");
574 precondition(row_beg >= 0 && row_end <=
static_cast<ptrdiff_t
>(n),
575 "Wrong subset of rows is requested");
577 ptrdiff_t chunk = row_end - row_beg;
581 f.seekg(2 *
sizeof(SizeT) + row_beg * m *
sizeof(Val));
582 precondition(read(f, v),
"File I/O error");
590bool write(std::ofstream& f,
const T& val)
592 return static_cast<bool>(f.write((
char*)&val,
sizeof(T)));
600bool write(std::ofstream& f,
const std::vector<T>& vec)
602 return static_cast<bool>(f.write((
char*)&vec[0],
sizeof(T) * vec.size()));
bool is_integer() const
Matrix in the file is integer-valued.
size_t rows() const
Number of rows.
bool is_symmetric() const
Matrix in the file is symmetric.
std::tuple< size_t, size_t > operator()(std::vector< Idx > &ptr, std::vector< Idx > &col, std::vector< Val > &val, ptrdiff_t row_beg=-1, ptrdiff_t row_end=-1)
Read sparse matrix from the file.
bool is_sparse() const
Matrix in the file is sparse.
std::tuple< size_t, size_t > operator()(std::vector< Val > &val, ptrdiff_t row_beg=-1, ptrdiff_t row_end=-1)
Read dense array from the file.
mm_reader(const std::string &fname)
Open the file by name.
size_t cols() const
Number of rows.
bool is_complex() const
Matrix in the file is complex-valued.
Informations d'exécution d'une boucle.
void arccoreParallelFor(const ComplexForLoopRanges< RankValue > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applique en concurrence la fonction lambda lambda_function sur l'intervalle d'itération donné par loo...
std::int32_t Int32
Type entier signé sur 32 bits.