|
Teuchos - Trilinos Tools Package
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 __Teuchos_MatrixMarket_generic_hpp 00043 #define __Teuchos_MatrixMarket_generic_hpp 00044 00045 #include "Teuchos_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 00054 namespace Teuchos { 00055 namespace MatrixMarket { 00056 00062 int maxLineLength(); 00063 00092 TEUCHOSNUMERICS_LIB_DLL_EXPORT bool 00093 checkCommentLine (const std::string& line, 00094 size_t& start, 00095 size_t& size, 00096 const size_t lineNumber, 00097 const bool tolerant, 00098 const bool maybeBannerLine = false); 00099 00133 template<class Ordinal> 00134 bool 00135 readPatternData (std::istream& istr, 00136 Ordinal& rowIndex, 00137 Ordinal& colIndex, 00138 const size_t lineNumber, 00139 const bool tolerant) 00140 { 00141 Ordinal the_rowIndex, the_colIndex; 00142 00143 if (istr.eof() || istr.fail()) 00144 { 00145 if (tolerant) 00146 return false; 00147 else 00148 { 00149 std::ostringstream os; 00150 os << "Unable to read any data from line " << lineNumber << " of input"; 00151 throw std::invalid_argument(os.str()); 00152 } 00153 } 00154 istr >> the_rowIndex; 00155 if (istr.fail()) 00156 { 00157 if (tolerant) 00158 return false; 00159 else 00160 { 00161 std::ostringstream os; 00162 os << "Failed to get row index from line " << lineNumber << " of input"; 00163 throw std::invalid_argument(os.str()); 00164 } 00165 } 00166 else if (istr.eof()) 00167 { 00168 if (tolerant) 00169 return false; 00170 else 00171 { 00172 std::ostringstream os; 00173 os << "No more data after row index on line " << lineNumber << " of input"; 00174 throw std::invalid_argument(os.str()); 00175 } 00176 } 00177 istr >> the_colIndex; 00178 if (istr.fail()) 00179 { 00180 if (tolerant) 00181 return false; 00182 else 00183 { 00184 std::ostringstream os; 00185 os << "Failed to get column index from line " << lineNumber << " of input"; 00186 throw std::invalid_argument(os.str()); 00187 } 00188 } 00189 rowIndex = the_rowIndex; 00190 colIndex = the_colIndex; 00191 return true; 00192 } 00193 00232 template<class Ordinal, class Real> 00233 bool 00234 readRealData (std::istream& istr, 00235 Ordinal& rowIndex, 00236 Ordinal& colIndex, 00237 Real& realValue, 00238 const size_t lineNumber, 00239 const bool tolerant) 00240 { 00241 Real the_realValue; 00242 if (! readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant)) 00243 { 00244 if (tolerant) 00245 return false; 00246 else 00247 { 00248 std::ostringstream os; 00249 os << "Failed to read pattern data from line " << lineNumber << " of input"; 00250 throw std::invalid_argument(os.str()); 00251 } 00252 } 00253 if (istr.eof()) 00254 { 00255 if (tolerant) 00256 return false; 00257 else 00258 { 00259 std::ostringstream os; 00260 os << "No more data after pattern data on line " << lineNumber << " of input"; 00261 throw std::invalid_argument(os.str()); 00262 } 00263 } 00264 istr >> the_realValue; 00265 if (istr.fail()) 00266 { 00267 if (tolerant) 00268 return false; 00269 else 00270 { 00271 std::ostringstream os; 00272 os << "Failed to get real value from line " << lineNumber << " of input"; 00273 throw std::invalid_argument(os.str()); 00274 } 00275 } 00276 realValue = the_realValue; 00277 return true; 00278 } 00279 00280 #ifdef HAVE_TEUCHOS_COMPLEX 00281 00323 template<class Ordinal, class Real> 00324 bool 00325 readComplexData (std::istream& istr, 00326 Ordinal& rowIndex, 00327 Ordinal& colIndex, 00328 Real& realPart, 00329 Real& imagPart, 00330 const size_t lineNumber, 00331 const bool tolerant) 00332 { 00333 Real the_realPart, the_imagPart; 00334 if (! readRealData (istr, rowIndex, colIndex, the_realPart, lineNumber, tolerant)) 00335 { 00336 if (tolerant) 00337 return false; 00338 else 00339 { 00340 std::ostringstream os; 00341 os << "Failed to read pattern data and/or real value from line " 00342 << lineNumber << " of input"; 00343 throw std::invalid_argument(os.str()); 00344 } 00345 } 00346 if (istr.eof()) 00347 { 00348 if (tolerant) 00349 return false; 00350 else 00351 { 00352 std::ostringstream os; 00353 os << "No more data after real value on line " 00354 << lineNumber << " of input"; 00355 throw std::invalid_argument(os.str()); 00356 } 00357 } 00358 istr >> the_imagPart; 00359 if (istr.fail()) 00360 { 00361 if (tolerant) 00362 return false; 00363 else 00364 { 00365 std::ostringstream os; 00366 os << "Failed to get imaginary value from line " 00367 << lineNumber << " of input"; 00368 throw std::invalid_argument(os.str()); 00369 } 00370 } 00371 realPart = the_realPart; 00372 imagPart = the_imagPart; 00373 return true; 00374 } 00375 #endif // HAVE_TEUCHOS_COMPLEX 00376 00377 template<class Ordinal> 00378 bool 00379 readPatternLine (const std::string& line, // only the data-containing part 00380 Ordinal& rowIndex, 00381 Ordinal& colIndex, 00382 const size_t lineNumber, 00383 const bool tolerant) 00384 { 00385 // The part of the line that contains data 00386 std::istringstream istr (line); 00387 return readPatternData (istr, rowIndex, colIndex, lineNumber, tolerant); 00388 } 00389 00390 template<class Ordinal, class Real> 00391 bool 00392 readRealLine (const std::string& line, 00393 Ordinal& rowIndex, 00394 Ordinal& colIndex, 00395 Real& realValue, 00396 const size_t lineNumber, 00397 const bool tolerant) 00398 { 00399 size_t start, size; 00400 if (checkCommentLine (line, start, size, lineNumber, tolerant)) { 00401 return false; // It's a comment line 00402 } 00403 // If it's an empty line, checkCommentLine() will throw an 00404 // exception if non-tolerant parsing is being performed, so 00405 // we need only return false otherwise. 00406 if (size == 0) { 00407 if (! tolerant) { 00408 throw std::logic_error("Should never get here! checkCommentLine() " 00409 "is supposed to catch empty lines."); 00410 } 00411 else { 00412 return false; 00413 } 00414 } 00415 // The part of the line that contains data 00416 std::istringstream istr (line.substr (start, size)); 00417 return readRealData (istr, rowIndex, colIndex, realValue, lineNumber, tolerant); 00418 } 00419 00420 #ifdef HAVE_TEUCHOS_COMPLEX 00421 template<class Ordinal, class Real> 00422 bool 00423 readComplexLine (const std::string& line, 00424 Ordinal& rowIndex, 00425 Ordinal& colIndex, 00426 Real& realPart, 00427 Real& imagPart, 00428 const size_t lineNumber, 00429 const bool tolerant) 00430 { 00431 size_t start, end; 00432 if (checkCommentLine (line, start, end, lineNumber, tolerant)) 00433 return false; // It's a comment line 00434 // If it's an empty line, checkCommentLine() will throw an 00435 // exception if non-tolerant parsing is being performed, so 00436 // we need only return false otherwise. 00437 if (end == 0) 00438 { 00439 if (tolerant) 00440 throw std::logic_error("Should never get here! checkCommentLine() " 00441 "is supposed to catch empty lines."); 00442 else 00443 return false; 00444 } 00445 // The part of the line that contains data 00446 std::istringstream istr (line.substr (start, end)); 00447 // Read the data 00448 Real the_realPart, the_imagPart; 00449 const bool success = 00450 readComplexData (istr, rowIndex, colIndex, the_realPart, the_imagPart, 00451 lineNumber, tolerant); 00452 if (success) 00453 { 00454 realPart = the_realPart; 00455 imagPart = the_imagPart; 00456 } 00457 return success; 00458 } 00459 #endif // HAVE_TEUCHOS_COMPLEX 00460 00461 template<class Ordinal, class PatternCallback> 00462 std::pair<bool, std::vector<size_t> > 00463 readPatternCoordinateData (std::istream& in, 00464 PatternCallback add, 00465 const size_t startingLineNumber, 00466 const bool tolerant) 00467 { 00468 std::string line; 00469 size_t lineNumber = startingLineNumber; 00470 bool anySucceeded = false; 00471 bool allSucceeded = true; 00472 std::vector<size_t> badLineNumbers; 00473 size_t validDataLines = 0; 00474 while (getline (in, line)) { 00475 size_t start, size; 00476 if (checkCommentLine (line, start, size, lineNumber, tolerant)) { 00477 continue; // it's a comment line 00478 } 00479 const std::string theLine = line.substr (start, size); 00480 00481 Ordinal rowIndex, colIndex; 00482 const bool localSuccess = 00483 readPatternLine (theLine, rowIndex, colIndex, 00484 lineNumber++, tolerant); 00485 anySucceeded = anySucceeded || localSuccess; 00486 allSucceeded = allSucceeded && localSuccess; 00487 if (! localSuccess) { 00488 badLineNumbers.push_back (lineNumber); 00489 } 00490 else { 00491 // Add the newly read entry to the sparse graph. 00492 add (rowIndex, colIndex); 00493 ++validDataLines; 00494 } 00495 } 00496 if (lineNumber == startingLineNumber) { 00497 anySucceeded = true; // Trivially true 00498 } 00499 00500 return std::make_pair (allSucceeded, badLineNumbers); 00501 } 00502 00503 00504 template<class Ordinal> 00505 bool 00506 readCoordinateDimensions (std::istream& in, 00507 Ordinal& numRows, 00508 Ordinal& numCols, 00509 Ordinal& numNonzeros, 00510 size_t& lineNumber, 00511 const bool tolerant) 00512 { 00513 using std::endl; 00514 00515 Ordinal the_numRows, the_numCols, the_numNonzeros; 00516 std::string line; 00517 00518 // Keep reading lines from the input stream until we find a 00519 // non-comment line, or until we run out of lines. The latter 00520 // is an error, since every "coordinate" format Matrix Market 00521 // file must have a dimensions line after the banner (even if 00522 // the matrix has zero rows or columns, or zero entries). 00523 bool commentLine = true; 00524 while (commentLine) 00525 { 00526 // Is it even valid to read from the input stream? 00527 if (in.eof () || in.fail ()) { 00528 if (tolerant) { 00529 return false; 00530 } 00531 else { 00532 std::ostringstream os; 00533 os << "Unable to get coordinate dimensions line (at all) " 00534 "from (line " << lineNumber << ") of input stream; the " 00535 "input stream claims that it is at \"end-of-file\" or has " 00536 "an otherwise \"fail\"ed state."; 00537 throw std::invalid_argument(os.str()); 00538 } 00539 } 00540 // Try to get the next line from the input stream. 00541 if (! getline (in, line)) { 00542 if (tolerant) { 00543 return false; 00544 } 00545 else { 00546 std::ostringstream os; 00547 os << "Failed to read coordinate dimensions line (at all) " 00548 "from (line " << lineNumber << " from input stream. The " 00549 "line should contain the coordinate matrix dimensions in " 00550 << " the form \"<numRows> <numCols> <numNonzeros>\"."; 00551 throw std::invalid_argument(os.str()); 00552 } 00553 } 00554 // Is the current line a comment line? Ignore start and 00555 // size; they are only useful for reading the actual matrix 00556 // entries. (We could use them here as an optimization, but 00557 // we've chosen not to.) 00558 size_t start = 0, size = 0; 00559 commentLine = checkCommentLine (line, start, size, 00560 lineNumber, tolerant); 00561 // This ensures that any error messages in this file are 00562 // correct. 00563 if (commentLine) { 00564 ++lineNumber; 00565 } 00566 } 00567 00568 // The current line is now not a comment line. 00569 // Try to read the coordinate dimensions from it. 00570 std::istringstream istr (line); 00571 if (istr.eof () || istr.fail ()) { 00572 if (tolerant) { 00573 return false; 00574 } 00575 else { 00576 std::ostringstream os; 00577 os << "Unable to read any coordinate dimensions data from line " 00578 << lineNumber << " of input stream. Offending line:" << endl 00579 << line; 00580 throw std::invalid_argument(os.str()); 00581 } 00582 } 00583 istr >> the_numRows; 00584 if (istr.fail ()) { 00585 if (tolerant) { 00586 return false; 00587 } 00588 else { 00589 std::ostringstream os; 00590 os << "Failed to get number of rows from the coordinate " 00591 "dimensions line (line " << lineNumber << " of input stream)." 00592 " Offending line:" << endl << line; 00593 throw std::invalid_argument(os.str()); 00594 } 00595 } 00596 else if (istr.eof ()) { 00597 if (tolerant) { 00598 return false; 00599 } 00600 else { 00601 std::ostringstream os; 00602 os << "No more data after number of rows, in the coordinate " 00603 "dimensions line (line " << lineNumber << " of input stream)." 00604 " Offending line:" << endl << line; 00605 throw std::invalid_argument(os.str()); 00606 } 00607 } 00608 istr >> the_numCols; 00609 if (istr.fail ()) { 00610 if (tolerant) { 00611 return false; 00612 } 00613 else { 00614 std::ostringstream os; 00615 os << "Failed to get number of columns from the coordinate " 00616 "dimensions line (line " << lineNumber << " of input stream)." 00617 " Offending line:" << endl << line; 00618 throw std::invalid_argument(os.str()); 00619 } 00620 } 00621 else if (istr.eof ()) { 00622 if (tolerant) { 00623 return false; 00624 } 00625 else { 00626 std::ostringstream os; 00627 os << "No more data after number of columns, in the coordinate " 00628 "dimensions line (line " << lineNumber << " of input stream)." 00629 " Offending line:" << endl << line; 00630 throw std::invalid_argument (os.str ()); 00631 } 00632 } 00633 istr >> the_numNonzeros; 00634 if (istr.fail ()) { 00635 if (tolerant) { 00636 return false; 00637 } 00638 else { 00639 std::ostringstream os; 00640 os << "Failed to get number of nonzeros from the coordinate " 00641 "dimensions line (line " << lineNumber << " of input stream)." 00642 " Offending line:" << endl << line; 00643 throw std::invalid_argument (os.str ()); 00644 } 00645 } 00646 numRows = the_numRows; 00647 numCols = the_numCols; 00648 numNonzeros = the_numNonzeros; 00649 // This function only increments the line number when it reads a 00650 // comment line successfully, or when it reads all the 00651 // coordinate dimensions successfully. 00652 ++lineNumber; 00653 return true; 00654 } 00655 00656 } // namespace MatrixMarket 00657 } // namespace Teuchos 00658 00659 #endif // __Teuchos_MatrixMarket_generic_hpp
1.7.6.1