Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_MatrixMarket_CoordDataReader.hpp
1// @HEADER
2// *****************************************************************************
3// Tpetra: Templated Linear Algebra Services Package
4//
5// Copyright 2008 NTESS and the Tpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef __Teuchos_MatrixMarket_CoordDataReader_hpp
11#define __Teuchos_MatrixMarket_CoordDataReader_hpp
12
13#include "Teuchos_MatrixMarket_generic.hpp"
14#include "Teuchos_RCP.hpp"
16#include "Teuchos_Tuple.hpp"
17
18
19namespace Teuchos {
20 namespace MatrixMarket {
67 template<class Callback, class Ordinal>
69 protected:
72
73 public:
86
95
98
106 adder_ = adder;
107 }
108
109 protected:
136 virtual bool
137 readLine (const std::string& theLine,
138 const size_t lineNumber,
139 const bool tolerant) = 0;
140
141 public:
142
170 virtual std::pair<bool, std::vector<size_t> >
171 read (std::istream& in,
172 const size_t startingLineNumber,
173 const bool tolerant,
174 const bool debug = false)
175 {
176 (void) debug; // silence unused input argument warning
177 TEUCHOS_TEST_FOR_EXCEPTION(! in, std::invalid_argument,
178 "Input stream is invalid.");
179
180 std::string line;
182 bool allSucceeded = true;
183 std::vector<size_t> badLineNumbers;
184 while (getline (in, line)) {
185 size_t start, size;
186 if (checkCommentLine (line, start, size, lineNumber, tolerant)) {
187 ++lineNumber;
188 continue; // it's a comment line
189 }
190 const std::string theLine = line.substr (start, size);
191
193 ++lineNumber;
195 if (! localSuccess) {
196 badLineNumbers.push_back (lineNumber);
197 }
198 }
199 return std::make_pair (allSucceeded, badLineNumbers);
200 }
201
225 std::pair<Teuchos::Tuple<Ordinal, 3>, bool>
226 readDimensions (std::istream& in,
227 size_t& lineNumber,
228 const bool tolerant = false)
229 {
231 // Fill in (numRows, numCols, numNonzeros) with reasonable
232 // defaults. If we don't succeed in reading all the data
233 // from the current line of the input stream, the remaining
234 // values not read will be these default values.
235 dims[0] = 0;
236 dims[1] = 0;
237 dims[2] = 0;
238
239 // Keep reading lines from the input stream until we find a
240 // non-comment line, or until we run out of lines. The latter
241 // is an error, since every "coordinate" format Matrix Market
242 // file must have a dimensions line after the banner (even if
243 // the matrix has zero rows or columns, or zero entries).
244 std::string line;
245 bool commentLine = true;
246 while (commentLine) {
247 // Is it even valid to read from the input stream?
248 if (in.eof() || in.fail()) {
249 if (tolerant) {
250 return std::make_pair (dims, false);
251 }
252 else {
253 std::ostringstream os;
254 os << "Unable to get coordinate dimensions line (at all) "
255 "from (line " << lineNumber << ") of input stream; the "
256 "input stream claims that it is at \"end-of-file\" or has "
257 "an otherwise \"fail\"ed state.";
258 throw std::invalid_argument(os.str());
259 }
260 }
261 // Try to get the next line from the input stream.
262 if (getline(in, line)) {
263 lineNumber++; // We did actually read a line
264 }
265 else {
266 if (tolerant) {
267 return std::make_pair (dims, false);
268 }
269 else {
270 std::ostringstream os;
271 os << "Failed to read coordinate dimensions line (at all) "
272 "from (line " << lineNumber << " from input stream. The "
273 "line should contain the coordinate matrix dimensions in "
274 << " the form \"<numRows> <numCols> <numNonzeros>\".";
275 throw std::invalid_argument (os.str());
276 }
277 }
278 // Is the current line a comment line? Ignore start and
279 // size; they are only useful for reading the actual matrix
280 // entries. (We could use them here as an optimization, but
281 // we've chosen not to.)
282 size_t start = 0, size = 0;
283 commentLine = checkCommentLine (line, start, size,
285 }
286 //
287 // Read in <numRows> <numCols> <numNonzeros> from input line
288 //
289 std::istringstream istr (line);
290 // Does line contain anything at all? Can we safely read from
291 // the input stream wrapping the line?
292 if (istr.eof() || istr.fail()) {
293 if (tolerant) {
294 return std::make_pair (dims, false);
295 }
296 std::ostringstream os;
297 os << "Unable to read any data from line " << lineNumber
298 << " of input; the line should contain the coordinate matrix "
299 << "dimensions \"<numRows> <numCols> <numNonzeros>\".";
300 throw std::invalid_argument(os.str());
301 }
302 // Read in <numRows>
303 {
304 Ordinal theNumRows = 0;
305 istr >> theNumRows;
306 if (istr.fail()) {
307 if (tolerant) {
308 return std::make_pair (dims, false);
309 }
310 std::ostringstream os;
311 os << "Failed to get number of rows from line " << lineNumber
312 << " of input; the line should contain the coordinate matrix "
313 << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
314 throw std::invalid_argument(os.str());
315 }
316 else { // Capture the validly read result before checking for eof.
317 dims[0] = theNumRows;
318 }
319 }
320 // There should be two more things to read.
321 if (istr.eof()) {
322 if (tolerant) {
323 return std::make_pair (dims, false);
324 }
325 std::ostringstream os;
326 os << "No more data after number of rows on line " << lineNumber
327 << " of input; the line should contain the coordinate matrix "
328 << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
329 throw std::invalid_argument(os.str());
330 }
331 // Read in <numCols>
332 {
333 Ordinal theNumCols = 0;
334 istr >> theNumCols;
335 if (istr.fail()) {
336 if (tolerant) {
337 return std::make_pair (dims, false);
338 }
339 std::ostringstream os;
340 os << "Failed to get number of columns from line " << lineNumber
341 << " of input; the line should contain the coordinate matrix "
342 << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
343 throw std::invalid_argument(os.str());
344 }
345 else { // Capture the validly read result before checking for eof.
346 dims[1] = theNumCols;
347 }
348 }
349 // There should be one more thing to read.
350 if (istr.eof()) {
351 if (tolerant) {
352 return std::make_pair (dims, false);
353 }
354 std::ostringstream os;
355 os << "No more data after number of columns on line " << lineNumber
356 << " of input; the line should contain the coordinate matrix "
357 << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
358 throw std::invalid_argument(os.str());
359 }
360 // Read in <numNonzeros>
361 {
362 Ordinal theNumNonzeros = 0;
364 if (istr.fail()) {
365 if (tolerant) {
366 return std::make_pair (dims, false);
367 }
368 std::ostringstream os;
369 os << "Failed to get number of (structural) nonzeros from line "
370 << lineNumber
371 << " of input; the line should contain the coordinate matrix "
372 << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
373 throw std::invalid_argument(os.str());
374 }
375 else { // Capture the validly read result
376 dims[2] = theNumNonzeros;
377 }
378 }
379 // It would be nice to validate the read-in data further. The
380 // only thing we can do now is test if it's negative. However,
381 // we don't know syntactically whether Ordinal is a signed or
382 // unsigned type, so we shouldn't even test for negativity.
383 return std::make_pair (dims, true);
384 }
385 };
386
421 template<class Callback,
422 class Ordinal,
423 class Scalar,
425 class CoordDataReader : public CoordDataReaderBase<Callback, Ordinal> {
426 public:
440
449
452
453 protected:
454 bool
455 readLine (const std::string& theLine,
456 const size_t lineNumber,
457 const bool tolerant);
458 };
459
460#ifdef HAVE_TEUCHOS_COMPLEX
461 // Partial specialization for complex Scalar types.
462 template<class Callback, class Ordinal, class Scalar>
463 class CoordDataReader<Callback, Ordinal, Scalar, true> :
464 public CoordDataReaderBase<Callback, Ordinal> {
465 public:
468 {}
469
471 CoordDataReaderBase<Callback, Ordinal> (null)
472 {}
473
474 virtual ~CoordDataReader() {};
475
476 protected:
477 bool
478 readLine (const std::string& theLine,
479 const size_t lineNumber,
480 const bool tolerant)
481 {
483 typedef typename STS::magnitudeType Real;
484
485 Ordinal rowIndex;
486 Ordinal colIndex;
487 Scalar value;
488
489 Real realPart, imagPart;
490 const bool localSuccess =
491 readComplexLine (theLine, rowIndex, colIndex, realPart, imagPart,
492 lineNumber, tolerant);
493 if (localSuccess) {
494 // Assume that assignment from std::complex<Real> to Scalar
495 // (which itself is complex-valued) is valid. We have to do
496 // this, since the C++ compiler may not be smart enough to
497 // assume here (when it instantiates the templates) that
498 // Scalar is an std::complex<Real> -- even though it has to
499 // be, if STS::isComplex is true (which as of 31 Jan 2011,
500 // only holds for std::complex<T>).
501 value = std::complex<Real> (realPart, imagPart);
502
503 // Now that we've read in the (i, j, A_ij) triple
504 // successfully, we can add the entry to the sparse matrix.
505 (*(this->adder_)) (rowIndex, colIndex, value);
506 }
507 return localSuccess;
508 }
509 };
510#endif // HAVE_TEUCHOS_COMPLEX
511
512 // Partial specialization for real Scalar types.
513 template<class Callback, class Ordinal, class Scalar>
514 class CoordDataReader<Callback, Ordinal, Scalar, false> :
515 public CoordDataReaderBase<Callback, Ordinal> {
516 public:
518 CoordDataReaderBase<Callback, Ordinal> (adder)
519 {}
520
522 CoordDataReaderBase<Callback, Ordinal> (null)
523 {}
524
525 virtual ~CoordDataReader() {};
526
527 protected:
528 bool
529 readLine (const std::string& theLine,
530 const size_t lineNumber,
531 const bool tolerant)
532 {
533 Ordinal rowIndex;
534 Ordinal colIndex;
535 Scalar value;
536 const bool localSuccess = readRealLine (theLine, rowIndex, colIndex,
537 value, lineNumber, tolerant);
538 if (localSuccess) {
539 // Now that we've read in the (i, j, A_ij) triple
540 // successfully, we can add the entry to the sparse matrix.
541 (*(this->adder_)) (rowIndex, colIndex, value);
542 }
543 return localSuccess;
544 }
545 };
546
547
570 template<class Callback, class Ordinal>
571 class CoordPatternReader : public CoordDataReaderBase<Callback, Ordinal> {
572 public:
588
597 CoordDataReaderBase<Callback, Ordinal> (null)
598 {}
599
602
603 protected:
604 bool
605 readLine (const std::string& theLine,
606 const size_t lineNumber,
607 const bool tolerant)
608 {
609 Ordinal rowIndex;
610 Ordinal colIndex;
611 const bool localSuccess =
612 readPatternLine (theLine, rowIndex, colIndex, lineNumber, tolerant);
613 if (localSuccess) {
614 // Now that we've read in the (i, j) pair successfully, we
615 // can add the entry to the sparse graph.
616 (*(this->adder_)) (rowIndex, colIndex);
617 }
618 return localSuccess;
619 }
620 };
621
622 } // namespace MatrixMarket
623} // namespace Teuchos
624
625#endif // __Teuchos_MatrixMarket_CoordDataReader_hpp
Reference-counted pointer class and non-member templated function implementations.
Defines basic traits for the scalar field type.
Common functionality of a coordinate-format sparse matrix or graph data reader.
virtual ~CoordDataReaderBase()
Virtual destructor for safety and happy compilers.
virtual std::pair< bool, std::vector< size_t > > read(std::istream &in, const size_t startingLineNumber, const bool tolerant, const bool debug=false)
Read in all the data from the given input stream.
std::pair< Teuchos::Tuple< Ordinal, 3 >, bool > readDimensions(std::istream &in, size_t &lineNumber, const bool tolerant=false)
Read (numRows, numCols, numNonzeros).
Teuchos::RCP< Callback > adder_
Closure that knows how to add entries to the sparse graph or matrix.
CoordDataReaderBase(const Teuchos::RCP< Callback > &adder)
Constructor with "adder" argument.
virtual bool readLine(const std::string &theLine, const size_t lineNumber, const bool tolerant)=0
Read in the data from a single line of the input stream.
void setAdder(const Teuchos::RCP< Callback > &adder)
Set the Adder object.
Coordinate-format sparse matrix data reader.
CoordDataReader()
No-argument constructor.
virtual ~CoordDataReader()
Virtual destructor for safety and happy compilers.
CoordDataReader(const Teuchos::RCP< Callback > &adder)
Constructor with "adder" argument.
bool readLine(const std::string &theLine, const size_t lineNumber, const bool tolerant)
Read in the data from a single line of the input stream.
CoordPatternReader(const Teuchos::RCP< Callback > &adder)
Constructor with "adder" argument.
virtual ~CoordPatternReader()
Virtual destructor for safety and happy compilers.
bool readLine(const std::string &theLine, const size_t lineNumber, const bool tolerant)
Read in the data from a single line of the input stream.
Smart reference counting pointer class for automatic garbage collection.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Matrix Market file utilities.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
This structure defines some basic traits for a scalar field type.