|
Tpetra Matrix/Vector Services Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Tpetra: Templated Linear Algebra Services Package 00005 // Copyright (2008) Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // ************************************************************************ 00040 // @HEADER 00041 00042 #ifndef __MatrixMarket_generic_hpp 00043 #define __MatrixMarket_generic_hpp 00044 00045 #include "Tpetra_ConfigDefs.hpp" 00046 #ifdef HAVE_TEUCHOS_COMPLEX 00047 # include <complex> 00048 #endif // HAVE_TEUCHOS_COMPLEX 00049 #include <iostream> 00050 #include <sstream> 00051 #include <stdexcept> 00052 00053 namespace Tpetra { 00054 namespace MatrixMarket { 00055 00061 int maxLineLength(); 00062 00071 bool 00072 checkCommentLine (const std::string& line, 00073 size_t& start, 00074 size_t& size, 00075 const size_t lineNumber, 00076 const bool tolerant); 00077 00111 template<class Ordinal> 00112 bool 00113 readPatternData (std::istream& istr, 00114 Ordinal& rowIndex, 00115 Ordinal& colIndex, 00116 const size_t lineNumber, 00117 const bool tolerant) 00118 { 00119 Ordinal the_rowIndex, the_colIndex; 00120 00121 if (istr.eof() || istr.fail()) 00122 { 00123 if (tolerant) 00124 return false; 00125 else 00126 { 00127 std::ostringstream os; 00128 os << "Unable to read any data from line " << lineNumber << " of input"; 00129 throw std::invalid_argument(os.str()); 00130 } 00131 } 00132 istr >> the_rowIndex; 00133 if (istr.fail()) 00134 { 00135 if (tolerant) 00136 return false; 00137 else 00138 { 00139 std::ostringstream os; 00140 os << "Failed to get row index from line " << lineNumber << " of input"; 00141 throw std::invalid_argument(os.str()); 00142 } 00143 } 00144 else if (istr.eof()) 00145 { 00146 if (tolerant) 00147 return false; 00148 else 00149 { 00150 std::ostringstream os; 00151 os << "No more data after row index on line " << lineNumber << " of input"; 00152 throw std::invalid_argument(os.str()); 00153 } 00154 } 00155 istr >> the_colIndex; 00156 if (istr.fail()) 00157 { 00158 if (tolerant) 00159 return false; 00160 else 00161 { 00162 std::ostringstream os; 00163 os << "Failed to get column index from line " << lineNumber << " of input"; 00164 throw std::invalid_argument(os.str()); 00165 } 00166 } 00167 rowIndex = the_rowIndex; 00168 colIndex = the_colIndex; 00169 return true; 00170 } 00171 00210 template<class Ordinal, class Real> 00211 bool 00212 readRealData (std::istream& istr, 00213 Ordinal& rowIndex, 00214 Ordinal& colIndex, 00215 Real& realValue, 00216 const size_t lineNumber, 00217 const bool tolerant) 00218 { 00219 Real the_realValue; 00220 if (! readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant)) 00221 { 00222 if (tolerant) 00223 return false; 00224 else 00225 { 00226 std::ostringstream os; 00227 os << "Failed to read pattern data from line " << lineNumber << " of input"; 00228 throw std::invalid_argument(os.str()); 00229 } 00230 } 00231 if (istr.eof()) 00232 { 00233 if (tolerant) 00234 return false; 00235 else 00236 { 00237 std::ostringstream os; 00238 os << "No more data after pattern data on line " << lineNumber << " of input"; 00239 throw std::invalid_argument(os.str()); 00240 } 00241 } 00242 istr >> the_realValue; 00243 if (istr.fail()) 00244 { 00245 if (tolerant) 00246 return false; 00247 else 00248 { 00249 std::ostringstream os; 00250 os << "Failed to get real value from line " << lineNumber << " of input"; 00251 throw std::invalid_argument(os.str()); 00252 } 00253 } 00254 realValue = the_realValue; 00255 return true; 00256 } 00257 00258 #ifdef HAVE_TEUCHOS_COMPLEX 00259 00301 template<class Ordinal, class Real> 00302 bool 00303 readComplexData (std::istream& istr, 00304 Ordinal& rowIndex, 00305 Ordinal& colIndex, 00306 Real& realPart, 00307 Real& imagPart, 00308 const size_t lineNumber, 00309 const bool tolerant) 00310 { 00311 Real the_realPart, the_imagPart; 00312 if (! readRealData (istr, rowIndex, colIndex, the_realPart, lineNumber, tolerant)) 00313 { 00314 if (tolerant) 00315 return false; 00316 else 00317 { 00318 std::ostringstream os; 00319 os << "Failed to read pattern data and/or real value from line " 00320 << lineNumber << " of input"; 00321 throw std::invalid_argument(os.str()); 00322 } 00323 } 00324 if (istr.eof()) 00325 { 00326 if (tolerant) 00327 return false; 00328 else 00329 { 00330 std::ostringstream os; 00331 os << "No more data after real value on line " 00332 << lineNumber << " of input"; 00333 throw std::invalid_argument(os.str()); 00334 } 00335 } 00336 istr >> the_imagPart; 00337 if (istr.fail()) 00338 { 00339 if (tolerant) 00340 return false; 00341 else 00342 { 00343 std::ostringstream os; 00344 os << "Failed to get imaginary value from line " 00345 << lineNumber << " of input"; 00346 throw std::invalid_argument(os.str()); 00347 } 00348 } 00349 realPart = the_realPart; 00350 imagPart = the_imagPart; 00351 return true; 00352 } 00353 #endif // HAVE_TEUCHOS_COMPLEX 00354 00355 template<class Ordinal> 00356 bool 00357 readPatternLine (const std::string& line, // only the data-containing part 00358 Ordinal& rowIndex, 00359 Ordinal& colIndex, 00360 const size_t lineNumber, 00361 const bool tolerant) 00362 { 00363 // The part of the line that contains data 00364 std::istringstream istr (line); 00365 return readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant); 00366 } 00367 00368 template<class Ordinal, class Real> 00369 bool 00370 readRealLine (const std::string& line, 00371 Ordinal& rowIndex, 00372 Ordinal& colIndex, 00373 Real& realValue, 00374 const size_t lineNumber, 00375 const bool tolerant) 00376 { 00377 size_t start, size; 00378 if (checkCommentLine (line, start, size, lineNumber, tolerant)) 00379 { 00380 // { 00381 // using std::cerr; 00382 // using std::endl; 00383 // cerr << "Comment line: " << lineNumber << endl; 00384 // } 00385 return false; // It's a comment line 00386 } 00387 // If it's an empty line, checkCommentLine() will throw an 00388 // exception if non-tolerant parsing is being performed, so 00389 // we need only return false otherwise. 00390 if (size == 0) 00391 { 00392 if (! tolerant) 00393 throw std::logic_error("Should never get here! checkCommentLine() " 00394 "is supposed to catch empty lines."); 00395 else 00396 { 00397 // { 00398 // using std::cerr; 00399 // using std::endl; 00400 // cerr << "Empty line: " << lineNumber << endl; 00401 // } 00402 return false; 00403 } 00404 } 00405 // The part of the line that contains data 00406 std::istringstream istr (line.substr (start, size)); 00407 return readRealData (istr, rowIndex, colIndex, realValue, lineNumber, tolerant); 00408 } 00409 00410 #ifdef HAVE_TEUCHOS_COMPLEX 00411 template<class Ordinal, class Real> 00412 bool 00413 readComplexLine (const std::string& line, 00414 Ordinal& rowIndex, 00415 Ordinal& colIndex, 00416 Real& realPart, 00417 Real& imagPart, 00418 const size_t lineNumber, 00419 const bool tolerant) 00420 { 00421 size_t start, end; 00422 if (checkCommentLine (line, start, end, lineNumber, tolerant)) 00423 return false; // It's a comment line 00424 // If it's an empty line, checkCommentLine() will throw an 00425 // exception if non-tolerant parsing is being performed, so 00426 // we need only return false otherwise. 00427 if (end == 0) 00428 { 00429 if (tolerant) 00430 throw std::logic_error("Should never get here! checkCommentLine() " 00431 "is supposed to catch empty lines."); 00432 else 00433 return false; 00434 } 00435 // The part of the line that contains data 00436 std::istringstream istr (line.substr (start, end)); 00437 // Read the data 00438 Real the_realPart, the_imagPart; 00439 const bool success = 00440 readComplexData (istr, rowIndex, colIndex, the_realPart, the_imagPart, 00441 lineNumber, tolerant); 00442 if (success) 00443 { 00444 realPart = the_realPart; 00445 imagPart = the_imagPart; 00446 } 00447 return success; 00448 } 00449 #endif // HAVE_TEUCHOS_COMPLEX 00450 00451 template<class Ordinal, class PatternCallback> 00452 std::pair<bool, std::vector<size_t> > 00453 readPatternCoordinateData (std::istream& in, 00454 PatternCallback add, 00455 const size_t startingLineNumber, 00456 const bool tolerant) 00457 { 00458 std::string line; 00459 size_t lineNumber = startingLineNumber; 00460 bool anySucceeded = false; 00461 bool allSucceeded = true; 00462 std::vector<size_t> badLineNumbers; 00463 size_t validDataLines = 0; 00464 while (getline (in, line)) { 00465 size_t start, size; 00466 if (checkCommentLine (line, start, size, lineNumber, tolerant)) { 00467 continue; // it's a comment line 00468 } 00469 const std::string theLine = line.substr (start, size); 00470 00471 Ordinal rowIndex, colIndex; 00472 const bool localSuccess = 00473 readPatternLine (theLine, rowIndex, colIndex, 00474 lineNumber++, tolerant); 00475 anySucceeded = anySucceeded || localSuccess; 00476 allSucceeded = allSucceeded && localSuccess; 00477 if (! localSuccess) { 00478 badLineNumbers.push_back (lineNumber); 00479 } 00480 else { 00481 // Add the newly read entry to the sparse graph. 00482 add (rowIndex, colIndex); 00483 ++validDataLines; 00484 } 00485 } 00486 if (lineNumber == startingLineNumber) { 00487 anySucceeded = true; // Trivially true 00488 } 00489 00490 return std::make_pair (allSucceeded, badLineNumbers); 00491 } 00492 00493 00494 template<class Ordinal> 00495 bool 00496 readCoordinateDimensions (std::istream& in, 00497 Ordinal& numRows, 00498 Ordinal& numCols, 00499 Ordinal& numNonzeros, 00500 size_t& lineNumber, 00501 const bool tolerant) 00502 { 00503 using std::endl; 00504 00505 Ordinal the_numRows, the_numCols, the_numNonzeros; 00506 std::string line; 00507 00508 // Keep reading lines from the input stream until we find a 00509 // non-comment line, or until we run out of lines. The latter 00510 // is an error, since every "coordinate" format Matrix Market 00511 // file must have a dimensions line after the banner (even if 00512 // the matrix has zero rows or columns, or zero entries). 00513 bool commentLine = true; 00514 while (commentLine) 00515 { 00516 // Is it even valid to read from the input stream? 00517 if (in.eof() || in.fail()) 00518 { 00519 if (tolerant) 00520 return false; 00521 else 00522 { 00523 std::ostringstream os; 00524 os << "Unable to get coordinate dimensions line (at all) " 00525 "from (line " << lineNumber << ") of input stream; the " 00526 "input stream claims that it is at \"end-of-file\" or has " 00527 "an otherwise \"fail\"ed state."; 00528 throw std::invalid_argument(os.str()); 00529 } 00530 } 00531 // Try to get the next line from the input stream. 00532 if (! getline(in, line)) 00533 { 00534 if (tolerant) 00535 return false; 00536 else 00537 { 00538 std::ostringstream os; 00539 os << "Failed to read coordinate dimensions line (at all) " 00540 "from (line " << lineNumber << " from input stream. The " 00541 "line should contain the coordinate matrix dimensions in " 00542 << " the form \"<numRows> <numCols> <numNonzeros>\"."; 00543 throw std::invalid_argument(os.str()); 00544 } 00545 } 00546 // Is the current line a comment line? Ignore start and 00547 // size; they are only useful for reading the actual matrix 00548 // entries. (We could use them here as an optimization, but 00549 // we've chosen not to.) 00550 size_t start = 0, size = 0; 00551 commentLine = checkCommentLine (line, start, size, 00552 lineNumber, tolerant); 00553 // This ensures that any error messages in this file are 00554 // correct. 00555 if (commentLine) 00556 lineNumber++; 00557 } 00558 00559 // The current line is now not a comment line. 00560 // Try to read the coordinate dimensions from it. 00561 std::istringstream istr (line); 00562 if (istr.eof() || istr.fail()) 00563 { 00564 if (tolerant) 00565 return false; 00566 else 00567 { 00568 std::ostringstream os; 00569 os << "Unable to read any coordinate dimensions data from line " 00570 << lineNumber << " of input stream. Offending line:" << endl 00571 << line; 00572 throw std::invalid_argument(os.str()); 00573 } 00574 } 00575 istr >> the_numRows; 00576 if (istr.fail()) 00577 { 00578 if (tolerant) 00579 return false; 00580 else 00581 { 00582 std::ostringstream os; 00583 os << "Failed to get number of rows from the coordinate " 00584 "dimensions line (line " << lineNumber << " of input stream)." 00585 " Offending line:" << endl << line; 00586 throw std::invalid_argument(os.str()); 00587 } 00588 } 00589 else if (istr.eof()) 00590 { 00591 if (tolerant) 00592 return false; 00593 else 00594 { 00595 std::ostringstream os; 00596 os << "No more data after number of rows, in the coordinate " 00597 "dimensions line (line " << lineNumber << " of input stream)." 00598 " Offending line:" << endl << line; 00599 throw std::invalid_argument(os.str()); 00600 } 00601 } 00602 istr >> the_numCols; 00603 if (istr.fail()) 00604 { 00605 if (tolerant) 00606 return false; 00607 else 00608 { 00609 std::ostringstream os; 00610 os << "Failed to get number of columns from the coordinate " 00611 "dimensions line (line " << lineNumber << " of input stream)." 00612 " Offending line:" << endl << line; 00613 throw std::invalid_argument(os.str()); 00614 } 00615 } 00616 else if (istr.eof()) 00617 { 00618 if (tolerant) 00619 return false; 00620 else 00621 { 00622 std::ostringstream os; 00623 os << "No more data after number of columns, in the coordinate " 00624 "dimensions line (line " << lineNumber << " of input stream)." 00625 " Offending line:" << endl << line; 00626 throw std::invalid_argument(os.str()); 00627 } 00628 } 00629 istr >> the_numNonzeros; 00630 if (istr.fail()) 00631 { 00632 if (tolerant) 00633 return false; 00634 else 00635 { 00636 std::ostringstream os; 00637 os << "Failed to get number of nonzeros from the coordinate " 00638 "dimensions line (line " << lineNumber << " of input stream)." 00639 " Offending line:" << endl << line; 00640 throw std::invalid_argument(os.str()); 00641 } 00642 } 00643 numRows = the_numRows; 00644 numCols = the_numCols; 00645 numNonzeros = the_numNonzeros; 00646 // This function only increments the line number when it reads a 00647 // comment line successfully, or when it reads all the 00648 // coordinate dimensions successfully. 00649 lineNumber++; 00650 return true; 00651 } 00652 00653 } // namespace MatrixMarket 00654 } // namespace Tpetra 00655 00656 #endif // __MatrixMarket_generic_hpp
1.7.4