12#ifndef ARCCORE_ALINA_IO_H
13#define ARCCORE_ALINA_IO_H
38#include "arccore/alina/AlinaUtils.h"
39#include "arccore/alina/BackendInterface.h"
46namespace Arcane::Alina::IO
61 precondition(f,
"Failed to open file \"" + fname +
"\"");
64 precondition(std::getline(f, line), format_error());
66 std::istringstream is(line);
67 std::string banner, mtx, coord, dtype, storage;
70 is >> banner >> mtx >> coord >> dtype >> storage,
73 precondition(banner ==
"%%MatrixMarket", format_error(
"no banner"));
74 precondition(mtx ==
"matrix", format_error(
"not a matrix"));
76 if (storage ==
"general") {
79 else if (storage ==
"symmetric") {
83 precondition(
false,
"unsupported storage type");
86 if (coord ==
"coordinate") {
89 else if (coord ==
"array") {
93 precondition(
false, format_error(
"unsupported coordinate type"));
96 if (dtype ==
"real") {
100 else if (dtype ==
"complex") {
104 else if (dtype ==
"integer") {
109 precondition(
false, format_error(
"unsupported data type"));
114 precondition(std::getline(f, line), format_error(
"unexpected eof"));
115 }
while (line[0] ==
'%');
120 precondition(is >> nrows >> ncols, format_error());
136 size_t rows()
const {
return nrows; }
139 size_t cols()
const {
return ncols; }
142 template <
typename Idx,
typename Val>
144 std::vector<Idx>& col,
145 std::vector<Val>& val,
146 ptrdiff_t row_beg = -1,
147 ptrdiff_t row_end = -1)
149 precondition(_sparse, format_error(
"not a sparse matrix"));
151 _complex ?
"attempt to read complex values into real vector" :
"attempt to read real values into complex vector");
152 precondition(std::is_integral<Val>::value == _integer,
153 _integer ?
"attempt to read integer values into real vector" :
"attempt to read real values into integer vector");
158 std::istringstream is;
163 precondition(is >> n >> m >> nnz, format_error());
171 precondition(row_beg >= 0 && row_end <= n,
172 "Wrong subset of rows is requested");
174 ptrdiff_t _nnz = _symmetric ? 2 * nnz : nnz;
176 if (row_beg != 0 || row_end != n)
177 _nnz *= 1.2 * (row_end - row_beg) / n;
179 std::vector<Idx> _row;
181 std::vector<Idx> _col;
183 std::vector<Val> _val;
186 ptrdiff_t chunk = row_end - row_beg;
188 ptr.resize(chunk + 1);
189 std::fill(ptr.begin(), ptr.end(), 0);
191 for (
size_t k = 0; k < nnz; ++k) {
192 precondition(std::getline(f, line), format_error(
"unexpected eof"));
199 precondition(is >> i >> j, format_error());
204 v = read_value<Val>(is);
206 if (row_beg <= i && i < row_end) {
207 ++ptr[i - row_beg + 1];
209 _row.push_back(i - row_beg);
214 if (_symmetric && i != j && row_beg <= j && j < row_end) {
215 ++ptr[j - row_beg + 1];
217 _row.push_back(j - row_beg);
223 std::partial_sum(ptr.begin(), ptr.end(), ptr.begin());
225 col.resize(ptr.back());
226 val.resize(ptr.back());
228 for (
size_t k = 0, e = val.size(); k < e; ++k) {
238 std::rotate(ptr.begin(), ptr.end() - 1, ptr.end());
242 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
244 Idx end = ptr[i + 1];
246 Alina::detail::sort_row(&col[0] + beg, &val[0] + beg, end - beg);
250 return std::make_tuple(chunk, m);
254 template <
typename Val>
256 ptrdiff_t row_beg = -1,
257 ptrdiff_t row_end = -1)
259 precondition(!_sparse, format_error(
"not a dense array"));
261 _complex ?
"attempt to read complex values into real vector" :
"attempt to read real values into complex vector");
262 precondition(std::is_integral<Val>::value == _integer,
263 _integer ?
"attempt to read integer values into real vector" :
"attempt to read real values into integer vector");
267 std::istringstream is;
272 precondition(is >> n >> m, format_error());
280 precondition(row_beg >= 0 && row_end <= n,
281 "Wrong subset of rows is requested");
283 val.resize((row_end - row_beg) * m);
285 for (ptrdiff_t j = 0; j < m; ++j) {
286 for (ptrdiff_t i = 0; i < n; ++i) {
287 precondition(std::getline(f, line), format_error(
"unexpected eof"));
288 if (row_beg <= i && i < row_end) {
291 val[(i - row_beg) * m + j] = read_value<Val>(is);
296 return std::make_tuple(row_end - row_beg, m);
311 std::string format_error(
const std::string& msg =
"")
const
313 std::string err_string =
"MatrixMarket format error";
315 err_string +=
" (" + msg +
")";
319 template <
typename T>
320 typename std::enable_if<Alina::is_complex<T>::value, T>::type
321 read_value(std::istream& s)
323 typename math::scalar_of<T>::type x, y;
324 precondition(s >> x >> y, format_error());
328 template <
typename T>
329 typename std::enable_if<!Alina::is_complex<T>::value, T>::type
330 read_value(std::istream& s)
333 if (std::is_same<T, char>::value) {
337 precondition(s >> i, format_error());
338 x =
static_cast<char>(i);
341 precondition(s >> x, format_error());
352 template <
typename Val>
353 typename std::enable_if<is_complex<Val>::value, std::ostream&>::type
354 write_value(std::ostream& s, Val v)
356 return s << std::scientific << std::setprecision(20) << std::real(v) <<
" " << std::imag(v);
359 template <
typename Val>
360 typename std::enable_if<!is_complex<Val>::value, std::ostream&>::type
361 write_value(std::ostream& s, Val v)
363 return s << std::scientific << std::setprecision(20) << v;
372template <
typename Val>
373void mm_write(
const std::string& fname,
378 std::ofstream f(fname.c_str());
379 precondition(f,
"Failed to open file \"" + fname +
"\" for writing");
382 f <<
"%%MatrixMarket matrix array ";
383 if (is_complex<Val>::value) {
386 else if (std::is_integral<Val>::value) {
395 f << rows <<
" " << cols <<
"\n";
398 for (
size_t j = 0; j < cols; ++j) {
399 for (
size_t i = 0; i < rows; ++i) {
400 detail::write_value(f, data[i * cols + j]) <<
"\n";
409template <
class Matrix>
410void mm_write(
const std::string& fname,
const Matrix& A)
412 typedef typename backend::value_type<Matrix>::type Val;
414 const size_t rows = backend::nbRow(A);
415 const size_t cols = backend::nbColumn(A);
416 const size_t nnz = backend::nonzeros(A);
418 std::ofstream f(fname.c_str());
419 precondition(f,
"Failed to open file \"" + fname +
"\" for writing");
422 f <<
"%%MatrixMarket matrix coordinate ";
423 if (is_complex<Val>::value) {
426 else if (std::is_integral<Val>::value) {
435 f << rows <<
" " << cols <<
" " << nnz <<
"\n";
438 for (
size_t i = 0; i < rows; ++i) {
439 for (
auto a = backend::row_begin(A, i); a; ++a) {
440 f << i + 1 <<
" " << a.col() + 1 <<
" ";
441 detail::write_value(f, a.value()) <<
"\n";
451bool read(std::ifstream& f, T& val)
453 return static_cast<bool>(f.read((
char*)&val,
sizeof(T)));
461bool read(std::ifstream& f, std::vector<T>& vec)
463 return static_cast<bool>(f.read((
char*)&vec[0],
sizeof(T) * vec.size()));
470template <
typename IndexType>
471IndexType crs_size(
const std::string& fname)
473 std::ifstream f(fname.c_str(), std::ios::binary);
476 precondition(f,
"Failed to open matrix file");
477 precondition(read(f, n),
"File I/O error");
486template <
typename SizeT,
typename Ptr,
typename Col,
typename Val>
487void read_crs(
const std::string& fname,
489 std::vector<Ptr>& ptr,
490 std::vector<Col>& col,
491 std::vector<Val>& val,
492 ptrdiff_t row_beg = -1,
493 ptrdiff_t row_end = -1)
495 std::ifstream f(fname.c_str(), std::ios::binary);
496 precondition(f,
"Failed to open matrix file");
498 precondition(read(f, n),
"File I/O error");
505 precondition(row_beg >= 0 && row_end <=
static_cast<ptrdiff_t
>(n),
506 "Wrong subset of rows is requested");
508 ptrdiff_t chunk = row_end - row_beg;
510 ptr.resize(chunk + 1);
512 size_t ptr_beg =
sizeof(SizeT);
513 f.seekg(ptr_beg + row_beg *
sizeof(Ptr));
514 precondition(read(f, ptr),
"File I/O error");
517 f.seekg(ptr_beg + n *
sizeof(Ptr));
518 precondition(read(f, nnz),
"File I/O error");
520 SizeT nnz_beg = ptr.front();
525 col.resize(ptr.back());
526 val.resize(ptr.back());
528 size_t col_beg = ptr_beg + (n + 1) *
sizeof(Ptr);
529 f.seekg(col_beg + nnz_beg *
sizeof(Col));
530 precondition(read(f, col),
"File I/O error");
532 f.seekg(col_beg + nnz *
sizeof(Col) + nnz_beg *
sizeof(Val));
533 precondition(read(f, val),
"File I/O error");
536 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
538 Ptr end = ptr[i + 1];
539 Alina::detail::sort_row(&col[beg], &val[beg], end - beg);
547template <
typename SizeT>
548void dense_size(
const std::string& fname, SizeT& n, SizeT& m)
550 std::ifstream f(fname.c_str(), std::ios::binary);
551 precondition(f,
"Failed to open matrix file");
553 precondition(read(f, n),
"File I/O error");
554 precondition(read(f, m),
"File I/O error");
560template <
typename SizeT,
typename Val>
561void read_dense(
const std::string& fname,
562 SizeT& n, SizeT& m, std::vector<Val>& v,
563 ptrdiff_t row_beg = -1, ptrdiff_t row_end = -1)
565 std::ifstream f(fname.c_str(), std::ios::binary);
566 precondition(f,
"Failed to open matrix file");
568 precondition(read(f, n),
"File I/O error");
569 precondition(read(f, m),
"File I/O error");
576 precondition(row_beg >= 0 && row_end <=
static_cast<ptrdiff_t
>(n),
577 "Wrong subset of rows is requested");
579 ptrdiff_t chunk = row_end - row_beg;
583 f.seekg(2 *
sizeof(SizeT) + row_beg * m *
sizeof(Val));
584 precondition(read(f, v),
"File I/O error");
592bool write(std::ofstream& f,
const T& val)
594 return static_cast<bool>(f.write((
char*)&val,
sizeof(T)));
602bool write(std::ofstream& f,
const std::vector<T>& vec)
604 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.