|
Teuchos Package Browser (Single Doxygen Collection)
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_CoordDataReader_hpp 00043 #define __Teuchos_MatrixMarket_CoordDataReader_hpp 00044 00045 #include "Teuchos_MatrixMarket_generic.hpp" 00046 #include "Teuchos_RCP.hpp" 00047 #include "Teuchos_ScalarTraits.hpp" 00048 #include "Teuchos_Tuple.hpp" 00049 00050 00051 namespace Teuchos { 00052 namespace MatrixMarket { 00099 template<class Callback, class Ordinal> 00100 class CoordDataReaderBase { 00101 protected: 00103 Teuchos::RCP<Callback> adder_; 00104 00105 public: 00116 CoordDataReaderBase (const Teuchos::RCP<Callback>& adder) : 00117 adder_ (adder) {} 00118 00126 CoordDataReaderBase () : adder_ (null) {} 00127 00129 virtual ~CoordDataReaderBase () {} 00130 00137 void setAdder (const Teuchos::RCP<Callback>& adder) { 00138 adder_ = adder; 00139 } 00140 00141 protected: 00168 virtual bool 00169 readLine (const std::string& theLine, 00170 const size_t lineNumber, 00171 const bool tolerant) = 0; 00172 00173 public: 00174 00202 virtual std::pair<bool, std::vector<size_t> > 00203 read (std::istream& in, 00204 const size_t startingLineNumber, 00205 const bool tolerant, 00206 const bool debug = false) 00207 { 00208 (void) debug; // silence unused input argument warning 00209 TEUCHOS_TEST_FOR_EXCEPTION(! in, std::invalid_argument, 00210 "Input stream is invalid."); 00211 00212 std::string line; 00213 size_t lineNumber = startingLineNumber; 00214 bool allSucceeded = true; 00215 std::vector<size_t> badLineNumbers; 00216 size_t validDataLines = 0; 00217 while (getline (in, line)) { 00218 size_t start, size; 00219 if (checkCommentLine (line, start, size, lineNumber, tolerant)) { 00220 ++lineNumber; 00221 continue; // it's a comment line 00222 } 00223 const std::string theLine = line.substr (start, size); 00224 00225 const bool localSuccess = readLine (theLine, lineNumber, tolerant); 00226 ++lineNumber; 00227 allSucceeded = allSucceeded && localSuccess; 00228 if (! localSuccess) { 00229 badLineNumbers.push_back (lineNumber); 00230 } 00231 else { 00232 ++validDataLines; 00233 } 00234 } 00235 return std::make_pair (allSucceeded, badLineNumbers); 00236 } 00237 00261 std::pair<Teuchos::Tuple<Ordinal, 3>, bool> 00262 readDimensions (std::istream& in, 00263 size_t& lineNumber, 00264 const bool tolerant = false) 00265 { 00266 Teuchos::Tuple<Ordinal, 3> dims; 00267 // Fill in (numRows, numCols, numNonzeros) with reasonable 00268 // defaults. If we don't succeed in reading all the data 00269 // from the current line of the input stream, the remaining 00270 // values not read will be these default values. 00271 dims[0] = 0; 00272 dims[1] = 0; 00273 dims[2] = 0; 00274 00275 // Keep reading lines from the input stream until we find a 00276 // non-comment line, or until we run out of lines. The latter 00277 // is an error, since every "coordinate" format Matrix Market 00278 // file must have a dimensions line after the banner (even if 00279 // the matrix has zero rows or columns, or zero entries). 00280 std::string line; 00281 bool commentLine = true; 00282 while (commentLine) { 00283 // Is it even valid to read from the input stream? 00284 if (in.eof() || in.fail()) { 00285 if (tolerant) { 00286 return std::make_pair (dims, false); 00287 } 00288 else { 00289 std::ostringstream os; 00290 os << "Unable to get coordinate dimensions line (at all) " 00291 "from (line " << lineNumber << ") of input stream; the " 00292 "input stream claims that it is at \"end-of-file\" or has " 00293 "an otherwise \"fail\"ed state."; 00294 throw std::invalid_argument(os.str()); 00295 } 00296 } 00297 // Try to get the next line from the input stream. 00298 if (getline(in, line)) { 00299 lineNumber++; // We did actually read a line 00300 } 00301 else { 00302 if (tolerant) { 00303 return std::make_pair (dims, false); 00304 } 00305 else { 00306 std::ostringstream os; 00307 os << "Failed to read coordinate dimensions line (at all) " 00308 "from (line " << lineNumber << " from input stream. The " 00309 "line should contain the coordinate matrix dimensions in " 00310 << " the form \"<numRows> <numCols> <numNonzeros>\"."; 00311 throw std::invalid_argument (os.str()); 00312 } 00313 } 00314 // Is the current line a comment line? Ignore start and 00315 // size; they are only useful for reading the actual matrix 00316 // entries. (We could use them here as an optimization, but 00317 // we've chosen not to.) 00318 size_t start = 0, size = 0; 00319 commentLine = checkCommentLine (line, start, size, 00320 lineNumber, tolerant); 00321 } 00322 // 00323 // Read in <numRows> <numCols> <numNonzeros> from input line 00324 // 00325 std::istringstream istr (line); 00326 // Does line contain anything at all? Can we safely read from 00327 // the input stream wrapping the line? 00328 if (istr.eof() || istr.fail()) { 00329 if (tolerant) { 00330 return std::make_pair (dims, false); 00331 } 00332 std::ostringstream os; 00333 os << "Unable to read any data from line " << lineNumber 00334 << " of input; the line should contain the coordinate matrix " 00335 << "dimensions \"<numRows> <numCols> <numNonzeros>\"."; 00336 throw std::invalid_argument(os.str()); 00337 } 00338 // Read in <numRows> 00339 { 00340 Ordinal theNumRows = 0; 00341 istr >> theNumRows; 00342 if (istr.fail()) { 00343 if (tolerant) { 00344 return std::make_pair (dims, false); 00345 } 00346 std::ostringstream os; 00347 os << "Failed to get number of rows from line " << lineNumber 00348 << " of input; the line should contain the coordinate matrix " 00349 << " dimensions \"<numRows> <numCols> <numNonzeros>\"."; 00350 throw std::invalid_argument(os.str()); 00351 } 00352 else { // Capture the validly read result before checking for eof. 00353 dims[0] = theNumRows; 00354 } 00355 } 00356 // There should be two more things to read. 00357 if (istr.eof()) { 00358 if (tolerant) { 00359 return std::make_pair (dims, false); 00360 } 00361 std::ostringstream os; 00362 os << "No more data after number of rows on line " << lineNumber 00363 << " of input; the line should contain the coordinate matrix " 00364 << " dimensions \"<numRows> <numCols> <numNonzeros>\"."; 00365 throw std::invalid_argument(os.str()); 00366 } 00367 // Read in <numCols> 00368 { 00369 Ordinal theNumCols = 0; 00370 istr >> theNumCols; 00371 if (istr.fail()) { 00372 if (tolerant) { 00373 return std::make_pair (dims, false); 00374 } 00375 std::ostringstream os; 00376 os << "Failed to get number of columns from line " << lineNumber 00377 << " of input; the line should contain the coordinate matrix " 00378 << " dimensions \"<numRows> <numCols> <numNonzeros>\"."; 00379 throw std::invalid_argument(os.str()); 00380 } 00381 else { // Capture the validly read result before checking for eof. 00382 dims[1] = theNumCols; 00383 } 00384 } 00385 // There should be one more thing to read. 00386 if (istr.eof()) { 00387 if (tolerant) { 00388 return std::make_pair (dims, false); 00389 } 00390 std::ostringstream os; 00391 os << "No more data after number of columns on line " << lineNumber 00392 << " of input; the line should contain the coordinate matrix " 00393 << " dimensions \"<numRows> <numCols> <numNonzeros>\"."; 00394 throw std::invalid_argument(os.str()); 00395 } 00396 // Read in <numNonzeros> 00397 { 00398 Ordinal theNumNonzeros = 0; 00399 istr >> theNumNonzeros; 00400 if (istr.fail()) { 00401 if (tolerant) { 00402 return std::make_pair (dims, false); 00403 } 00404 std::ostringstream os; 00405 os << "Failed to get number of (structural) nonzeros from line " 00406 << lineNumber 00407 << " of input; the line should contain the coordinate matrix " 00408 << " dimensions \"<numRows> <numCols> <numNonzeros>\"."; 00409 throw std::invalid_argument(os.str()); 00410 } 00411 else { // Capture the validly read result 00412 dims[2] = theNumNonzeros; 00413 } 00414 } 00415 // It would be nice to validate the read-in data further. The 00416 // only thing we can do now is test if it's negative. However, 00417 // we don't know syntactically whether Ordinal is a signed or 00418 // unsigned type, so we shouldn't even test for negativity. 00419 return std::make_pair (dims, true); 00420 } 00421 }; 00422 00457 template<class Callback, 00458 class Ordinal, 00459 class Scalar, 00460 bool isComplex = Teuchos::ScalarTraits<Scalar>::isComplex> 00461 class CoordDataReader : public CoordDataReaderBase<Callback, Ordinal> { 00462 public: 00475 CoordDataReader (const Teuchos::RCP<Callback>& adder); 00476 00484 CoordDataReader (); 00485 00487 virtual ~CoordDataReader(); 00488 00489 protected: 00490 bool 00491 readLine (const std::string& theLine, 00492 const size_t lineNumber, 00493 const bool tolerant); 00494 }; 00495 00496 #ifdef HAVE_TEUCHOS_COMPLEX 00497 // Partial specialization for complex Scalar types. 00498 template<class Callback, class Ordinal, class Scalar> 00499 class CoordDataReader<Callback, Ordinal, Scalar, true> : 00500 public CoordDataReaderBase<Callback, Ordinal> { 00501 public: 00502 CoordDataReader (const Teuchos::RCP<Callback>& adder) : 00503 CoordDataReaderBase<Callback, Ordinal> (adder) 00504 {} 00505 00506 CoordDataReader() : 00507 CoordDataReaderBase<Callback, Ordinal> (null) 00508 {} 00509 00510 virtual ~CoordDataReader() {}; 00511 00512 protected: 00513 bool 00514 readLine (const std::string& theLine, 00515 const size_t lineNumber, 00516 const bool tolerant) 00517 { 00518 typedef Teuchos::ScalarTraits<Scalar> STS; 00519 typedef typename STS::magnitudeType Real; 00520 00521 Ordinal rowIndex; 00522 Ordinal colIndex; 00523 Scalar value; 00524 00525 Real realPart, imagPart; 00526 const bool localSuccess = 00527 readComplexLine (theLine, rowIndex, colIndex, realPart, imagPart, 00528 lineNumber, tolerant); 00529 if (localSuccess) { 00530 // Assume that assignment from std::complex<Real> to Scalar 00531 // (which itself is complex-valued) is valid. We have to do 00532 // this, since the C++ compiler may not be smart enough to 00533 // assume here (when it instantiates the templates) that 00534 // Scalar is an std::complex<Real> -- even though it has to 00535 // be, if STS::isComplex is true (which as of 31 Jan 2011, 00536 // only holds for std::complex<T>). 00537 value = std::complex<Real> (realPart, imagPart); 00538 00539 // Now that we've read in the (i, j, A_ij) triple 00540 // successfully, we can add the entry to the sparse matrix. 00541 (*(this->adder_)) (rowIndex, colIndex, value); 00542 } 00543 return localSuccess; 00544 } 00545 }; 00546 #endif // HAVE_TEUCHOS_COMPLEX 00547 00548 // Partial specialization for real Scalar types. 00549 template<class Callback, class Ordinal, class Scalar> 00550 class CoordDataReader<Callback, Ordinal, Scalar, false> : 00551 public CoordDataReaderBase<Callback, Ordinal> { 00552 public: 00553 CoordDataReader (const Teuchos::RCP<Callback>& adder) : 00554 CoordDataReaderBase<Callback, Ordinal> (adder) 00555 {} 00556 00557 CoordDataReader() : 00558 CoordDataReaderBase<Callback, Ordinal> (null) 00559 {} 00560 00561 virtual ~CoordDataReader() {}; 00562 00563 protected: 00564 bool 00565 readLine (const std::string& theLine, 00566 const size_t lineNumber, 00567 const bool tolerant) 00568 { 00569 Ordinal rowIndex; 00570 Ordinal colIndex; 00571 Scalar value; 00572 const bool localSuccess = readRealLine (theLine, rowIndex, colIndex, 00573 value, lineNumber, tolerant); 00574 if (localSuccess) { 00575 // Now that we've read in the (i, j, A_ij) triple 00576 // successfully, we can add the entry to the sparse matrix. 00577 (*(this->adder_)) (rowIndex, colIndex, value); 00578 } 00579 return localSuccess; 00580 } 00581 }; 00582 00583 00606 template<class Callback, class Ordinal> 00607 class CoordPatternReader : public CoordDataReaderBase<Callback, Ordinal> { 00608 public: 00621 CoordPatternReader (const Teuchos::RCP<Callback>& adder) : 00622 CoordDataReaderBase<Callback, Ordinal> (adder) 00623 {} 00624 00632 CoordPatternReader() : 00633 CoordDataReaderBase<Callback, Ordinal> (null) 00634 {} 00635 00637 virtual ~CoordPatternReader() {}; 00638 00639 protected: 00640 bool 00641 readLine (const std::string& theLine, 00642 const size_t lineNumber, 00643 const bool tolerant) 00644 { 00645 Ordinal rowIndex; 00646 Ordinal colIndex; 00647 const bool localSuccess = 00648 readPatternLine (theLine, rowIndex, colIndex, lineNumber, tolerant); 00649 if (localSuccess) { 00650 // Now that we've read in the (i, j) pair successfully, we 00651 // can add the entry to the sparse graph. 00652 (*(this->adder_)) (rowIndex, colIndex); 00653 } 00654 return localSuccess; 00655 } 00656 }; 00657 00658 } // namespace MatrixMarket 00659 } // namespace Teuchos 00660 00661 #endif // __Teuchos_MatrixMarket_CoordDataReader_hpp
1.7.6.1