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