Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_MatrixMarket_generic.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_generic_hpp
11#define __Teuchos_MatrixMarket_generic_hpp
12
14#ifdef HAVE_TEUCHOS_COMPLEX
15# include <complex>
16#endif // HAVE_TEUCHOS_COMPLEX
17#include <iostream>
18#include <sstream>
19#include <stdexcept>
20#include <type_traits>
21#include <vector>
22
23namespace Teuchos {
24 namespace MatrixMarket {
25
31 int maxLineLength();
32
61 TEUCHOSNUMERICS_LIB_DLL_EXPORT bool
62 checkCommentLine (const std::string& line,
63 size_t& start,
64 size_t& size,
65 const size_t lineNumber,
66 const bool tolerant,
67 const bool maybeBannerLine = false);
68
102 template<class Ordinal>
103 bool
104 readPatternData (std::istream& istr,
105 Ordinal& rowIndex,
106 Ordinal& colIndex,
107 const size_t lineNumber,
108 const bool tolerant)
109 {
110 Ordinal the_rowIndex, the_colIndex;
111
112 if (istr.eof() || istr.fail())
113 {
114 if (tolerant)
115 return false;
116 else
117 {
118 std::ostringstream os;
119 os << "Unable to read any data from line " << lineNumber << " of input";
120 throw std::invalid_argument(os.str());
121 }
122 }
123 istr >> the_rowIndex;
124 if (istr.fail())
125 {
126 if (tolerant)
127 return false;
128 else
129 {
130 std::ostringstream os;
131 os << "Failed to get row index from line " << lineNumber << " of input";
132 throw std::invalid_argument(os.str());
133 }
134 }
135 else if (istr.eof())
136 {
137 if (tolerant)
138 return false;
139 else
140 {
141 std::ostringstream os;
142 os << "No more data after row index on line " << lineNumber << " of input";
143 throw std::invalid_argument(os.str());
144 }
145 }
146 istr >> the_colIndex;
147 if (istr.fail())
148 {
149 if (tolerant)
150 return false;
151 else
152 {
153 std::ostringstream os;
154 os << "Failed to get column index from line " << lineNumber << " of input";
155 throw std::invalid_argument(os.str());
156 }
157 }
158 rowIndex = the_rowIndex;
159 colIndex = the_colIndex;
160 return true;
161 }
162
201 template<class Ordinal, class Real>
202 bool
203 readRealData (std::istream& istr,
204 Ordinal& rowIndex,
205 Ordinal& colIndex,
206 Real& realValue,
207 const size_t lineNumber,
208 const bool tolerant)
209 {
210 Real the_realValue;
211 if (! readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant))
212 {
213 if (tolerant)
214 return false;
215 else
216 {
217 std::ostringstream os;
218 os << "Failed to read pattern data from line " << lineNumber << " of input";
219 throw std::invalid_argument(os.str());
220 }
221 }
222 if (istr.eof())
223 {
224 if (tolerant)
225 return false;
226 else
227 {
228 std::ostringstream os;
229 os << "No more data after pattern data on line " << lineNumber << " of input";
230 throw std::invalid_argument(os.str());
231 }
232 }
233 {
234 if (std::is_same<Real, float>::value) {
235 double dblVal {};
236 istr >> dblVal;
237 the_realValue = static_cast<Real> (dblVal);
238 }
239 else {
240 istr >> the_realValue;
241 }
242 }
243 if (istr.fail())
244 {
245 if (tolerant)
246 return false;
247 else
248 {
249 std::ostringstream os;
250 os << "Failed to get real value from line " << lineNumber << " of input";
251 throw std::invalid_argument(os.str());
252 }
253 }
254 realValue = the_realValue;
255 return true;
256 }
257
258#ifdef HAVE_TEUCHOS_COMPLEX
259
301 template<class Ordinal, class Real>
302 bool
303 readComplexData (std::istream& istr,
304 Ordinal& rowIndex,
305 Ordinal& colIndex,
306 Real& realPart,
307 Real& imagPart,
308 const size_t lineNumber,
309 const bool tolerant)
310 {
311 Real the_realPart, the_imagPart;
312 if (! readRealData (istr, rowIndex, colIndex, the_realPart, lineNumber, tolerant))
313 {
314 if (tolerant)
315 return false;
316 else
317 {
318 std::ostringstream os;
319 os << "Failed to read pattern data and/or real value from line "
320 << lineNumber << " of input";
321 throw std::invalid_argument(os.str());
322 }
323 }
324 if (istr.eof())
325 {
326 if (tolerant)
327 return false;
328 else
329 {
330 std::ostringstream os;
331 os << "No more data after real value on line "
332 << lineNumber << " of input";
333 throw std::invalid_argument(os.str());
334 }
335 }
336 istr >> the_imagPart;
337 if (istr.fail())
338 {
339 if (tolerant)
340 return false;
341 else
342 {
343 std::ostringstream os;
344 os << "Failed to get imaginary value from line "
345 << lineNumber << " of input";
346 throw std::invalid_argument(os.str());
347 }
348 }
349 realPart = the_realPart;
350 imagPart = the_imagPart;
351 return true;
352 }
353#endif // HAVE_TEUCHOS_COMPLEX
354
355 template<class Ordinal>
356 bool
357 readPatternLine (const std::string& line, // only the data-containing part
358 Ordinal& rowIndex,
359 Ordinal& colIndex,
360 const size_t lineNumber,
361 const bool tolerant)
362 {
363 // The part of the line that contains data
364 std::istringstream istr (line);
365 return readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant);
366 }
367
368 template<class Ordinal, class Real>
369 bool
370 readRealLine (const std::string& line,
371 Ordinal& rowIndex,
372 Ordinal& colIndex,
373 Real& realValue,
374 const size_t lineNumber,
375 const bool tolerant)
376 {
377 size_t start, size;
378 if (checkCommentLine (line, start, size, lineNumber, tolerant)) {
379 return false; // It's a comment line
380 }
381 // If it's an empty line, checkCommentLine() will throw an
382 // exception if non-tolerant parsing is being performed, so
383 // we need only return false otherwise.
384 if (size == 0) {
385 if (! tolerant) {
386 throw std::logic_error("Should never get here! checkCommentLine() "
387 "is supposed to catch empty lines.");
388 }
389 else {
390 return false;
391 }
392 }
393 // The part of the line that contains data
394 std::istringstream istr (line.substr (start, size));
395 return readRealData (istr, rowIndex, colIndex, realValue, lineNumber, tolerant);
396 }
397
398#ifdef HAVE_TEUCHOS_COMPLEX
399 template<class Ordinal, class Real>
400 bool
401 readComplexLine (const std::string& line,
402 Ordinal& rowIndex,
403 Ordinal& colIndex,
404 Real& realPart,
405 Real& imagPart,
406 const size_t lineNumber,
407 const bool tolerant)
408 {
409 size_t start, end;
410 if (checkCommentLine (line, start, end, lineNumber, tolerant))
411 return false; // It's a comment line
412 // If it's an empty line, checkCommentLine() will throw an
413 // exception if non-tolerant parsing is being performed, so
414 // we need only return false otherwise.
415 if (end == 0)
416 {
417 if (tolerant)
418 throw std::logic_error("Should never get here! checkCommentLine() "
419 "is supposed to catch empty lines.");
420 else
421 return false;
422 }
423 // The part of the line that contains data
424 std::istringstream istr (line.substr (start, end));
425 // Read the data
426 Real the_realPart, the_imagPart;
427 const bool success =
428 readComplexData (istr, rowIndex, colIndex, the_realPart, the_imagPart,
429 lineNumber, tolerant);
430 if (success)
431 {
432 realPart = the_realPart;
433 imagPart = the_imagPart;
434 }
435 return success;
436 }
437#endif // HAVE_TEUCHOS_COMPLEX
438
439 template<class Ordinal, class PatternCallback>
440 std::pair<bool, std::vector<size_t> >
441 readPatternCoordinateData (std::istream& in,
442 PatternCallback add,
443 const size_t startingLineNumber,
444 const bool tolerant)
445 {
446 std::string line;
447 size_t lineNumber = startingLineNumber;
448 bool anySucceeded = false;
449 bool allSucceeded = true;
450 std::vector<size_t> badLineNumbers;
451 while (getline (in, line)) {
452 size_t start, size;
453 if (checkCommentLine (line, start, size, lineNumber, tolerant)) {
454 continue; // it's a comment line
455 }
456 const std::string theLine = line.substr (start, size);
457
458 Ordinal rowIndex, colIndex;
459 const bool localSuccess =
460 readPatternLine (theLine, rowIndex, colIndex,
461 lineNumber++, tolerant);
462 anySucceeded = anySucceeded || localSuccess;
463 allSucceeded = allSucceeded && localSuccess;
464 if (! localSuccess) {
465 badLineNumbers.push_back (lineNumber);
466 }
467 else {
468 // Add the newly read entry to the sparse graph.
469 add(rowIndex, colIndex);
470 }
471 }
472 if (lineNumber == startingLineNumber) {
473 anySucceeded = true; // Trivially true
474 }
475
476 return std::make_pair (allSucceeded, badLineNumbers);
477 }
478
479
480 template<class Ordinal>
481 bool
482 readCoordinateDimensions (std::istream& in,
483 Ordinal& numRows,
484 Ordinal& numCols,
485 Ordinal& numNonzeros,
486 size_t& lineNumber,
487 const bool tolerant)
488 {
489 using std::endl;
490
491 Ordinal the_numRows, the_numCols, the_numNonzeros;
492 std::string line;
493
494 // Keep reading lines from the input stream until we find a
495 // non-comment line, or until we run out of lines. The latter
496 // is an error, since every "coordinate" format Matrix Market
497 // file must have a dimensions line after the banner (even if
498 // the matrix has zero rows or columns, or zero entries).
499 bool commentLine = true;
500 while (commentLine)
501 {
502 // Is it even valid to read from the input stream?
503 if (in.eof () || in.fail ()) {
504 if (tolerant) {
505 return false;
506 }
507 else {
508 std::ostringstream os;
509 os << "Unable to get coordinate dimensions line (at all) "
510 "from (line " << lineNumber << ") of input stream; the "
511 "input stream claims that it is at \"end-of-file\" or has "
512 "an otherwise \"fail\"ed state.";
513 throw std::invalid_argument(os.str());
514 }
515 }
516 // Try to get the next line from the input stream.
517 if (! getline (in, line)) {
518 if (tolerant) {
519 return false;
520 }
521 else {
522 std::ostringstream os;
523 os << "Failed to read coordinate dimensions line (at all) "
524 "from (line " << lineNumber << " from input stream. The "
525 "line should contain the coordinate matrix dimensions in "
526 << " the form \"<numRows> <numCols> <numNonzeros>\".";
527 throw std::invalid_argument(os.str());
528 }
529 }
530 // Is the current line a comment line? Ignore start and
531 // size; they are only useful for reading the actual matrix
532 // entries. (We could use them here as an optimization, but
533 // we've chosen not to.)
534 size_t start = 0, size = 0;
535 commentLine = checkCommentLine (line, start, size,
536 lineNumber, tolerant);
537 // This ensures that any error messages in this file are
538 // correct.
539 if (commentLine) {
540 ++lineNumber;
541 }
542 }
543
544 // The current line is now not a comment line.
545 // Try to read the coordinate dimensions from it.
546 std::istringstream istr (line);
547 if (istr.eof () || istr.fail ()) {
548 if (tolerant) {
549 return false;
550 }
551 else {
552 std::ostringstream os;
553 os << "Unable to read any coordinate dimensions data from line "
554 << lineNumber << " of input stream. Offending line:" << endl
555 << line;
556 throw std::invalid_argument(os.str());
557 }
558 }
559 istr >> the_numRows;
560 if (istr.fail ()) {
561 if (tolerant) {
562 return false;
563 }
564 else {
565 std::ostringstream os;
566 os << "Failed to get number of rows from the coordinate "
567 "dimensions line (line " << lineNumber << " of input stream)."
568 " Offending line:" << endl << line;
569 throw std::invalid_argument(os.str());
570 }
571 }
572 else if (istr.eof ()) {
573 if (tolerant) {
574 return false;
575 }
576 else {
577 std::ostringstream os;
578 os << "No more data after number of rows, in the coordinate "
579 "dimensions line (line " << lineNumber << " of input stream)."
580 " Offending line:" << endl << line;
581 throw std::invalid_argument(os.str());
582 }
583 }
584 istr >> the_numCols;
585 if (istr.fail ()) {
586 if (tolerant) {
587 return false;
588 }
589 else {
590 std::ostringstream os;
591 os << "Failed to get number of columns from the coordinate "
592 "dimensions line (line " << lineNumber << " of input stream)."
593 " Offending line:" << endl << line;
594 throw std::invalid_argument(os.str());
595 }
596 }
597 else if (istr.eof ()) {
598 if (tolerant) {
599 return false;
600 }
601 else {
602 std::ostringstream os;
603 os << "No more data after number of columns, in the coordinate "
604 "dimensions line (line " << lineNumber << " of input stream)."
605 " Offending line:" << endl << line;
606 throw std::invalid_argument (os.str ());
607 }
608 }
609 istr >> the_numNonzeros;
610 if (istr.fail ()) {
611 if (tolerant) {
612 return false;
613 }
614 else {
615 std::ostringstream os;
616 os << "Failed to get number of nonzeros from the coordinate "
617 "dimensions line (line " << lineNumber << " of input stream)."
618 " Offending line:" << endl << line;
619 throw std::invalid_argument (os.str ());
620 }
621 }
622 numRows = the_numRows;
623 numCols = the_numCols;
624 numNonzeros = the_numNonzeros;
625 // This function only increments the line number when it reads a
626 // comment line successfully, or when it reads all the
627 // coordinate dimensions successfully.
628 ++lineNumber;
629 return true;
630 }
631
632 } // namespace MatrixMarket
633} // namespace Teuchos
634
635#endif // __Teuchos_MatrixMarket_generic_hpp
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
Matrix Market file utilities.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...