Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Teuchos_MatrixMarket_CoordDataReader.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_CoordDataReader_hpp
43 #define __Teuchos_MatrixMarket_CoordDataReader_hpp
44 
46 #include "Teuchos_RCP.hpp"
47 #include "Teuchos_ScalarTraits.hpp"
48 #include "Teuchos_Tuple.hpp"
49 
50 
51 namespace Teuchos {
52  namespace MatrixMarket {
99  template<class Callback, class Ordinal>
101  protected:
104 
105  public:
117  adder_ (adder) {}
118 
127 
129  virtual ~CoordDataReaderBase () {}
130 
137  void setAdder (const Teuchos::RCP<Callback>& adder) {
138  adder_ = adder;
139  }
140 
141  protected:
168  virtual bool
169  readLine (const std::string& theLine,
170  const size_t lineNumber,
171  const bool tolerant) = 0;
172 
173  public:
174 
202  virtual std::pair<bool, std::vector<size_t> >
203  read (std::istream& in,
204  const size_t startingLineNumber,
205  const bool tolerant,
206  const bool debug = false)
207  {
208  (void) debug; // silence unused input argument warning
209  TEUCHOS_TEST_FOR_EXCEPTION(! in, std::invalid_argument,
210  "Input stream is invalid.");
211 
212  std::string line;
213  size_t lineNumber = startingLineNumber;
214  bool allSucceeded = true;
215  std::vector<size_t> badLineNumbers;
216  size_t validDataLines = 0;
217  while (getline (in, line)) {
218  size_t start, size;
219  if (checkCommentLine (line, start, size, lineNumber, tolerant)) {
220  ++lineNumber;
221  continue; // it's a comment line
222  }
223  const std::string theLine = line.substr (start, size);
224 
225  const bool localSuccess = readLine (theLine, lineNumber, tolerant);
226  ++lineNumber;
227  allSucceeded = allSucceeded && localSuccess;
228  if (! localSuccess) {
229  badLineNumbers.push_back (lineNumber);
230  }
231  else {
232  ++validDataLines;
233  }
234  }
235  return std::make_pair (allSucceeded, badLineNumbers);
236  }
237 
261  std::pair<Teuchos::Tuple<Ordinal, 3>, bool>
262  readDimensions (std::istream& in,
263  size_t& lineNumber,
264  const bool tolerant = false)
265  {
267  // Fill in (numRows, numCols, numNonzeros) with reasonable
268  // defaults. If we don't succeed in reading all the data
269  // from the current line of the input stream, the remaining
270  // values not read will be these default values.
271  dims[0] = 0;
272  dims[1] = 0;
273  dims[2] = 0;
274 
275  // Keep reading lines from the input stream until we find a
276  // non-comment line, or until we run out of lines. The latter
277  // is an error, since every "coordinate" format Matrix Market
278  // file must have a dimensions line after the banner (even if
279  // the matrix has zero rows or columns, or zero entries).
280  std::string line;
281  bool commentLine = true;
282  while (commentLine) {
283  // Is it even valid to read from the input stream?
284  if (in.eof() || in.fail()) {
285  if (tolerant) {
286  return std::make_pair (dims, false);
287  }
288  else {
289  std::ostringstream os;
290  os << "Unable to get coordinate dimensions line (at all) "
291  "from (line " << lineNumber << ") of input stream; the "
292  "input stream claims that it is at \"end-of-file\" or has "
293  "an otherwise \"fail\"ed state.";
294  throw std::invalid_argument(os.str());
295  }
296  }
297  // Try to get the next line from the input stream.
298  if (getline(in, line)) {
299  lineNumber++; // We did actually read a line
300  }
301  else {
302  if (tolerant) {
303  return std::make_pair (dims, false);
304  }
305  else {
306  std::ostringstream os;
307  os << "Failed to read coordinate dimensions line (at all) "
308  "from (line " << lineNumber << " from input stream. The "
309  "line should contain the coordinate matrix dimensions in "
310  << " the form \"<numRows> <numCols> <numNonzeros>\".";
311  throw std::invalid_argument (os.str());
312  }
313  }
314  // Is the current line a comment line? Ignore start and
315  // size; they are only useful for reading the actual matrix
316  // entries. (We could use them here as an optimization, but
317  // we've chosen not to.)
318  size_t start = 0, size = 0;
319  commentLine = checkCommentLine (line, start, size,
320  lineNumber, tolerant);
321  }
322  //
323  // Read in <numRows> <numCols> <numNonzeros> from input line
324  //
325  std::istringstream istr (line);
326  // Does line contain anything at all? Can we safely read from
327  // the input stream wrapping the line?
328  if (istr.eof() || istr.fail()) {
329  if (tolerant) {
330  return std::make_pair (dims, false);
331  }
332  std::ostringstream os;
333  os << "Unable to read any data from line " << lineNumber
334  << " of input; the line should contain the coordinate matrix "
335  << "dimensions \"<numRows> <numCols> <numNonzeros>\".";
336  throw std::invalid_argument(os.str());
337  }
338  // Read in <numRows>
339  {
340  Ordinal theNumRows = 0;
341  istr >> theNumRows;
342  if (istr.fail()) {
343  if (tolerant) {
344  return std::make_pair (dims, false);
345  }
346  std::ostringstream os;
347  os << "Failed to get number of rows from line " << lineNumber
348  << " of input; the line should contain the coordinate matrix "
349  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
350  throw std::invalid_argument(os.str());
351  }
352  else { // Capture the validly read result before checking for eof.
353  dims[0] = theNumRows;
354  }
355  }
356  // There should be two more things to read.
357  if (istr.eof()) {
358  if (tolerant) {
359  return std::make_pair (dims, false);
360  }
361  std::ostringstream os;
362  os << "No more data after number of rows on line " << lineNumber
363  << " of input; the line should contain the coordinate matrix "
364  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
365  throw std::invalid_argument(os.str());
366  }
367  // Read in <numCols>
368  {
369  Ordinal theNumCols = 0;
370  istr >> theNumCols;
371  if (istr.fail()) {
372  if (tolerant) {
373  return std::make_pair (dims, false);
374  }
375  std::ostringstream os;
376  os << "Failed to get number of columns from line " << lineNumber
377  << " of input; the line should contain the coordinate matrix "
378  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
379  throw std::invalid_argument(os.str());
380  }
381  else { // Capture the validly read result before checking for eof.
382  dims[1] = theNumCols;
383  }
384  }
385  // There should be one more thing to read.
386  if (istr.eof()) {
387  if (tolerant) {
388  return std::make_pair (dims, false);
389  }
390  std::ostringstream os;
391  os << "No more data after number of columns on line " << lineNumber
392  << " of input; the line should contain the coordinate matrix "
393  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
394  throw std::invalid_argument(os.str());
395  }
396  // Read in <numNonzeros>
397  {
398  Ordinal theNumNonzeros = 0;
399  istr >> theNumNonzeros;
400  if (istr.fail()) {
401  if (tolerant) {
402  return std::make_pair (dims, false);
403  }
404  std::ostringstream os;
405  os << "Failed to get number of (structural) nonzeros from line "
406  << lineNumber
407  << " of input; the line should contain the coordinate matrix "
408  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
409  throw std::invalid_argument(os.str());
410  }
411  else { // Capture the validly read result
412  dims[2] = theNumNonzeros;
413  }
414  }
415  // It would be nice to validate the read-in data further. The
416  // only thing we can do now is test if it's negative. However,
417  // we don't know syntactically whether Ordinal is a signed or
418  // unsigned type, so we shouldn't even test for negativity.
419  return std::make_pair (dims, true);
420  }
421  };
422 
457  template<class Callback,
458  class Ordinal,
459  class Scalar,
461  class CoordDataReader : public CoordDataReaderBase<Callback, Ordinal> {
462  public:
476 
484  CoordDataReader ();
485 
487  virtual ~CoordDataReader();
488 
489  protected:
490  bool
491  readLine (const std::string& theLine,
492  const size_t lineNumber,
493  const bool tolerant);
494  };
495 
496 #ifdef HAVE_TEUCHOS_COMPLEX
497  // Partial specialization for complex Scalar types.
498  template<class Callback, class Ordinal, class Scalar>
499  class CoordDataReader<Callback, Ordinal, Scalar, true> :
500  public CoordDataReaderBase<Callback, Ordinal> {
501  public:
502  CoordDataReader (const Teuchos::RCP<Callback>& adder) :
503  CoordDataReaderBase<Callback, Ordinal> (adder)
504  {}
505 
506  CoordDataReader() :
507  CoordDataReaderBase<Callback, Ordinal> (null)
508  {}
509 
510  virtual ~CoordDataReader() {};
511 
512  protected:
513  bool
514  readLine (const std::string& theLine,
515  const size_t lineNumber,
516  const bool tolerant)
517  {
518  typedef Teuchos::ScalarTraits<Scalar> STS;
519  typedef typename STS::magnitudeType Real;
520 
521  Ordinal rowIndex;
522  Ordinal colIndex;
523  Scalar value;
524 
525  Real realPart, imagPart;
526  const bool localSuccess =
527  readComplexLine (theLine, rowIndex, colIndex, realPart, imagPart,
528  lineNumber, tolerant);
529  if (localSuccess) {
530  // Assume that assignment from std::complex<Real> to Scalar
531  // (which itself is complex-valued) is valid. We have to do
532  // this, since the C++ compiler may not be smart enough to
533  // assume here (when it instantiates the templates) that
534  // Scalar is an std::complex<Real> -- even though it has to
535  // be, if STS::isComplex is true (which as of 31 Jan 2011,
536  // only holds for std::complex<T>).
537  value = std::complex<Real> (realPart, imagPart);
538 
539  // Now that we've read in the (i, j, A_ij) triple
540  // successfully, we can add the entry to the sparse matrix.
541  (*(this->adder_)) (rowIndex, colIndex, value);
542  }
543  return localSuccess;
544  }
545  };
546 #endif // HAVE_TEUCHOS_COMPLEX
547 
548  // Partial specialization for real Scalar types.
549  template<class Callback, class Ordinal, class Scalar>
550  class CoordDataReader<Callback, Ordinal, Scalar, false> :
551  public CoordDataReaderBase<Callback, Ordinal> {
552  public:
554  CoordDataReaderBase<Callback, Ordinal> (adder)
555  {}
556 
558  CoordDataReaderBase<Callback, Ordinal> (null)
559  {}
560 
561  virtual ~CoordDataReader() {};
562 
563  protected:
564  bool
565  readLine (const std::string& theLine,
566  const size_t lineNumber,
567  const bool tolerant)
568  {
569  Ordinal rowIndex;
570  Ordinal colIndex;
571  Scalar value;
572  const bool localSuccess = readRealLine (theLine, rowIndex, colIndex,
573  value, lineNumber, tolerant);
574  if (localSuccess) {
575  // Now that we've read in the (i, j, A_ij) triple
576  // successfully, we can add the entry to the sparse matrix.
577  (*(this->adder_)) (rowIndex, colIndex, value);
578  }
579  return localSuccess;
580  }
581  };
582 
583 
606  template<class Callback, class Ordinal>
607  class CoordPatternReader : public CoordDataReaderBase<Callback, Ordinal> {
608  public:
622  CoordDataReaderBase<Callback, Ordinal> (adder)
623  {}
624 
633  CoordDataReaderBase<Callback, Ordinal> (null)
634  {}
635 
637  virtual ~CoordPatternReader() {};
638 
639  protected:
640  bool
641  readLine (const std::string& theLine,
642  const size_t lineNumber,
643  const bool tolerant)
644  {
645  Ordinal rowIndex;
646  Ordinal colIndex;
647  const bool localSuccess =
648  readPatternLine (theLine, rowIndex, colIndex, lineNumber, tolerant);
649  if (localSuccess) {
650  // Now that we've read in the (i, j) pair successfully, we
651  // can add the entry to the sparse graph.
652  (*(this->adder_)) (rowIndex, colIndex);
653  }
654  return localSuccess;
655  }
656  };
657 
658  } // namespace MatrixMarket
659 } // namespace Teuchos
660 
661 #endif // __Teuchos_MatrixMarket_CoordDataReader_hpp
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.
virtual std::pair< bool, std::vector< size_t > > read(std::istream &in, const size_t startingLineNumber, const bool tolerant, const bool debug=false)
Read in all the data from the given input stream.
CoordDataReader()
No-argument constructor.
bool readLine(const std::string &theLine, const size_t lineNumber, const bool tolerant)
Read in the data from a single line of the input stream.
std::pair< Teuchos::Tuple< Ordinal, 3 >, bool > readDimensions(std::istream &in, size_t &lineNumber, const bool tolerant=false)
Read (numRows, numCols, numNonzeros).
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
virtual ~CoordPatternReader()
Virtual destructor for safety and happy compilers.
CoordDataReaderBase(const Teuchos::RCP< Callback > &adder)
Constructor with &quot;adder&quot; argument.
Coordinate-format sparse matrix data reader.
This structure defines some basic traits for a scalar field type.
Statically sized simple array (tuple) class.
bool readLine(const std::string &theLine, const size_t lineNumber, const bool tolerant)
Read in the data from a single line of the input stream.
CoordPatternReader(const Teuchos::RCP< Callback > &adder)
Constructor with &quot;adder&quot; argument.
bool readPatternLine(const std::string &line, Ordinal &rowIndex, Ordinal &colIndex, const size_t lineNumber, const bool tolerant)
bool readLine(const std::string &theLine, const size_t lineNumber, const bool tolerant)
Read in the data from a single line of the input stream.
virtual bool readLine(const std::string &theLine, const size_t lineNumber, const bool tolerant)=0
Read in the data from a single line of the input stream.
bool readRealLine(const std::string &line, Ordinal &rowIndex, Ordinal &colIndex, Real &realValue, const size_t lineNumber, const bool tolerant)
virtual ~CoordDataReader()
Virtual destructor for safety and happy compilers.
void setAdder(const Teuchos::RCP< Callback > &adder)
Set the Adder object.
Defines basic traits for the scalar field type.
Teuchos::RCP< Callback > adder_
Closure that knows how to add entries to the sparse graph or matrix.
Common functionality of a coordinate-format sparse matrix or graph data reader.
virtual ~CoordDataReaderBase()
Virtual destructor for safety and happy compilers.
Reference-counted pointer class and non-member templated function implementations.