|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Teuchos: Common Tools Package 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 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 #include <Teuchos_MatrixMarket_Raw_Checker.hpp> 00043 #include <Teuchos_MatrixMarket_Raw_Reader.hpp> 00044 #include <Teuchos_MatrixMarket_SetScientific.hpp> 00045 #include <Teuchos_CommandLineProcessor.hpp> 00046 #include <Teuchos_GlobalMPISession.hpp> 00047 #include <Teuchos_oblackholestream.hpp> 00048 #include <Teuchos_DefaultSerialComm.hpp> 00049 #include <algorithm> 00050 00051 using std::endl; 00052 00053 namespace { 00054 // Sample Matrix Market sparse matrix file. We include this so we 00055 // can test without needing to read in a file. Notice that all the 00056 // decimal floating-point values in this example can be represented 00057 // exactly in binary floating point. This example has correct 00058 // syntax, so you won't need to use tolerant mode to parse it. 00059 const char sampleMatrixMarketFile[] = 00060 "%%MatrixMarket matrix coordinate real general\n" 00061 "5 5 10\n" 00062 "5 5 55.0\n" 00063 "4 4 44.0\n" 00064 "3 3 33.0\n" 00065 "2 2 22.0\n" 00066 "1 1 11.0\n" 00067 "4 5 45.0\n" 00068 "3 4 34.0\n" 00069 "2 3 23.0\n" 00070 "1 2 12.0\n" 00071 "1 5 15.0\n"; 00072 00073 // Sample Matrix Market sparse matrix file for testing symmetric 00074 // storage. Matrix Market format for symmetric, skew-symemtric, 00075 // etc. specifies that only the lower triangle should be stored. 00076 const char symmetricMatrixMarketFile[] = 00077 "%%MatrixMarket matrix coordinate real symmetric\n" 00078 "5 5 10\n" 00079 "5 5 55.0\n" 00080 "4 4 44.0\n" 00081 "3 3 33.0\n" 00082 "2 2 22.0\n" 00083 "1 1 11.0\n" 00084 "5 4 54.0\n" 00085 "4 3 43.0\n" 00086 "3 2 32.0\n" 00087 "2 1 21.0\n" 00088 "5 1 51.0\n"; 00089 00090 // Given the three arrays of a CSR data structure, along with the 00091 // numbers of rows and columns, print the result to the given output 00092 // stream as a MatrixMarket file. 00093 template<class OrdinalType, class ScalarType> 00094 void 00095 csrToMatrixMarket (std::ostream& out, 00096 Teuchos::ArrayView<OrdinalType> ptr, 00097 Teuchos::ArrayView<OrdinalType> ind, 00098 Teuchos::ArrayView<ScalarType> val, 00099 const OrdinalType numRows, 00100 const OrdinalType numCols) 00101 { 00102 using Teuchos::ArrayView; 00103 using std::endl; 00104 typedef typename ArrayView<OrdinalType>::size_type size_type; 00105 typedef Teuchos::ScalarTraits<ScalarType> STS; 00106 00107 // Make the output stream write floating-point numbers in 00108 // scientific notation. It will politely put the output 00109 // stream back to its state on input, when this scope 00110 // terminates. 00111 Teuchos::MatrixMarket::details::SetScientific<ScalarType> sci (out); 00112 00113 out << "%%MatrixMarket matrix coordinate "; 00114 if (STS::isComplex) { 00115 out << "complex "; 00116 } 00117 else { 00118 out << "real "; 00119 } 00120 out << "general" << endl; 00121 out << numRows << " " << numCols << " " << ptr[numRows] << endl; 00122 OrdinalType k; 00123 for (OrdinalType i = 0; i < numRows; ++i) { 00124 for (k = ptr[i]; k < ptr[i+1]; ++k) { 00125 // Matrix Market files use 1-based row and column indices. 00126 out << (i+1) << " " << (ind[k]+1) << " "; 00127 if (STS::isComplex) { 00128 out << STS::real (val[k]) << " " << STS::imag (val[k]); 00129 } 00130 else { 00131 out << val[k]; 00132 } 00133 out << endl; 00134 } 00135 } 00136 TEUCHOS_TEST_FOR_EXCEPTION(k != ptr[numRows], std::logic_error, 00137 "csrToMatrixMarket: Failed to print all the matrix entries! The last k " 00138 "index value is " << k << ", but the number of entries is " << ptr[numRows] 00139 << "."); 00140 } 00141 } // namespace (anonymous) 00142 00143 // Benchmark driver 00144 int 00145 main (int argc, char *argv[]) 00146 { 00147 using Teuchos::MatrixMarket::Raw::Checker; 00148 using Teuchos::MatrixMarket::Raw::Reader; 00149 using Teuchos::ArrayRCP; 00150 using Teuchos::ArrayView; 00151 using Teuchos::Comm; 00152 using Teuchos::CommandLineProcessor; 00153 using Teuchos::ParameterList; 00154 using Teuchos::RCP; 00155 using Teuchos::rcp; 00156 using Teuchos::rcpFromRef; 00157 using Teuchos::SerialComm; 00158 using std::cout; 00159 using std::cerr; 00160 typedef double scalar_type; 00161 typedef int ordinal_type; 00162 00163 // Name of the Matrix Market sparse matrix file to read. If empty, 00164 // use the Matrix Market example embedded as a string in this file. 00165 std::string filename; 00166 // If true, just check the sparse matrix file. Otherwise, 00167 // do a full conversion to CSR (compressed sparse row) format. 00168 bool checkOnly = false; 00169 // Whether to echo the sparse matrix to stdout after reading it 00170 // successfully. 00171 bool echo = false; 00172 // Whether to parse the Matrix Market file tolerantly. 00173 bool tolerant = false; 00174 // Verbosity of output 00175 bool verbose = false; 00176 // Whether to print debugging-level output 00177 bool debug = false; 00178 00179 CommandLineProcessor cmdp (false, true); 00180 cmdp.setOption ("filename", &filename, 00181 "Name of the Matrix Market sparse matrix file to read."); 00182 cmdp.setOption ("checkOnly", "fullTest", &checkOnly, 00183 "If true, just check the syntax of the input file. " 00184 "Otherwise, do a full test."); 00185 cmdp.setOption ("echo", "noecho", &echo, 00186 "Whether to echo the sparse matrix contents to stdout " 00187 "after reading it successfully."); 00188 cmdp.setOption ("tolerant", "strict", &tolerant, 00189 "Whether to tolerate syntax errors in the Matrix Market file."); 00190 cmdp.setOption ("verbose", "quiet", &verbose, 00191 "Print status output to stdout."); 00192 cmdp.setOption ("debug", "nodebug", &debug, 00193 "Print possibly copious debugging output to stderr."); 00194 // Parse the command-line arguments. 00195 { 00196 const CommandLineProcessor::EParseCommandLineReturn parseResult = 00197 cmdp.parse (argc,argv); 00198 // If the caller asks us to print the documentation, or does not 00199 // explicitly say to run the benchmark, we let this "test" pass 00200 // trivially. 00201 if (parseResult == CommandLineProcessor::PARSE_HELP_PRINTED) { 00202 std::cout << "End Result: TEST PASSED" << endl; 00203 return EXIT_SUCCESS; 00204 } 00205 TEUCHOS_TEST_FOR_EXCEPTION( 00206 parseResult != CommandLineProcessor::PARSE_SUCCESSFUL, 00207 std::invalid_argument, "Failed to parse command-line arguments."); 00208 } 00209 00210 // Test reading in the sparse matrix. If no filename or an empty 00211 // filename is specified, the test passes trivially. 00212 bool success = true; 00213 if (checkOnly) { 00214 typedef Checker<scalar_type, ordinal_type> checker_type; 00215 checker_type checker (echo, tolerant, debug); 00216 00217 RCP<const Comm<int> > comm = rcp (new SerialComm<int>); 00218 if (filename != "") { 00219 if (verbose) { 00220 cout << "Checking syntax of the Matrix Market file \"" << filename 00221 << "\"" << endl; 00222 } 00223 success = success && checker.readFile (*comm, filename); 00224 if (verbose) { 00225 if (success) { 00226 cout << "The given file is a valid Matrix Market file." << endl; 00227 } 00228 else { 00229 cout << "The given file has syntax errors." << endl; 00230 } 00231 } 00232 } 00233 else { 00234 if (verbose) { 00235 cout << "Checking syntax of the first built-in Matrix Market example" << endl 00236 << std::flush;// for debug output next 00237 } 00238 if (debug) { 00239 cerr << "First built-in Matrix Market example: " << endl 00240 << sampleMatrixMarketFile << endl; 00241 } 00242 std::istringstream in (sampleMatrixMarketFile); 00243 RCP<std::istream> inStream = rcpFromRef (in); 00244 success = success && checker.read (*comm, inStream); 00245 if (verbose) { 00246 if (success) { 00247 cout << "The example has valid Matrix Market syntax." << endl; 00248 } 00249 else { 00250 cout << "The example has syntax errors." << endl; 00251 } 00252 } 00253 } 00254 } 00255 else { 00256 typedef Reader<scalar_type, ordinal_type> reader_type; 00257 reader_type reader (tolerant, debug); 00258 ArrayRCP<ordinal_type> ptr, ind; 00259 ArrayRCP<scalar_type> val; 00260 ordinal_type numRows, numCols; 00261 // 00262 // Read the Matrix Market data, either from a file or from a 00263 // built-in string. 00264 // 00265 if (filename != "") { 00266 if (verbose) { 00267 cout << "Reading the Matrix Market file \"" << filename << "\"" << endl; 00268 } 00269 success = success && reader.readFile (ptr, ind, val, 00270 numRows, numCols, filename); 00271 } 00272 else { 00273 if (verbose) { 00274 cout << "Reading the first built-in Matrix Market example" << endl; 00275 } 00276 if (debug) { 00277 cerr << "First built-in Matrix Market example:" << endl 00278 << sampleMatrixMarketFile << endl; 00279 } 00280 std::istringstream inStr (sampleMatrixMarketFile); 00281 success = success && reader.read (ptr, ind, val, numRows, numCols, inStr); 00282 } 00283 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::runtime_error, "Matrix Market " 00284 "reader failed to read the given file or input stream."); 00285 if (success && verbose) { 00286 cout << "Returned from reading the Matrix Market data" << endl 00287 << std::flush; // for following debug output 00288 } 00289 if (debug) { 00290 cerr << "CSR output info:" << endl 00291 << " ptr.size() = " << ptr.size() 00292 << ", ind.size() = " << ind.size() 00293 << ", val.size() = " << val.size() 00294 << ", numRows = " << numRows 00295 << ", numCols = " << numCols 00296 << endl; 00297 } 00298 00299 // Here's the fun part. Output the CSR data to an output stream. 00300 // Then read in the output stream. The resulting matrix should be 00301 // exactly the same (unless the original file had elements at the 00302 // same location that were added together with rounding error). 00303 std::ostringstream outStr; 00304 if (success && verbose) { 00305 cout << "Printing the CSR arrays to a Matrix Market output stream" 00306 << endl << std::flush; 00307 } 00308 csrToMatrixMarket<ordinal_type, scalar_type> (outStr, ptr (), ind (), val (), 00309 numRows, numCols); 00310 if (debug && echo) { 00311 cerr << "CSR data:" << endl 00312 << "- ptr = ["; 00313 for (ordinal_type i = 0; i < ptr.size(); ++i) { 00314 cerr << ptr[i]; 00315 if (i+1 != ptr.size()) { // don't subtract from zero if unsigned 00316 cerr << ", "; 00317 } 00318 } 00319 cerr << "]" << endl 00320 << "- ind = ["; 00321 for (ordinal_type i = 0; i < ind.size(); ++i) { 00322 cerr << ind[i]; 00323 if (i+1 != ind.size()) { // don't subtract from zero if unsigned 00324 cerr << ", "; 00325 } 00326 } 00327 cerr << "]" << endl 00328 << "- val = ["; 00329 for (ordinal_type i = 0; i < val.size(); ++i) { 00330 cerr << val[i]; 00331 if (i+1 != val.size()) { // don't subtract from zero if unsigned 00332 cerr << ", "; 00333 } 00334 } 00335 cerr << "]" << endl; 00336 00337 cerr << "CSR data, converted back to Matrix Market format" << endl; 00338 csrToMatrixMarket<ordinal_type, scalar_type> (cerr, ptr (), ind (), val (), 00339 numRows, numCols); 00340 cerr << endl; 00341 } 00342 00343 ArrayRCP<ordinal_type> newptr, newind; 00344 ArrayRCP<scalar_type> newval; 00345 ordinal_type newNumRows, newNumCols; 00346 if (success && verbose) { 00347 cout << "Reading the Matrix Market output back into CSR arrays" << endl; 00348 } 00349 { 00350 std::istringstream inStr (outStr.str ()); 00351 success = success && reader.read (newptr, newind, newval, 00352 newNumRows, newNumCols, inStr); 00353 } 00354 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::logic_error, "Matrix Market " 00355 "reader failed to read the output back into CSR arrays."); 00356 if (success && verbose) { 00357 cout << "Successfully read the Matrix Market output back into CSR arrays" 00358 << endl << std::flush; 00359 } 00360 if (debug) { 00361 cerr << "CSR output info:" << endl 00362 << " newptr.size() = " << newptr.size() 00363 << ", newind.size() = " << newind.size() 00364 << ", newval.size() = " << newval.size() 00365 << ", newNumRows = " << newNumRows 00366 << ", newNumCols = " << newNumCols 00367 << endl; 00368 } 00369 00370 // The old arrays should equal the new arrays. 00371 TEUCHOS_TEST_FOR_EXCEPTION(ptr.size () != newptr.size (), std::logic_error, 00372 "New ptr array has a different length than old ptr array"); 00373 TEUCHOS_TEST_FOR_EXCEPTION(ind.size () != newind.size (), std::logic_error, 00374 "New ind array has a different length than old ind array"); 00375 TEUCHOS_TEST_FOR_EXCEPTION(val.size () != newval.size (), std::logic_error, 00376 "New val array has a different length than old val array"); 00377 TEUCHOS_TEST_FOR_EXCEPTION(newNumRows != numRows || newNumCols != numCols, 00378 std::logic_error, "New dimensions differ from old dimensions"); 00379 TEUCHOS_TEST_FOR_EXCEPTION(ptr.size () != numRows+1, std::logic_error, 00380 "ptr.size() != numRows+1"); 00381 TEUCHOS_TEST_FOR_EXCEPTION(newptr.size () != newNumRows+1, std::logic_error, 00382 "newptr.size() != newNumRows+1"); 00383 00384 for (ordinal_type rowIndex = 0; rowIndex < numRows; ++rowIndex) { 00385 TEUCHOS_TEST_FOR_EXCEPTION(ptr[rowIndex] != newptr[rowIndex], 00386 std::logic_error, "At row index " << rowIndex << ", ptr[rowIndex] = " 00387 << ptr[rowIndex] << " != newptr[rowIndex] = " << newptr[rowIndex] 00388 << "."); 00389 TEUCHOS_TEST_FOR_EXCEPTION(ptr[rowIndex+1] != newptr[rowIndex+1], 00390 std::logic_error, "At row index " << rowIndex << ", ptr[rowIndex+1] = " 00391 << ptr[rowIndex+1] << " != newptr[rowIndex+1] = " << newptr[rowIndex+1] 00392 << "."); 00393 for (ordinal_type k = ptr[rowIndex]; k < ptr[rowIndex+1]; ++k) { 00394 TEUCHOS_TEST_FOR_EXCEPTION(ind[k] != newind[k], std::logic_error, 00395 "At row index " << rowIndex << ", ind[k=" << k << "] = " 00396 << ind[k] << " != newind[k] = " << newind[k] << "."); 00397 // You may want to relax this inequality if the original 00398 // Matrix Market file had multiple entries at the same 00399 // location and if adding them together resulted in rounding 00400 // error. 00401 TEUCHOS_TEST_FOR_EXCEPTION(val[k] != newval[k], std::logic_error, 00402 "At row index " << rowIndex << ", val[k=" << k << "] = " 00403 << val[k] << " != newval[k] = " << newval[k] << "."); 00404 } 00405 } 00406 00407 // Now test reading symmetric data, if no filename was specified. 00408 if (filename == "") { 00409 std::istringstream inStr (symmetricMatrixMarketFile); 00410 success = success && reader.read (ptr, ind, val, numRows, numCols, inStr); 00411 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::logic_error, 00412 "Matrix Market reader failed to read the given example string."); 00413 if (success && verbose) { 00414 cout << "Returned from reading the Matrix Market data" << endl 00415 << std::flush; // for following debug output 00416 } 00417 if (debug) { 00418 cerr << "CSR output info:" << endl 00419 << " ptr.size() = " << ptr.size() 00420 << ", ind.size() = " << ind.size() 00421 << ", val.size() = " << val.size() 00422 << ", numRows = " << numRows 00423 << ", numCols = " << numCols 00424 << endl; 00425 } 00426 00427 // This is a bit of a hack, since we know the contents of the 00428 // example. Since we "symmetrize" when reading in symmetric 00429 // data, there should be 15 entries in the resulting matrix. 00430 const ordinal_type correctNumEntries = 15; 00431 TEUCHOS_TEST_FOR_EXCEPTION( 00432 val.size() != correctNumEntries, 00433 std::logic_error, 00434 "Incorrect number of entries after symmetrization: There should be " 00435 << correctNumEntries << ", but there are " << val.size() << " entries " 00436 "instead."); 00437 } 00438 } // end of the file / string Reader tests 00439 00440 if (success) { 00441 std::cout << "End Result: TEST PASSED" << endl; 00442 return EXIT_SUCCESS; 00443 } 00444 else { 00445 std::cout << "End Result: TEST FAILED" << endl; 00446 return EXIT_FAILURE; 00447 } 00448 } 00449 00450 00451
1.7.6.1