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  while (getline (in, line)) {
217  size_t start, size;
218  if (checkCommentLine (line, start, size, lineNumber, tolerant)) {
219  ++lineNumber;
220  continue; // it's a comment line
221  }
222  const std::string theLine = line.substr (start, size);
223 
224  const bool localSuccess = readLine (theLine, lineNumber, tolerant);
225  ++lineNumber;
226  allSucceeded = allSucceeded && localSuccess;
227  if (! localSuccess) {
228  badLineNumbers.push_back (lineNumber);
229  }
230  }
231  return std::make_pair (allSucceeded, badLineNumbers);
232  }
233 
257  std::pair<Teuchos::Tuple<Ordinal, 3>, bool>
258  readDimensions (std::istream& in,
259  size_t& lineNumber,
260  const bool tolerant = false)
261  {
263  // Fill in (numRows, numCols, numNonzeros) with reasonable
264  // defaults. If we don't succeed in reading all the data
265  // from the current line of the input stream, the remaining
266  // values not read will be these default values.
267  dims[0] = 0;
268  dims[1] = 0;
269  dims[2] = 0;
270 
271  // Keep reading lines from the input stream until we find a
272  // non-comment line, or until we run out of lines. The latter
273  // is an error, since every "coordinate" format Matrix Market
274  // file must have a dimensions line after the banner (even if
275  // the matrix has zero rows or columns, or zero entries).
276  std::string line;
277  bool commentLine = true;
278  while (commentLine) {
279  // Is it even valid to read from the input stream?
280  if (in.eof() || in.fail()) {
281  if (tolerant) {
282  return std::make_pair (dims, false);
283  }
284  else {
285  std::ostringstream os;
286  os << "Unable to get coordinate dimensions line (at all) "
287  "from (line " << lineNumber << ") of input stream; the "
288  "input stream claims that it is at \"end-of-file\" or has "
289  "an otherwise \"fail\"ed state.";
290  throw std::invalid_argument(os.str());
291  }
292  }
293  // Try to get the next line from the input stream.
294  if (getline(in, line)) {
295  lineNumber++; // We did actually read a line
296  }
297  else {
298  if (tolerant) {
299  return std::make_pair (dims, false);
300  }
301  else {
302  std::ostringstream os;
303  os << "Failed to read coordinate dimensions line (at all) "
304  "from (line " << lineNumber << " from input stream. The "
305  "line should contain the coordinate matrix dimensions in "
306  << " the form \"<numRows> <numCols> <numNonzeros>\".";
307  throw std::invalid_argument (os.str());
308  }
309  }
310  // Is the current line a comment line? Ignore start and
311  // size; they are only useful for reading the actual matrix
312  // entries. (We could use them here as an optimization, but
313  // we've chosen not to.)
314  size_t start = 0, size = 0;
315  commentLine = checkCommentLine (line, start, size,
316  lineNumber, tolerant);
317  }
318  //
319  // Read in <numRows> <numCols> <numNonzeros> from input line
320  //
321  std::istringstream istr (line);
322  // Does line contain anything at all? Can we safely read from
323  // the input stream wrapping the line?
324  if (istr.eof() || istr.fail()) {
325  if (tolerant) {
326  return std::make_pair (dims, false);
327  }
328  std::ostringstream os;
329  os << "Unable to read any data from line " << lineNumber
330  << " of input; the line should contain the coordinate matrix "
331  << "dimensions \"<numRows> <numCols> <numNonzeros>\".";
332  throw std::invalid_argument(os.str());
333  }
334  // Read in <numRows>
335  {
336  Ordinal theNumRows = 0;
337  istr >> theNumRows;
338  if (istr.fail()) {
339  if (tolerant) {
340  return std::make_pair (dims, false);
341  }
342  std::ostringstream os;
343  os << "Failed to get number of rows from line " << lineNumber
344  << " of input; the line should contain the coordinate matrix "
345  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
346  throw std::invalid_argument(os.str());
347  }
348  else { // Capture the validly read result before checking for eof.
349  dims[0] = theNumRows;
350  }
351  }
352  // There should be two more things to read.
353  if (istr.eof()) {
354  if (tolerant) {
355  return std::make_pair (dims, false);
356  }
357  std::ostringstream os;
358  os << "No more data after number of rows on line " << lineNumber
359  << " of input; the line should contain the coordinate matrix "
360  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
361  throw std::invalid_argument(os.str());
362  }
363  // Read in <numCols>
364  {
365  Ordinal theNumCols = 0;
366  istr >> theNumCols;
367  if (istr.fail()) {
368  if (tolerant) {
369  return std::make_pair (dims, false);
370  }
371  std::ostringstream os;
372  os << "Failed to get number of columns from line " << lineNumber
373  << " of input; the line should contain the coordinate matrix "
374  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
375  throw std::invalid_argument(os.str());
376  }
377  else { // Capture the validly read result before checking for eof.
378  dims[1] = theNumCols;
379  }
380  }
381  // There should be one more thing to read.
382  if (istr.eof()) {
383  if (tolerant) {
384  return std::make_pair (dims, false);
385  }
386  std::ostringstream os;
387  os << "No more data after number of columns on line " << lineNumber
388  << " of input; the line should contain the coordinate matrix "
389  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
390  throw std::invalid_argument(os.str());
391  }
392  // Read in <numNonzeros>
393  {
394  Ordinal theNumNonzeros = 0;
395  istr >> theNumNonzeros;
396  if (istr.fail()) {
397  if (tolerant) {
398  return std::make_pair (dims, false);
399  }
400  std::ostringstream os;
401  os << "Failed to get number of (structural) nonzeros from line "
402  << lineNumber
403  << " of input; the line should contain the coordinate matrix "
404  << " dimensions \"<numRows> <numCols> <numNonzeros>\".";
405  throw std::invalid_argument(os.str());
406  }
407  else { // Capture the validly read result
408  dims[2] = theNumNonzeros;
409  }
410  }
411  // It would be nice to validate the read-in data further. The
412  // only thing we can do now is test if it's negative. However,
413  // we don't know syntactically whether Ordinal is a signed or
414  // unsigned type, so we shouldn't even test for negativity.
415  return std::make_pair (dims, true);
416  }
417  };
418 
453  template<class Callback,
454  class Ordinal,
455  class Scalar,
457  class CoordDataReader : public CoordDataReaderBase<Callback, Ordinal> {
458  public:
472 
480  CoordDataReader ();
481 
483  virtual ~CoordDataReader();
484 
485  protected:
486  bool
487  readLine (const std::string& theLine,
488  const size_t lineNumber,
489  const bool tolerant);
490  };
491 
492 #ifdef HAVE_TEUCHOS_COMPLEX
493  // Partial specialization for complex Scalar types.
494  template<class Callback, class Ordinal, class Scalar>
495  class CoordDataReader<Callback, Ordinal, Scalar, true> :
496  public CoordDataReaderBase<Callback, Ordinal> {
497  public:
498  CoordDataReader (const Teuchos::RCP<Callback>& adder) :
499  CoordDataReaderBase<Callback, Ordinal> (adder)
500  {}
501 
502  CoordDataReader() :
503  CoordDataReaderBase<Callback, Ordinal> (null)
504  {}
505 
506  virtual ~CoordDataReader() {};
507 
508  protected:
509  bool
510  readLine (const std::string& theLine,
511  const size_t lineNumber,
512  const bool tolerant)
513  {
514  typedef Teuchos::ScalarTraits<Scalar> STS;
515  typedef typename STS::magnitudeType Real;
516 
517  Ordinal rowIndex;
518  Ordinal colIndex;
519  Scalar value;
520 
521  Real realPart, imagPart;
522  const bool localSuccess =
523  readComplexLine (theLine, rowIndex, colIndex, realPart, imagPart,
524  lineNumber, tolerant);
525  if (localSuccess) {
526  // Assume that assignment from std::complex<Real> to Scalar
527  // (which itself is complex-valued) is valid. We have to do
528  // this, since the C++ compiler may not be smart enough to
529  // assume here (when it instantiates the templates) that
530  // Scalar is an std::complex<Real> -- even though it has to
531  // be, if STS::isComplex is true (which as of 31 Jan 2011,
532  // only holds for std::complex<T>).
533  value = std::complex<Real> (realPart, imagPart);
534 
535  // Now that we've read in the (i, j, A_ij) triple
536  // successfully, we can add the entry to the sparse matrix.
537  (*(this->adder_)) (rowIndex, colIndex, value);
538  }
539  return localSuccess;
540  }
541  };
542 #endif // HAVE_TEUCHOS_COMPLEX
543 
544  // Partial specialization for real Scalar types.
545  template<class Callback, class Ordinal, class Scalar>
546  class CoordDataReader<Callback, Ordinal, Scalar, false> :
547  public CoordDataReaderBase<Callback, Ordinal> {
548  public:
550  CoordDataReaderBase<Callback, Ordinal> (adder)
551  {}
552 
554  CoordDataReaderBase<Callback, Ordinal> (null)
555  {}
556 
557  virtual ~CoordDataReader() {};
558 
559  protected:
560  bool
561  readLine (const std::string& theLine,
562  const size_t lineNumber,
563  const bool tolerant)
564  {
565  Ordinal rowIndex;
566  Ordinal colIndex;
567  Scalar value;
568  const bool localSuccess = readRealLine (theLine, rowIndex, colIndex,
569  value, lineNumber, tolerant);
570  if (localSuccess) {
571  // Now that we've read in the (i, j, A_ij) triple
572  // successfully, we can add the entry to the sparse matrix.
573  (*(this->adder_)) (rowIndex, colIndex, value);
574  }
575  return localSuccess;
576  }
577  };
578 
579 
602  template<class Callback, class Ordinal>
603  class CoordPatternReader : public CoordDataReaderBase<Callback, Ordinal> {
604  public:
618  CoordDataReaderBase<Callback, Ordinal> (adder)
619  {}
620 
629  CoordDataReaderBase<Callback, Ordinal> (null)
630  {}
631 
633  virtual ~CoordPatternReader() {};
634 
635  protected:
636  bool
637  readLine (const std::string& theLine,
638  const size_t lineNumber,
639  const bool tolerant)
640  {
641  Ordinal rowIndex;
642  Ordinal colIndex;
643  const bool localSuccess =
644  readPatternLine (theLine, rowIndex, colIndex, lineNumber, tolerant);
645  if (localSuccess) {
646  // Now that we've read in the (i, j) pair successfully, we
647  // can add the entry to the sparse graph.
648  (*(this->adder_)) (rowIndex, colIndex);
649  }
650  return localSuccess;
651  }
652  };
653 
654  } // namespace MatrixMarket
655 } // namespace Teuchos
656 
657 #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.