Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
Teuchos_MatrixMarket_generic.hpp
Go to the documentation of this file.
1// @HEADER
2// ***********************************************************************
3//
4// Tpetra: Templated Linear Algebra Services Package
5// Copyright (2008) Sandia Corporation
6//
7// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8// the U.S. Government retains certain rights in this software.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ************************************************************************
40// @HEADER
41
42#ifndef __Teuchos_MatrixMarket_generic_hpp
43#define __Teuchos_MatrixMarket_generic_hpp
44
46#ifdef HAVE_TEUCHOS_COMPLEX
47# include <complex>
48#endif // HAVE_TEUCHOS_COMPLEX
49#include <iostream>
50#include <sstream>
51#include <stdexcept>
52#include <type_traits>
53#include <vector>
54
55namespace Teuchos {
56 namespace MatrixMarket {
57
63 int maxLineLength();
64
94 checkCommentLine (const std::string& line,
95 size_t& start,
96 size_t& size,
97 const size_t lineNumber,
98 const bool tolerant,
99 const bool maybeBannerLine = false);
100
134 template<class Ordinal>
135 bool
136 readPatternData (std::istream& istr,
137 Ordinal& rowIndex,
138 Ordinal& colIndex,
139 const size_t lineNumber,
140 const bool tolerant)
141 {
142 Ordinal the_rowIndex, the_colIndex;
143
144 if (istr.eof() || istr.fail())
145 {
146 if (tolerant)
147 return false;
148 else
149 {
150 std::ostringstream os;
151 os << "Unable to read any data from line " << lineNumber << " of input";
152 throw std::invalid_argument(os.str());
153 }
154 }
155 istr >> the_rowIndex;
156 if (istr.fail())
157 {
158 if (tolerant)
159 return false;
160 else
161 {
162 std::ostringstream os;
163 os << "Failed to get row index from line " << lineNumber << " of input";
164 throw std::invalid_argument(os.str());
165 }
166 }
167 else if (istr.eof())
168 {
169 if (tolerant)
170 return false;
171 else
172 {
173 std::ostringstream os;
174 os << "No more data after row index on line " << lineNumber << " of input";
175 throw std::invalid_argument(os.str());
176 }
177 }
178 istr >> the_colIndex;
179 if (istr.fail())
180 {
181 if (tolerant)
182 return false;
183 else
184 {
185 std::ostringstream os;
186 os << "Failed to get column index from line " << lineNumber << " of input";
187 throw std::invalid_argument(os.str());
188 }
189 }
190 rowIndex = the_rowIndex;
191 colIndex = the_colIndex;
192 return true;
193 }
194
233 template<class Ordinal, class Real>
234 bool
235 readRealData (std::istream& istr,
236 Ordinal& rowIndex,
237 Ordinal& colIndex,
238 Real& realValue,
239 const size_t lineNumber,
240 const bool tolerant)
241 {
242 Real the_realValue;
243 if (! readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant))
244 {
245 if (tolerant)
246 return false;
247 else
248 {
249 std::ostringstream os;
250 os << "Failed to read pattern data from line " << lineNumber << " of input";
251 throw std::invalid_argument(os.str());
252 }
253 }
254 if (istr.eof())
255 {
256 if (tolerant)
257 return false;
258 else
259 {
260 std::ostringstream os;
261 os << "No more data after pattern data on line " << lineNumber << " of input";
262 throw std::invalid_argument(os.str());
263 }
264 }
265 {
266 if (std::is_same<Real, float>::value) {
267 double dblVal {};
268 istr >> dblVal;
269 the_realValue = static_cast<Real> (dblVal);
270 }
271 else {
272 istr >> the_realValue;
273 }
274 }
275 if (istr.fail())
276 {
277 if (tolerant)
278 return false;
279 else
280 {
281 std::ostringstream os;
282 os << "Failed to get real value from line " << lineNumber << " of input";
283 throw std::invalid_argument(os.str());
284 }
285 }
286 realValue = the_realValue;
287 return true;
288 }
289
290#ifdef HAVE_TEUCHOS_COMPLEX
291
333 template<class Ordinal, class Real>
334 bool
335 readComplexData (std::istream& istr,
336 Ordinal& rowIndex,
337 Ordinal& colIndex,
338 Real& realPart,
339 Real& imagPart,
340 const size_t lineNumber,
341 const bool tolerant)
342 {
343 Real the_realPart, the_imagPart;
344 if (! readRealData (istr, rowIndex, colIndex, the_realPart, lineNumber, tolerant))
345 {
346 if (tolerant)
347 return false;
348 else
349 {
350 std::ostringstream os;
351 os << "Failed to read pattern data and/or real value from line "
352 << lineNumber << " of input";
353 throw std::invalid_argument(os.str());
354 }
355 }
356 if (istr.eof())
357 {
358 if (tolerant)
359 return false;
360 else
361 {
362 std::ostringstream os;
363 os << "No more data after real value on line "
364 << lineNumber << " of input";
365 throw std::invalid_argument(os.str());
366 }
367 }
368 istr >> the_imagPart;
369 if (istr.fail())
370 {
371 if (tolerant)
372 return false;
373 else
374 {
375 std::ostringstream os;
376 os << "Failed to get imaginary value from line "
377 << lineNumber << " of input";
378 throw std::invalid_argument(os.str());
379 }
380 }
381 realPart = the_realPart;
382 imagPart = the_imagPart;
383 return true;
384 }
385#endif // HAVE_TEUCHOS_COMPLEX
386
387 template<class Ordinal>
388 bool
389 readPatternLine (const std::string& line, // only the data-containing part
390 Ordinal& rowIndex,
391 Ordinal& colIndex,
392 const size_t lineNumber,
393 const bool tolerant)
394 {
395 // The part of the line that contains data
396 std::istringstream istr (line);
397 return readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant);
398 }
399
400 template<class Ordinal, class Real>
401 bool
402 readRealLine (const std::string& line,
403 Ordinal& rowIndex,
404 Ordinal& colIndex,
405 Real& realValue,
406 const size_t lineNumber,
407 const bool tolerant)
408 {
409 size_t start, size;
410 if (checkCommentLine (line, start, size, lineNumber, tolerant)) {
411 return false; // It's a comment line
412 }
413 // If it's an empty line, checkCommentLine() will throw an
414 // exception if non-tolerant parsing is being performed, so
415 // we need only return false otherwise.
416 if (size == 0) {
417 if (! tolerant) {
418 throw std::logic_error("Should never get here! checkCommentLine() "
419 "is supposed to catch empty lines.");
420 }
421 else {
422 return false;
423 }
424 }
425 // The part of the line that contains data
426 std::istringstream istr (line.substr (start, size));
427 return readRealData (istr, rowIndex, colIndex, realValue, lineNumber, tolerant);
428 }
429
430#ifdef HAVE_TEUCHOS_COMPLEX
431 template<class Ordinal, class Real>
432 bool
433 readComplexLine (const std::string& line,
434 Ordinal& rowIndex,
435 Ordinal& colIndex,
436 Real& realPart,
437 Real& imagPart,
438 const size_t lineNumber,
439 const bool tolerant)
440 {
441 size_t start, end;
442 if (checkCommentLine (line, start, end, lineNumber, tolerant))
443 return false; // It's a comment line
444 // If it's an empty line, checkCommentLine() will throw an
445 // exception if non-tolerant parsing is being performed, so
446 // we need only return false otherwise.
447 if (end == 0)
448 {
449 if (tolerant)
450 throw std::logic_error("Should never get here! checkCommentLine() "
451 "is supposed to catch empty lines.");
452 else
453 return false;
454 }
455 // The part of the line that contains data
456 std::istringstream istr (line.substr (start, end));
457 // Read the data
458 Real the_realPart, the_imagPart;
459 const bool success =
460 readComplexData (istr, rowIndex, colIndex, the_realPart, the_imagPart,
461 lineNumber, tolerant);
462 if (success)
463 {
464 realPart = the_realPart;
465 imagPart = the_imagPart;
466 }
467 return success;
468 }
469#endif // HAVE_TEUCHOS_COMPLEX
470
471 template<class Ordinal, class PatternCallback>
472 std::pair<bool, std::vector<size_t> >
473 readPatternCoordinateData (std::istream& in,
474 PatternCallback add,
475 const size_t startingLineNumber,
476 const bool tolerant)
477 {
478 std::string line;
479 size_t lineNumber = startingLineNumber;
480 bool anySucceeded = false;
481 bool allSucceeded = true;
482 std::vector<size_t> badLineNumbers;
483 size_t validDataLines = 0;
484 while (getline (in, line)) {
485 size_t start, size;
486 if (checkCommentLine (line, start, size, lineNumber, tolerant)) {
487 continue; // it's a comment line
488 }
489 const std::string theLine = line.substr (start, size);
490
491 Ordinal rowIndex, colIndex;
492 const bool localSuccess =
493 readPatternLine (theLine, rowIndex, colIndex,
494 lineNumber++, tolerant);
495 anySucceeded = anySucceeded || localSuccess;
496 allSucceeded = allSucceeded && localSuccess;
497 if (! localSuccess) {
498 badLineNumbers.push_back (lineNumber);
499 }
500 else {
501 // Add the newly read entry to the sparse graph.
502 add (rowIndex, colIndex);
503 ++validDataLines;
504 }
505 }
506 if (lineNumber == startingLineNumber) {
507 anySucceeded = true; // Trivially true
508 }
509
510 return std::make_pair (allSucceeded, badLineNumbers);
511 }
512
513
514 template<class Ordinal>
515 bool
516 readCoordinateDimensions (std::istream& in,
517 Ordinal& numRows,
518 Ordinal& numCols,
519 Ordinal& numNonzeros,
520 size_t& lineNumber,
521 const bool tolerant)
522 {
523 using std::endl;
524
525 Ordinal the_numRows, the_numCols, the_numNonzeros;
526 std::string line;
527
528 // Keep reading lines from the input stream until we find a
529 // non-comment line, or until we run out of lines. The latter
530 // is an error, since every "coordinate" format Matrix Market
531 // file must have a dimensions line after the banner (even if
532 // the matrix has zero rows or columns, or zero entries).
533 bool commentLine = true;
534 while (commentLine)
535 {
536 // Is it even valid to read from the input stream?
537 if (in.eof () || in.fail ()) {
538 if (tolerant) {
539 return false;
540 }
541 else {
542 std::ostringstream os;
543 os << "Unable to get coordinate dimensions line (at all) "
544 "from (line " << lineNumber << ") of input stream; the "
545 "input stream claims that it is at \"end-of-file\" or has "
546 "an otherwise \"fail\"ed state.";
547 throw std::invalid_argument(os.str());
548 }
549 }
550 // Try to get the next line from the input stream.
551 if (! getline (in, line)) {
552 if (tolerant) {
553 return false;
554 }
555 else {
556 std::ostringstream os;
557 os << "Failed to read coordinate dimensions line (at all) "
558 "from (line " << lineNumber << " from input stream. The "
559 "line should contain the coordinate matrix dimensions in "
560 << " the form \"<numRows> <numCols> <numNonzeros>\".";
561 throw std::invalid_argument(os.str());
562 }
563 }
564 // Is the current line a comment line? Ignore start and
565 // size; they are only useful for reading the actual matrix
566 // entries. (We could use them here as an optimization, but
567 // we've chosen not to.)
568 size_t start = 0, size = 0;
569 commentLine = checkCommentLine (line, start, size,
570 lineNumber, tolerant);
571 // This ensures that any error messages in this file are
572 // correct.
573 if (commentLine) {
574 ++lineNumber;
575 }
576 }
577
578 // The current line is now not a comment line.
579 // Try to read the coordinate dimensions from it.
580 std::istringstream istr (line);
581 if (istr.eof () || istr.fail ()) {
582 if (tolerant) {
583 return false;
584 }
585 else {
586 std::ostringstream os;
587 os << "Unable to read any coordinate dimensions data from line "
588 << lineNumber << " of input stream. Offending line:" << endl
589 << line;
590 throw std::invalid_argument(os.str());
591 }
592 }
593 istr >> the_numRows;
594 if (istr.fail ()) {
595 if (tolerant) {
596 return false;
597 }
598 else {
599 std::ostringstream os;
600 os << "Failed to get number of rows from the coordinate "
601 "dimensions line (line " << lineNumber << " of input stream)."
602 " Offending line:" << endl << line;
603 throw std::invalid_argument(os.str());
604 }
605 }
606 else if (istr.eof ()) {
607 if (tolerant) {
608 return false;
609 }
610 else {
611 std::ostringstream os;
612 os << "No more data after number of rows, in the coordinate "
613 "dimensions line (line " << lineNumber << " of input stream)."
614 " Offending line:" << endl << line;
615 throw std::invalid_argument(os.str());
616 }
617 }
618 istr >> the_numCols;
619 if (istr.fail ()) {
620 if (tolerant) {
621 return false;
622 }
623 else {
624 std::ostringstream os;
625 os << "Failed to get number of columns from the coordinate "
626 "dimensions line (line " << lineNumber << " of input stream)."
627 " Offending line:" << endl << line;
628 throw std::invalid_argument(os.str());
629 }
630 }
631 else if (istr.eof ()) {
632 if (tolerant) {
633 return false;
634 }
635 else {
636 std::ostringstream os;
637 os << "No more data after number of columns, in the coordinate "
638 "dimensions line (line " << lineNumber << " of input stream)."
639 " Offending line:" << endl << line;
640 throw std::invalid_argument (os.str ());
641 }
642 }
643 istr >> the_numNonzeros;
644 if (istr.fail ()) {
645 if (tolerant) {
646 return false;
647 }
648 else {
649 std::ostringstream os;
650 os << "Failed to get number of nonzeros from the coordinate "
651 "dimensions line (line " << lineNumber << " of input stream)."
652 " Offending line:" << endl << line;
653 throw std::invalid_argument (os.str ());
654 }
655 }
656 numRows = the_numRows;
657 numCols = the_numCols;
658 numNonzeros = the_numNonzeros;
659 // This function only increments the line number when it reads a
660 // comment line successfully, or when it reads all the
661 // coordinate dimensions successfully.
662 ++lineNumber;
663 return true;
664 }
665
666 } // namespace MatrixMarket
667} // namespace Teuchos
668
669#endif // __Teuchos_MatrixMarket_generic_hpp
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
#define TEUCHOSNUMERICS_LIB_DLL_EXPORT
Matrix Market file utilities.
bool readCoordinateDimensions(std::istream &in, Ordinal &numRows, Ordinal &numCols, Ordinal &numNonzeros, size_t &lineNumber, const bool tolerant)
bool readPatternData(std::istream &istr, Ordinal &rowIndex, Ordinal &colIndex, const size_t lineNumber, const bool tolerant)
bool checkCommentLine(const std::string &line, size_t &start, size_t &size, const size_t lineNumber, const bool tolerant, const bool maybeBannerLine)
True if the line is a comment line, false otherwise.
std::pair< bool, std::vector< size_t > > readPatternCoordinateData(std::istream &in, PatternCallback add, const size_t startingLineNumber, const bool tolerant)
int maxLineLength()
Maximum line length for a Matrix Market file.
bool readRealLine(const std::string &line, Ordinal &rowIndex, Ordinal &colIndex, Real &realValue, const size_t lineNumber, const bool tolerant)
bool readPatternLine(const std::string &line, Ordinal &rowIndex, Ordinal &colIndex, const size_t lineNumber, const bool tolerant)
bool readRealData(std::istream &istr, Ordinal &rowIndex, Ordinal &colIndex, Real &realValue, const size_t lineNumber, const bool tolerant)