|
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 #include "Teuchos_MatrixMarket_Banner.hpp" 00043 #include "Teuchos_MatrixMarket_split.hpp" 00044 #include "Teuchos_TestForException.hpp" 00045 #include <algorithm> 00046 #include <iostream> 00047 #include <sstream> 00048 #include <stdexcept> 00049 00050 00051 namespace Teuchos { 00052 namespace MatrixMarket { 00053 00054 using details::split; 00055 using details::trim_and_lowercase; 00056 00057 std::string 00058 Banner::validateObjectType (const std::string& objectType, const bool tolerant) 00059 { 00060 // Canonical representation is lowercase 00061 std::string out = trim_and_lowercase (objectType); 00062 00063 const char* const validValues[] = {"matrix"}; 00064 const int numValidValues = 1; 00065 if (tolerant) 00066 // This is the only value currently defined for this token in 00067 // the Matrix Market format, so we just return it. 00068 return std::string (validValues[0]); 00069 else if (validValues + numValidValues == 00070 std::find (validValues, validValues + numValidValues, out)) 00071 throw std::invalid_argument("Object type \"" + out + "\" is " 00072 "not one of the valid values"); 00073 else 00074 return out; 00075 } 00076 00077 std::string 00078 Banner::validateMatrixType (const std::string& matrixType, const bool tolerant) 00079 { 00080 // Canonical representation is lowercase 00081 std::string out = trim_and_lowercase (matrixType); 00082 00083 const char* const validValues[] = {"coordinate", "array"}; 00084 const int numValidValues = 2; 00085 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out)) 00086 throw std::invalid_argument("Matrix type \"" + out + "\" is not one of the valid values"); 00087 else 00088 return out; 00089 } 00090 00091 std::string 00092 Banner::validateDataType (const std::string& dataType, const bool tolerant) 00093 { 00094 // Canonical representation is lowercase 00095 std::string out = trim_and_lowercase (dataType); 00096 00097 const char* const validValues[] = {"real", "complex", "integer", "pattern"}; 00098 const int numValidValues = 4; 00099 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out)) 00100 throw std::invalid_argument("Data type \"" + out + "\" is not one of the valid values"); 00101 else 00102 return out; 00103 } 00104 00105 std::string 00106 Banner::validateSymmType (const std::string& symmType, const bool tolerant) 00107 { 00108 // Canonical representation is lowercase 00109 std::string out = trim_and_lowercase (symmType); 00110 00111 if (tolerant) 00112 { 00113 const char* const validValues[] = 00114 {"general", "nonsymmetric", "unsymmetric", "symmetric", 00115 "skew-symmetric", "skew", "hermitian"}; 00116 const int numValidValues = 7; 00117 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out)) 00118 throw std::invalid_argument("Symmetry type \"" + out + "\" is not one of the valid values"); 00119 else 00120 { 00121 if (out == "nonsymmetric" || out == "unsymmetric") 00122 return std::string("general"); 00123 else if (out == "skew") 00124 return std::string("skew-symmetric"); 00125 else 00126 return out; 00127 } 00128 } 00129 else 00130 { 00131 const char* const validValues[] = {"general", "symmetric", "skew-symmetric", "hermitian"}; 00132 const int numValidValues = 4; 00133 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out)) 00134 throw std::invalid_argument("Symmetry type \"" + out + "\" is not one of the valid values"); 00135 else 00136 return out; 00137 } 00138 } 00139 00140 00141 void 00142 Banner::setDefaults (const int howMany) 00143 { 00144 if (howMany >= 4) 00145 objectType_ = "matrix"; 00146 if (howMany >= 3) 00147 matrixType_ = "coordinate"; 00148 if (howMany >= 2) 00149 dataType_ = "real"; 00150 if (howMany >= 1) 00151 symmType_ = "general"; 00152 } 00153 00154 Banner::Banner (const std::string& line, const bool tolerant) 00155 { 00156 size_t start; 00157 00158 if (line.empty()) { 00159 if (tolerant) { 00160 setDefaults (4); 00161 return; 00162 } 00163 else { 00164 throw std::invalid_argument ("The banner line is empty"); 00165 } 00166 } 00167 start = line.find_first_not_of (" \t"); 00168 if (start == std::string::npos) { 00169 if (tolerant) { 00170 setDefaults (4); 00171 return; 00172 } 00173 else { 00174 throw std::invalid_argument ("The banner line contains only " 00175 "whitespace characters"); 00176 } 00177 } 00178 else if (start != 0 && ! tolerant) { 00179 // If tolerant, we allow the banner line to start with 00180 // whitespace characters, and keep reading. 00181 throw std::invalid_argument ("The banner line is not allowed to start " 00182 "with whitespace characters"); 00183 } 00184 00185 // Find "%%MatrixMarket" -- it should be the first thing in the 00186 // banner line, and all other data should come after it. 00187 // Optionally relax to allow any case, and possibly a space 00188 // between "%%" and "MatrixMarket". 00189 size_t ppStart = line.find ("%%", start); 00190 size_t tokenStart; 00191 if (ppStart == std::string::npos) { 00192 if (tolerant) { 00193 tokenStart = start; // Just ignore the missing %% 00194 } 00195 else { 00196 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix " 00197 "Market file's banner line should always start with \"%%\". Here " 00198 "is the offending line: " << std::endl << line); 00199 } 00200 } 00201 else { 00202 tokenStart = ppStart + 2; 00203 if (tokenStart >= line.size()) { 00204 // There's no banner information after the %%. 00205 if (tolerant) { 00206 setDefaults (4); 00207 return; 00208 } 00209 else { 00210 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix " 00211 "Market file's banner line needs to contain information after the " 00212 "\"%%\" marker. Here is the offending line: " << std::endl << line); 00213 } 00214 } 00215 } 00216 // 00217 // In tolerant mode, fill in missing tokens with their default 00218 // values. 00219 // 00220 // After extracting the %%, search for the five tokens. 00221 std::vector<std::string> tokens = split (line, " \t", 2); 00222 const int numTokens = tokens.size(); 00223 if (numTokens < 1) { 00224 if (tolerant) { 00225 setDefaults (4); 00226 return; 00227 } 00228 else { 00229 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix " 00230 "Market file's banner line must always begin with the \"Matrix" 00231 "Market\" keyword. Here is the offending line: " << std::endl 00232 << line); 00233 } 00234 } 00235 // In tolerant mode, just ignore the first token. 00236 if (! tolerant && tokens[0] != "MatrixMarket") { 00237 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix " 00238 "Market file's banner line must always begin with the \"Matrix" 00239 "Market\" keyword. Here is the offending line: " << std::endl 00240 << line); 00241 } 00242 if (numTokens < 5) { 00243 if (tolerant) { 00244 setDefaults (5 - numTokens); // how many defaults to set 00245 } 00246 else { 00247 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix " 00248 "Market file's banner line must always have 5 tokens, but yours " 00249 "only has " << numTokens << "token" << (numTokens != 1 ? "s" : "") 00250 << ". Here is the offending line: " << std::endl << line); 00251 } 00252 } 00253 if (numTokens >= 2) { 00254 objectType_ = validateObjectType (tokens[1], tolerant); 00255 } 00256 if (numTokens >= 3) { 00257 matrixType_ = validateMatrixType (tokens[2], tolerant); 00258 } 00259 if (numTokens >= 4) { 00260 dataType_ = validateDataType (tokens[3], tolerant); 00261 } 00262 if (numTokens >= 5) { 00263 symmType_ = validateSymmType (tokens[4], tolerant); 00264 } 00265 } 00266 00267 std::ostream& 00268 operator<< (std::ostream& out, const Banner& banner) 00269 { 00270 out << "%%MatrixMarket" 00271 << " " << banner.objectType() 00272 << " " << banner.matrixType() 00273 << " " << banner.dataType() 00274 << " " << banner.symmType(); 00275 return out; 00276 } 00277 } // namespace MatrixMarket 00278 } // namespace Teuchos 00279
1.7.6.1