Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_MatrixMarket_Banner.cpp
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#include "Teuchos_MatrixMarket_Banner.hpp"
43#include "Teuchos_MatrixMarket_split.hpp"
45#include <algorithm>
46#include <iostream>
47#include <sstream>
48#include <stdexcept>
49
50
51namespace Teuchos {
52 namespace MatrixMarket {
53
54 using details::split;
55 using details::trim_and_lowercase;
56
57 std::string
58 Banner::validateObjectType (const std::string& objectType, const bool tolerant)
59 {
60 // Canonical representation is lowercase
61 std::string out = trim_and_lowercase (objectType);
62
63 const char* const validValues[] = {"matrix"};
64 const int numValidValues = 1;
65 if (tolerant)
66 // This is the only value currently defined for this token in
67 // the Matrix Market format, so we just return it.
68 return std::string (validValues[0]);
69 else if (validValues + numValidValues ==
70 std::find (validValues, validValues + numValidValues, out))
71 throw std::invalid_argument("Object type \"" + out + "\" is "
72 "not one of the valid values");
73 else
74 return out;
75 }
76
77 std::string
78 Banner::validateMatrixType (const std::string& matrixType, const bool /* tolerant */)
79 {
80 // Canonical representation is lowercase
81 std::string out = trim_and_lowercase (matrixType);
82
83 const char* const validValues[] = {"coordinate", "array"};
84 const int numValidValues = 2;
85 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out))
86 throw std::invalid_argument("Matrix type \"" + out + "\" is not one of the valid values");
87 else
88 return out;
89 }
90
91 std::string
92 Banner::validateDataType (const std::string& dataType, const bool /* tolerant */)
93 {
94 // Canonical representation is lowercase
95 std::string out = trim_and_lowercase (dataType);
96
97 const char* const validValues[] = {"real", "complex", "integer", "pattern"};
98 const int numValidValues = 4;
99 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out))
100 throw std::invalid_argument("Data type \"" + out + "\" is not one of the valid values");
101 else
102 return out;
103 }
104
105 std::string
106 Banner::validateSymmType (const std::string& symmType, const bool tolerant)
107 {
108 // Canonical representation is lowercase
109 std::string out = trim_and_lowercase (symmType);
110
111 if (tolerant)
112 {
113 const char* const validValues[] =
114 {"general", "nonsymmetric", "unsymmetric", "symmetric",
115 "skew-symmetric", "skew", "hermitian"};
116 const int numValidValues = 7;
117 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out))
118 throw std::invalid_argument("Symmetry type \"" + out + "\" is not one of the valid values");
119 else
120 {
121 if (out == "nonsymmetric" || out == "unsymmetric")
122 return std::string("general");
123 else if (out == "skew")
124 return std::string("skew-symmetric");
125 else
126 return out;
127 }
128 }
129 else
130 {
131 const char* const validValues[] = {"general", "symmetric", "skew-symmetric", "hermitian"};
132 const int numValidValues = 4;
133 if (validValues + numValidValues == std::find (validValues, validValues + numValidValues, out))
134 throw std::invalid_argument("Symmetry type \"" + out + "\" is not one of the valid values");
135 else
136 return out;
137 }
138 }
139
140
141 void
142 Banner::setDefaults (const int howMany)
143 {
144 if (howMany >= 4)
145 objectType_ = "matrix";
146 if (howMany >= 3)
147 matrixType_ = "coordinate";
148 if (howMany >= 2)
149 dataType_ = "real";
150 if (howMany >= 1)
151 symmType_ = "general";
152 }
153
154 Banner::Banner (const std::string& line, const bool tolerant)
155 {
156 size_t start;
157
158 if (line.empty()) {
159 if (tolerant) {
160 setDefaults (4);
161 return;
162 }
163 else {
164 throw std::invalid_argument ("The banner line is empty");
165 }
166 }
167 start = line.find_first_not_of (" \t");
168 if (start == std::string::npos) {
169 if (tolerant) {
170 setDefaults (4);
171 return;
172 }
173 else {
174 throw std::invalid_argument ("The banner line contains only "
175 "whitespace characters");
176 }
177 }
178 else if (start != 0 && ! tolerant) {
179 // If tolerant, we allow the banner line to start with
180 // whitespace characters, and keep reading.
181 throw std::invalid_argument ("The banner line is not allowed to start "
182 "with whitespace characters");
183 }
184
185 // Find "%%MatrixMarket" -- it should be the first thing in the
186 // banner line, and all other data should come after it.
187 // Optionally relax to allow any case, and possibly a space
188 // between "%%" and "MatrixMarket".
189 size_t ppStart = line.find ("%%", start);
190 size_t tokenStart;
191 if (ppStart == std::string::npos) {
192 if (tolerant) {
193 tokenStart = start; // Just ignore the missing %%
194 }
195 else {
196 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix "
197 "Market file's banner line should always start with \"%%\". Here "
198 "is the offending line: " << std::endl << line);
199 }
200 }
201 else {
202 tokenStart = ppStart + 2;
203 if (tokenStart >= line.size()) {
204 // There's no banner information after the %%.
205 if (tolerant) {
206 setDefaults (4);
207 return;
208 }
209 else {
210 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix "
211 "Market file's banner line needs to contain information after the "
212 "\"%%\" marker. Here is the offending line: " << std::endl << line);
213 }
214 }
215 }
216 //
217 // In tolerant mode, fill in missing tokens with their default
218 // values.
219 //
220 // After extracting the %%, search for the five tokens.
221 std::vector<std::string> tokens = split (line, " \t", 2);
222 const int numTokens = tokens.size();
223 if (numTokens < 1) {
224 if (tolerant) {
225 setDefaults (4);
226 return;
227 }
228 else {
229 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix "
230 "Market file's banner line must always begin with the \"Matrix"
231 "Market\" keyword. Here is the offending line: " << std::endl
232 << line);
233 }
234 }
235 // In tolerant mode, just ignore the first token.
236 if (! tolerant && tokens[0] != "MatrixMarket") {
237 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix "
238 "Market file's banner line must always begin with the \"Matrix"
239 "Market\" keyword. Here is the offending line: " << std::endl
240 << line);
241 }
242 if (numTokens < 5) {
243 if (tolerant) {
244 setDefaults (5 - numTokens); // how many defaults to set
245 }
246 else {
247 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The Matrix "
248 "Market file's banner line must always have 5 tokens, but yours "
249 "only has " << numTokens << "token" << (numTokens != 1 ? "s" : "")
250 << ". Here is the offending line: " << std::endl << line);
251 }
252 }
253 if (numTokens >= 2) {
254 objectType_ = validateObjectType (tokens[1], tolerant);
255 }
256 if (numTokens >= 3) {
257 matrixType_ = validateMatrixType (tokens[2], tolerant);
258 }
259 if (numTokens >= 4) {
260 dataType_ = validateDataType (tokens[3], tolerant);
261 }
262 if (numTokens >= 5) {
263 symmType_ = validateSymmType (tokens[4], tolerant);
264 }
265 }
266
267 std::ostream&
268 operator<< (std::ostream& out, const Banner& banner)
269 {
270 out << "%%MatrixMarket"
271 << " " << banner.objectType()
272 << " " << banner.matrixType()
273 << " " << banner.dataType()
274 << " " << banner.symmType();
275 return out;
276 }
277 } // namespace MatrixMarket
278} // namespace Teuchos
279
Standard test and throw macros.
Parse a Matrix Market banner line.
Banner(const std::string &line, const bool tolerant=false)
const std::string & symmType() const
Symmetric storage type.
const std::string & objectType() const
The object type.
const std::string & dataType() const
Data type of matrix entries.
const std::string & matrixType() const
Storage type of the matrix.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Matrix Market file utilities.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...