1 /*
2 ARPACK++ v1.2 2/20/2000
3 c++ interface to ARPACK code.
4
5 MODULE ARHBMat.h
6 Matrix template that generates a matrix in CSC format
7 from a Harwell-Boing matrix file.
8
9 ARPACK authors:
10 Richard Lehoucq
11 Kristyn Maschhoff
12 Danny Sorensen
13 Chao Yang
14 Dept. of Computational & Applied Mathematics
15 Rice University
16 Houston, Texas
17 */
18
19
20 #ifndef ARHBMAT_H
21 #define ARHBMAT_H
22
23 #include <cstddef>
24 #include <fstream>
25 #include <cstdlib>
26 #include <cstring>
27 #include <string>
28 #include "arch.h"
29 #include "arerror.h"
30
31
32 template<class ARINT, class ARTYPE>
33 class ARhbMatrix {
34
35 private:
36
37 std::string datafile; // Filename.
38 std::string title; // Title.
39 std::string name; // Name.
40 std::string type; // Matrix type.
41 int m; // Number of rows.
42 int n; // Number of columns.
43 int nnz; // Number of nonzero variables.
44 ARINT* irow; // Row indices.
45 ARINT* pcol; // Column pointers.
46 ARTYPE* val; // Numerical values of matrix entries.
47
48 void ConvertDouble(char* num);
49
50 bool ReadEntry(std::ifstream& file, int nval, int fval, int& j, double& val);
51
52 bool ReadEntry(std::ifstream& file, int nval, int fval, int& j, float& val);
53
54 bool ReadEntry(std::ifstream& file, int nval, int fval,
55 int& j, arcomplex<double>& val);
56
57 bool ReadEntry(std::ifstream& file, int nval, int fval,
58 int& j, arcomplex<float>& val);
59
60 void ReadFormat(std::ifstream& file, int& n, int& fmt);
61
62 public:
63
IsDefined()64 bool IsDefined() { return (m!=0); }
65
IsReal()66 bool IsReal() { return (type.size() > 0 && type[0]=='R'); }
67
IsComplex()68 bool IsComplex() { return (type.size() > 0 && type[0]=='C'); }
69
IsSymmetric()70 bool IsSymmetric() { return (type.size() > 1 && type[1]=='S'); }
71
IsUnsymmetric()72 bool IsUnsymmetric() { return (type.size() > 1 && type[1]=='U'); }
73
IsHermitian()74 bool IsHermitian() { return (type.size() > 1 && type[1]=='H'); }
75
IsSkewSymmetric()76 bool IsSkewSymmetric() { return (type.size() > 1 && type[1]=='Z'); }
77
Filename()78 const std::string& Filename() { return datafile; }
79
Title()80 const std::string& Title() { return title; }
81
Name()82 const std::string& Name() { return name; }
83
Type()84 const std::string& Type() { return type; }
85
NRows()86 int NRows() { return m; }
87
NCols()88 int NCols() { return n; }
89
NonZeros()90 int NonZeros() { return nnz; }
91
RowInd()92 ARINT* RowInd() { return irow; }
93
ColPtr()94 ARINT* ColPtr() { return pcol; }
95
Entries()96 ARTYPE* Entries() { return val; }
97
98 void Define(const std::string& filename);
99 // Function that reads the matrix file.
100
101 ARhbMatrix();
102 // Short constructor.
103
ARhbMatrix(const std::string & filename)104 ARhbMatrix(const std::string& filename) { Define(filename); }
105 // Long constructor.
106
107 ~ARhbMatrix();
108 // Destructor.
109
110 }; // Class ARhbMatrix.
111
112
113 // ------------------------------------------------------------------------ //
114 // ARhbMatrix member functions definition. //
115 // ------------------------------------------------------------------------ //
116
117
118 template<class ARINT, class ARTYPE>
ConvertDouble(char * num)119 inline void ARhbMatrix<ARINT, ARTYPE>::ConvertDouble(char* num)
120 {
121
122 char* pd;
123
124 pd = strchr((char*)num,'D');
125 if (pd) *pd = 'E';
126 pd = strchr((char*)num,'d');
127 if (pd) *pd = 'E';
128
129
130 } // ConvertDouble.
131
132
133 template<class ARINT, class ARTYPE>
134 inline bool ARhbMatrix<ARINT, ARTYPE>::
ReadEntry(std::ifstream & file,int nval,int fval,int & j,double & val)135 ReadEntry(std::ifstream& file, int nval, int fval, int& j, double& val)
136 {
137
138 char num[81];
139 char c;
140
141 if (file.get((char*)num,fval,'\n')) {
142 ConvertDouble((char*)num);
143 val = atof((char*)num);
144 if (!((++j)%nval)) do file.get(c); while (c!='\n');
145 return true;
146 }
147 else {
148 return false;
149 }
150
151 } // ReadEntry (double).
152
153
154 template<class ARINT, class ARTYPE>
155 inline bool ARhbMatrix<ARINT, ARTYPE>::
ReadEntry(std::ifstream & file,int nval,int fval,int & j,float & val)156 ReadEntry(std::ifstream& file, int nval, int fval, int& j, float& val)
157 {
158
159 double dval;
160 bool ret;
161
162 ret = ReadEntry(file, nval, fval, j, dval);
163 val = (float)dval;
164 return ret;
165
166 } // ReadEntry (float).
167
168
169 template<class ARINT, class ARTYPE>
170 inline bool ARhbMatrix<ARINT, ARTYPE>::
ReadEntry(std::ifstream & file,int nval,int fval,int & j,arcomplex<double> & val)171 ReadEntry(std::ifstream& file, int nval, int fval,
172 int& j, arcomplex<double>& val)
173 {
174
175 char num[81], img[81];
176 char c;
177
178 if (file.get((char*)num,fval,'\n')) {
179 ConvertDouble((char*)num);
180 if (!((++j)%nval)) do file.get(c); while (c!='\n');
181 if (file.get((char*)img,fval,'\n')) {
182 ConvertDouble((char*)img);
183 if (!((++j)%nval)) do file.get(c); while (c!='\n');
184 val = arcomplex<double>(atof((char*)num), atof((char*)img));
185 return true;
186 }
187 else {
188 return false;
189 }
190 }
191 else {
192 return false;
193 }
194
195 } // ReadEntry (arcomplex<double>).
196
197
198 template<class ARINT, class ARTYPE>
199 inline bool ARhbMatrix<ARINT, ARTYPE>::
ReadEntry(std::ifstream & file,int nval,int fval,int & j,arcomplex<float> & val)200 ReadEntry(std::ifstream& file, int nval, int fval,
201 int& j, arcomplex<float>& val)
202 {
203
204 // I hope one day c++ will have a standard complex
205 // class, so functions like this can be suppressed.
206
207 char num[81], img[81];
208 char c;
209
210 if (file.get((char*)num,fval,'\n')) {
211 ConvertDouble((char*)num);
212 if (!((++j)%nval)) do file.get(c); while (c!='\n');
213 if (file.get((char*)img,fval,'\n')) {
214 ConvertDouble((char*)img);
215 if (!((++j)%nval)) do file.get(c); while (c!='\n');
216 val = arcomplex<float>(atof((char*)num), atof((char*)img));
217 return true;
218 }
219 else {
220 return false;
221 }
222 }
223 else {
224 return false;
225 }
226
227 } // ReadEntry (arcomplex<float>).
228
229
230 template<class ARINT, class ARTYPE>
ReadFormat(std::ifstream & file,int & n,int & fmt)231 void ARhbMatrix<ARINT, ARTYPE>::ReadFormat(std::ifstream& file, int& n, int& fmt)
232 {
233
234 char c;
235
236 do file.get(c); while ((c != '(') && (c!='\n'));
237 file >> n;
238 file.get(c);
239 while ((c!='I') && (c!='i') && (c!='E') && (c!='e') &&
240 (c!='D') && (c!='d') && (c!='\n')) {
241 do file.get(c); while ((c != ',') && (c!='\n'));
242 file >> n;
243 file.get(c);
244 }
245 if ((c==')')||(c=='\n')) { // Reading error!
246 fmt = 0;
247 }
248 else {
249 file >> fmt;
250 }
251
252 } // ReadFormat.
253
254
255 template<class ARINT, class ARTYPE>
Define(const std::string & filename)256 void ARhbMatrix<ARINT, ARTYPE>::Define(const std::string& filename)
257 {
258
259 // Declaring variables.
260
261 int i, j;
262 int lintot, linptr, linind, linval, linrhs;
263 int npcol, fpcol, nirow, firow, nval, fval;
264 char c;
265 char num[81];
266 char titlechar[73];
267 char namechar[9];
268 char typechar[4];
269 ARTYPE value;
270
271 // Opening file.
272
273 datafile = filename;
274 std::ifstream file(datafile.c_str());
275
276 if (!file) {
277 throw ArpackError(ArpackError::CANNOT_OPEN_FILE, "ARhbMatrix");
278 }
279
280 // Reading the first line.
281
282 file.get((char*)titlechar,73,'\n');
283 title = std::string(titlechar);
284 file.get((char*)namechar,9,'\n');
285 name = std::string(namechar);
286 do file.get(c); while (c!='\n');
287
288 // Reading the second line.
289
290 file >> lintot >> linptr >> linind >> linval >> linrhs;
291 do file.get(c); while (c!='\n');
292
293 if ((linptr < 1) || (linind < 1)) {
294 throw ArpackError(ArpackError::PARAMETER_ERROR, "ARhbMatrix");
295 }
296
297 // Reading the third line.
298
299 file.get((char*)typechar,4,'\n');
300 type = std::string(typechar);
301 file >> m >> n >> nnz;
302 do file.get(c); while (c!='\n');
303
304 if ( (type.size()<3) || ((type[0] != 'R') && (type[0] != 'C')) || (type[2] != 'A')) {
305 throw ArpackError(ArpackError::WRONG_MATRIX_TYPE, "ARhbMatrix");
306 }
307 else if ((m < 1) || (n < 1) || (nnz < 1)) {
308 throw ArpackError(ArpackError::PARAMETER_ERROR, "ARhbMatrix");
309 }
310
311 // Reading the fourth line.
312
313 ReadFormat(file, npcol, fpcol);
314 ReadFormat(file, nirow, firow);
315 ReadFormat(file, nval, fval);
316 do file.get(c); while (c!='\n');
317 if ((fpcol<1) || (firow<1) || (fval<1)) {
318 throw ArpackError(ArpackError::WRONG_DATA_TYPE, "ARhbMatrix");
319 }
320
321 // Skipping the fifth line.
322
323 if (linrhs) {
324 do file.get(c); while (c!='\n');
325 ArpackError(ArpackError::RHS_IGNORED, "ARhbMatrix");
326 }
327
328 // Reading column pointers.
329
330 pcol = new ARINT[n+1];
331 fpcol++;
332 i = 0;
333 while ((i <= n) && (file.get((char*)num,fpcol,'\n'))) {
334 pcol[i++] = atoi((char*)num)-1;
335 if (!(i%npcol)) do file.get(c); while (c!='\n');
336 }
337 if (i%npcol) do file.get(c); while (c!='\n');
338
339 if (i <= n) {
340 throw ArpackError(ArpackError::UNEXPECTED_EOF, "ARhbMatrix");
341 }
342
343 // Reading row indices.
344
345 irow = new ARINT[nnz];
346 firow++;
347 i = 0;
348 while ((i < nnz) && (file.get((char*)num,firow,'\n'))) {
349 irow[i++] = atoi((char*)num)-1;
350 if (!(i%nirow)) do file.get(c); while (c!='\n');
351 }
352 if (i%nirow) do file.get(c); while (c!='\n');
353
354 if (i < nnz) {
355 throw ArpackError(ArpackError::UNEXPECTED_EOF, "ARhbMatrix");
356 }
357
358 // Reading matrix elements.
359
360 fval++;
361 val = new ARTYPE[nnz];
362 i = 0;
363 j = 0;
364 while ((i < nnz) && (ReadEntry(file, nval, fval, j, value))) {
365 val[i++] = value;
366 }
367 if (j%nval) do file.get(c); while (c!='\n');
368
369 if (i < nnz) {
370 throw ArpackError(ArpackError::UNEXPECTED_EOF, "ARhbMatrix");
371 }
372
373 // Closing file and reporting success.
374
375 file.close();
376
377 } // Define.
378
379
380 template<class ARINT, class ARTYPE>
ARhbMatrix()381 ARhbMatrix<ARINT, ARTYPE>::ARhbMatrix()
382 {
383
384 m = n = nnz = 0;
385 title[0]= '\0';
386 name[0] = '\0';
387 type[0] = '\0';
388 pcol = NULL;
389 irow = NULL;
390 val = NULL;
391
392 } // Short constructor.
393
394
395 template<class ARINT, class ARTYPE>
~ARhbMatrix()396 ARhbMatrix<ARINT, ARTYPE>::~ARhbMatrix()
397 {
398
399 if (irow != NULL) delete[] irow;
400 if (pcol != NULL) delete[] pcol;
401 if (val != NULL) delete[] val;
402
403 } // Destructor.
404
405
406 #endif // ARHBMAT_H
407
408