Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Util_iohb.cpp
1/*
2Fri Aug 15 16:29:47 EDT 1997
3
4 Harwell-Boeing File I/O in C
5 V. 1.0
6
7 National Institute of Standards and Technology, MD.
8 K.A. Remington
9
10++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 NOTICE
12
13 Permission to use, copy, modify, and distribute this software and
14 its documentation for any purpose and without fee is hereby granted
15 provided that the above copyright notice appear in all copies and
16 that both the copyright notice and this permission notice appear in
17 supporting documentation.
18
19 Neither the Author nor the Institution (National Institute of Standards
20 and Technology) make any representations about the suitability of this
21 software for any purpose. This software is provided "as is" without
22 expressed or implied warranty.
23++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24
25 ---------------------
26 INTERFACE DESCRIPTION
27 ---------------------
28 ---------------
29 QUERY FUNCTIONS
30 ---------------
31
32 FUNCTION:
33
34 int readHB_info(const char *filename, int *M, int *N, int *nz,
35 char **Type, int *Nrhs)
36
37 DESCRIPTION:
38
39 The readHB_info function opens and reads the header information from
40 the specified Harwell-Boeing file, and reports back the number of rows
41 and columns in the stored matrix (M and N), the number of nonzeros in
42 the matrix (nz), the 3-character matrix type(Type), and the number of
43 right-hand-sides stored along with the matrix (Nrhs). This function
44 is designed to retrieve basic size information which can be used to
45 allocate arrays.
46
47 FUNCTION:
48
49 int readHB_header(std::FILE* in_file, char* Title, char* Key, char* Type,
50 int* Nrow, int* Ncol, int* Nnzero, int* Nrhs,
51 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
52 int* Ptrcrd, int* Indcrd, int* Valcrd, int* Rhscrd,
53 char *Rhstype)
54
55 DESCRIPTION:
56
57 More detailed than the readHB_info function, readHB_header() reads from
58 the specified Harwell-Boeing file all of the header information.
59
60
61 ------------------------------
62 DOUBLE PRECISION I/O FUNCTIONS
63 ------------------------------
64 FUNCTION:
65
66 int readHB_newmat_double(const char *filename, int *M, int *N, *int nz,
67 int **colptr, int **rowind, double**val)
68
69 int readHB_mat_double(const char *filename, int *colptr, int *rowind,
70 double*val)
71
72
73 DESCRIPTION:
74
75 This function opens and reads the specified file, interpreting its
76 contents as a sparse matrix stored in the Harwell/Boeing standard
77 format. (See readHB_aux_double to read auxillary vectors.)
78 -- Values are interpreted as double precision numbers. --
79
80 The "mat" function uses _pre-allocated_ vectors to hold the index and
81 nonzero value information.
82
83 The "newmat" function allocates vectors to hold the index and nonzero
84 value information, and returns pointers to these vectors along with
85 matrix dimension and number of nonzeros.
86
87 FUNCTION:
88
89 int readHB_aux_double(const char* filename, const char AuxType, double b[])
90
91 int readHB_newaux_double(const char* filename, const char AuxType, double** b)
92
93 DESCRIPTION:
94
95 This function opens and reads from the specified file auxillary vector(s).
96 The char argument Auxtype determines which type of auxillary vector(s)
97 will be read (if present in the file).
98
99 AuxType = 'F' right-hand-side
100 AuxType = 'G' initial estimate (Guess)
101 AuxType = 'X' eXact solution
102
103 If Nrhs > 1, all of the Nrhs vectors of the given type are read and
104 stored in column-major order in the vector b.
105
106 The "newaux" function allocates a vector to hold the values retrieved.
107 The "mat" function uses a _pre-allocated_ vector to hold the values.
108
109 FUNCTION:
110
111 int writeHB_mat_double(const char* filename, int M, int N,
112 int nz, const int colptr[], const int rowind[],
113 const double val[], int Nrhs, const double rhs[],
114 const double guess[], const double exact[],
115 const char* Title, const char* Key, const char* Type,
116 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
117 const char* Rhstype)
118
119 DESCRIPTION:
120
121 The writeHB_mat_double function opens the named file and writes the specified
122 matrix and optional auxillary vector(s) to that file in Harwell-Boeing
123 format. The format arguments (Ptrfmt,Indfmt,Valfmt, and Rhsfmt) are
124 character strings specifying "Fortran-style" output formats -- as they
125 would appear in a Harwell-Boeing file. They are used to produce output
126 which is as close as possible to what would be produced by Fortran code,
127 but note that "D" and "P" edit descriptors are not supported.
128 If NULL, the following defaults will be used:
129 Ptrfmt = Indfmt = "(8I10)"
130 Valfmt = Rhsfmt = "(4E20.13)"
131
132 -----------------------
133 CHARACTER I/O FUNCTIONS
134 -----------------------
135 FUNCTION:
136
137 int readHB_mat_char(const char* filename, int colptr[], int rowind[],
138 char val[], char* Valfmt)
139 int readHB_newmat_char(const char* filename, int* M, int* N, int* nonzeros,
140 int** colptr, int** rowind, char** val, char** Valfmt)
141
142 DESCRIPTION:
143
144 This function opens and reads the specified file, interpreting its
145 contents as a sparse matrix stored in the Harwell/Boeing standard
146 format. (See readHB_aux_char to read auxillary vectors.)
147 -- Values are interpreted as char strings. --
148 (Used to translate exact values from the file into a new storage format.)
149
150 The "mat" function uses _pre-allocated_ arrays to hold the index and
151 nonzero value information.
152
153 The "newmat" function allocates char arrays to hold the index
154 and nonzero value information, and returns pointers to these arrays
155 along with matrix dimension and number of nonzeros.
156
157 FUNCTION:
158
159 int readHB_aux_char(const char* filename, const char AuxType, char b[])
160 int readHB_newaux_char(const char* filename, const char AuxType, char** b,
161 char** Rhsfmt)
162
163 DESCRIPTION:
164
165 This function opens and reads from the specified file auxillary vector(s).
166 The char argument Auxtype determines which type of auxillary vector(s)
167 will be read (if present in the file).
168
169 AuxType = 'F' right-hand-side
170 AuxType = 'G' initial estimate (Guess)
171 AuxType = 'X' eXact solution
172
173 If Nrhs > 1, all of the Nrhs vectors of the given type are read and
174 stored in column-major order in the vector b.
175
176 The "newaux" function allocates a character array to hold the values
177 retrieved.
178 The "mat" function uses a _pre-allocated_ array to hold the values.
179
180 FUNCTION:
181
182 int writeHB_mat_char(const char* filename, int M, int N,
183 int nz, const int colptr[], const int rowind[],
184 const char val[], int Nrhs, const char rhs[],
185 const char guess[], const char exact[],
186 const char* Title, const char* Key, const char* Type,
187 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
188 const char* Rhstype)
189
190 DESCRIPTION:
191
192 The writeHB_mat_char function opens the named file and writes the specified
193 matrix and optional auxillary vector(s) to that file in Harwell-Boeing
194 format. The format arguments (Ptrfmt,Indfmt,Valfmt, and Rhsfmt) are
195 character strings specifying "Fortran-style" output formats -- as they
196 would appear in a Harwell-Boeing file. Valfmt and Rhsfmt must accurately
197 represent the character representation of the values stored in val[]
198 and rhs[].
199
200 If NULL, the following defaults will be used for the integer vectors:
201 Ptrfmt = Indfmt = "(8I10)"
202 Valfmt = Rhsfmt = "(4E20.13)"
203
204
205*/
206
207/*---------------------------------------------------------------------*/
208/* If zero-based indexing is desired, _SP_base should be set to 0 */
209/* This will cause indices read from H-B files to be decremented by 1 */
210/* and indices written to H-B files to be incremented by 1 */
211/* <<< Standard usage is _SP_base = 1 >>> */
212#ifndef _SP_base
213#define _SP_base 1
214#endif
215/*---------------------------------------------------------------------*/
216
217#include "Tpetra_Util_iohb.h"
218
219#include <cstring>
220#include <cmath>
221#include <cstdlib>
222#include <cctype>
223
224namespace Tpetra::HB {
225
226using ::std::free;
227using ::std::malloc;
228using ::std::size_t;
229
230char* substr(const char* S, const int pos, const int len);
231void upcase(char* S);
232void IOHBTerminate(const char* message);
233
234int readHB_info(const char* filename, int* M, int* N, int* nz, char** Type,
235 int* Nrhs) {
236 /****************************************************************************/
237 /* The readHB_info function opens and reads the header information from */
238 /* the specified Harwell-Boeing file, and reports back the number of rows */
239 /* and columns in the stored matrix (M and N), the number of nonzeros in */
240 /* the matrix (nz), and the number of right-hand-sides stored along with */
241 /* the matrix (Nrhs). */
242 /* */
243 /* For a description of the Harwell Boeing standard, see: */
244 /* Duff, et al., ACM TOMS Vol.15, No.1, March 1989 */
245 /* */
246 /* ---------- */
247 /* **CAVEAT** */
248 /* ---------- */
249 /* ** If the input file does not adhere to the H/B format, the ** */
250 /* ** results will be unpredictable. ** */
251 /* */
252 /****************************************************************************/
253 std::FILE* in_file;
254 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
255 int Nrow, Ncol, Nnzero;
256 char* mat_type;
257 char Title[73], Key[9], Rhstype[4];
258 char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
259
260 mat_type = (char*)malloc(4);
261 if (mat_type == NULL) IOHBTerminate("Insufficient memory for mat_type\n");
262
263 if ((in_file = std::fopen(filename, "r")) == NULL) {
264 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
265 return 0;
266 }
267
268 readHB_header(in_file, Title, Key, mat_type, &Nrow, &Ncol, &Nnzero, Nrhs,
269 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
270 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
271 std::fclose(in_file);
272 *Type = mat_type;
273 *(*Type + 3) = '\0';
274 *M = Nrow;
275 *N = Ncol;
276 *nz = Nnzero;
277 if (Rhscrd == 0) {
278 *Nrhs = 0;
279 }
280
281 /* In verbose mode, print some of the header information: */
282 /*
283 if (verbose == 1)
284 {
285 printf("Reading from Harwell-Boeing file %s (verbose on)...\n",filename);
286 printf(" Title: %s\n",Title);
287 printf(" Key: %s\n",Key);
288 printf(" The stored matrix is %i by %i with %i nonzeros.\n",
289 *M, *N, *nz );
290 printf(" %i right-hand--side(s) stored.\n",*Nrhs);
291 }
292 */
293
294 return 1;
295}
296
297int readHB_header(std::FILE* in_file, char* Title, char* Key, char* Type,
298 int* Nrow, int* Ncol, int* Nnzero, int* Nrhs,
299 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
300 int* Ptrcrd, int* Indcrd, int* Valcrd, int* Rhscrd,
301 char* Rhstype) {
302 /*************************************************************************/
303 /* Read header information from the named H/B file... */
304 /*************************************************************************/
305 int Totcrd, Neltvl, Nrhsix;
306 char line[BUFSIZ];
307
308 /* First line: */
309 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
310 std::fprintf(stderr, "Error: Failed to read from file.\n");
311 return 0;
312 }
313 if (std::sscanf(line, "%*s") < 0)
314 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) first line of HB file.\n");
315 (void)std::sscanf(line, "%72c%8[^\n]", Title, Key);
316 *(Key + 8) = '\0';
317 *(Title + 72) = '\0';
318
319 /* Second line: */
320 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
321 std::fprintf(stderr, "Error: Failed to read from file.\n");
322 return 0;
323 }
324 if (std::sscanf(line, "%*s") < 0)
325 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) second line of HB file.\n");
326 if (std::sscanf(line, "%i", &Totcrd) != 1) Totcrd = 0;
327 if (std::sscanf(line, "%*i%i", Ptrcrd) != 1) *Ptrcrd = 0;
328 if (std::sscanf(line, "%*i%*i%i", Indcrd) != 1) *Indcrd = 0;
329 if (std::sscanf(line, "%*i%*i%*i%i", Valcrd) != 1) *Valcrd = 0;
330 if (std::sscanf(line, "%*i%*i%*i%*i%i", Rhscrd) != 1) *Rhscrd = 0;
331
332 /* Third line: */
333 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
334 std::fprintf(stderr, "Error: Failed to read from file.\n");
335 return 0;
336 }
337 if (std::sscanf(line, "%*s") < 0)
338 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) third line of HB file.\n");
339 *(Type + 3) = '\0';
340 if (std::sscanf(line, "%3c", Type) != 1)
341 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid Type info, line 3 of Harwell-Boeing file.\n");
342 upcase(Type);
343 if (std::sscanf(line, "%*3c%i", Nrow) != 1) *Nrow = 0;
344 if (std::sscanf(line, "%*3c%*i%i", Ncol) != 1) *Ncol = 0;
345 if (std::sscanf(line, "%*3c%*i%*i%i", Nnzero) != 1) *Nnzero = 0;
346 if (std::sscanf(line, "%*3c%*i%*i%*i%i", &Neltvl) != 1) Neltvl = 0;
347
348 /* Fourth line: */
349 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
350 std::fprintf(stderr, "Error: Failed to read from file.\n");
351 return 0;
352 }
353 if (std::sscanf(line, "%*s") < 0)
354 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) fourth line of HB file.\n");
355 if (std::sscanf(line, "%16c", Ptrfmt) != 1)
356 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid format info, line 4 of Harwell-Boeing file.\n");
357 if (std::sscanf(line, "%*16c%16c", Indfmt) != 1)
358 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid format info, line 4 of Harwell-Boeing file.\n");
359 if (std::sscanf(line, "%*16c%*16c%20c", Valfmt) != 1)
360 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid format info, line 4 of Harwell-Boeing file.\n");
361 std::sscanf(line, "%*16c%*16c%*20c%20c", Rhsfmt);
362 *(Ptrfmt + 16) = '\0';
363 *(Indfmt + 16) = '\0';
364 *(Valfmt + 20) = '\0';
365 *(Rhsfmt + 20) = '\0';
366
367 /* (Optional) Fifth line: */
368 if (*Rhscrd != 0) {
369 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
370 std::fprintf(stderr, "Error: Failed to read from file.\n");
371 return 0;
372 }
373 if (std::sscanf(line, "%*s") < 0)
374 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) fifth line of HB file.\n");
375 if (std::sscanf(line, "%3c", Rhstype) != 1)
376 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid RHS type information, line 5 of Harwell-Boeing file.\n");
377 if (std::sscanf(line, "%*3c%i", Nrhs) != 1) *Nrhs = 0;
378 if (std::sscanf(line, "%*3c%*i%i", &Nrhsix) != 1) Nrhsix = 0;
379 }
380 return 1;
381}
382
383int readHB_mat_double(const char* filename, int colptr[], int rowind[],
384 double val[]) {
385 /****************************************************************************/
386 /* This function opens and reads the specified file, interpreting its */
387 /* contents as a sparse matrix stored in the Harwell/Boeing standard */
388 /* format and creating compressed column storage scheme vectors to hold */
389 /* the index and nonzero value information. */
390 /* */
391 /* ---------- */
392 /* **CAVEAT** */
393 /* ---------- */
394 /* Parsing real formats from Fortran is tricky, and this file reader */
395 /* does not claim to be foolproof. It has been tested for cases when */
396 /* the real values are printed consistently and evenly spaced on each */
397 /* line, with Fixed (F), and Exponential (E or D) formats. */
398 /* */
399 /* ** If the input file does not adhere to the H/B format, the ** */
400 /* ** results will be unpredictable. ** */
401 /* */
402 /****************************************************************************/
403 std::FILE* in_file;
404 int i, j, ind, col, offset, count, last, Nrhs;
405 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
406 int Nrow, Ncol, Nnzero, Nentries;
407 int Ptrperline, Ptrwidth, Indperline, Indwidth;
408 int Valperline, Valwidth, Valprec;
409 int Valflag; /* Indicates 'E','D', or 'F' float format */
410 char* ThisElement;
411 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
412 char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
413 char line[BUFSIZ];
414
415 if ((in_file = std::fopen(filename, "r")) == NULL) {
416 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
417 return 0;
418 }
419
420 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
421 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
422 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
423
424 /* Parse the array input formats from Line 3 of HB file */
425 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
426 ParseIfmt(Indfmt, &Indperline, &Indwidth);
427 if (Type[0] != 'P') { /* Skip if pattern only */
428 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
429 }
430
431 /* Read column pointer array: */
432
433 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
434 /* then storage entries are offset by 1 */
435
436 ThisElement = (char*)malloc(Ptrwidth + 1);
437 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
438 *(ThisElement + Ptrwidth) = '\0';
439 count = 0;
440 for (i = 0; i < Ptrcrd; i++) {
441 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
442 std::fprintf(stderr, "Error: Failed to read from file.\n");
443 return 0;
444 }
445 if (std::sscanf(line, "%*s") < 0)
446 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in pointer data region of HB file.\n");
447 col = 0;
448 for (ind = 0; ind < Ptrperline; ind++) {
449 if (count > Ncol) break;
450 std::strncpy(ThisElement, line + col, Ptrwidth);
451 /* ThisElement = substr(line,col,Ptrwidth); */
452 colptr[count] = std::atoi(ThisElement) - offset;
453 count++;
454 col += Ptrwidth;
455 }
456 }
457 free(ThisElement);
458
459 /* Read row index array: */
460
461 ThisElement = (char*)malloc(Indwidth + 1);
462 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
463 *(ThisElement + Indwidth) = '\0';
464 count = 0;
465 for (i = 0; i < Indcrd; i++) {
466 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
467 std::fprintf(stderr, "Error: Failed to read from file.\n");
468 return 0;
469 }
470 if (std::sscanf(line, "%*s") < 0)
471 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in index data region of HB file.\n");
472 col = 0;
473 for (ind = 0; ind < Indperline; ind++) {
474 if (count == Nnzero) break;
475 std::strncpy(ThisElement, line + col, Indwidth);
476 /* ThisElement = substr(line,col,Indwidth); */
477 rowind[count] = std::atoi(ThisElement) - offset;
478 count++;
479 col += Indwidth;
480 }
481 }
482 free(ThisElement);
483
484 /* Read array of values: */
485
486 if (Type[0] != 'P') { /* Skip if pattern only */
487
488 if (Type[0] == 'C')
489 Nentries = 2 * Nnzero;
490 else
491 Nentries = Nnzero;
492
493 ThisElement = (char*)malloc(Valwidth + 2);
494 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
495 *(ThisElement + Valwidth) = '\0';
496 *(ThisElement + Valwidth + 1) = '\0';
497 count = 0;
498 for (i = 0; i < Valcrd; i++) {
499 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
500 std::fprintf(stderr, "Error: Failed to read from file.\n");
501 return 0;
502 }
503 if (std::sscanf(line, "%*s") < 0)
504 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in value data region of HB file.\n");
505 if (Valflag == 'D') {
506 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
507 /* *std::strchr(Valfmt,'D') = 'E'; */
508 }
509 col = 0;
510 for (ind = 0; ind < Valperline; ind++) {
511 if (count == Nentries) break;
512 std::strncpy(ThisElement, line + col, Valwidth);
513 /*ThisElement = substr(line,col,Valwidth);*/
514 if (Valflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
515 /* insert a char prefix for exp */
516 last = std::strlen(ThisElement);
517 for (j = last + 1; j >= 0; j--) {
518 ThisElement[j] = ThisElement[j - 1];
519 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
520 ThisElement[j - 1] = Valflag;
521 break;
522 }
523 }
524 }
525 val[count] = std::atof(ThisElement);
526 count++;
527 col += Valwidth;
528 *(ThisElement + Valwidth) = '\0';
529 *(ThisElement + Valwidth + 1) = '\0';
530 }
531 }
532 free(ThisElement);
533 }
534
535 std::fclose(in_file);
536 return 1;
537}
538
539int readHB_newmat_double(const char* filename, int* M, int* N, int* nonzeros,
540 int** colptr, int** rowind, double** val) {
541 int Nrhs;
542 char* Type;
543
544 if (readHB_info(filename, M, N, nonzeros, &Type, &Nrhs) == 0) {
545 return 0;
546 }
547
548 *colptr = (int*)malloc((*N + 1) * sizeof(int));
549 if (*colptr == NULL) IOHBTerminate("Insufficient memory for colptr.\n");
550 *rowind = (int*)malloc(*nonzeros * sizeof(int));
551 if (*rowind == NULL) IOHBTerminate("Insufficient memory for rowind.\n");
552 if (Type[0] == 'C') {
553 /*
554 std::fprintf(stderr, "Warning: Reading complex data from HB file %s.\n",filename);
555 std::fprintf(stderr, " Real and imaginary parts will be interlaced in val[].\n");
556 */
557 /* Malloc enough space for real AND imaginary parts of val[] */
558 *val = (double*)malloc(*nonzeros * sizeof(double) * 2);
559 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
560 } else {
561 if (Type[0] != 'P') {
562 /* Malloc enough space for real array val[] */
563 *val = (double*)malloc(*nonzeros * sizeof(double));
564 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
565 }
566 } /* No val[] space needed if pattern only */
567 return readHB_mat_double(filename, *colptr, *rowind, *val);
568}
569
570int readHB_aux_double(const char* filename, const char AuxType, double b[]) {
571 /****************************************************************************/
572 /* This function opens and reads the specified file, placing auxillary */
573 /* vector(s) of the given type (if available) in b. */
574 /* Return value is the number of vectors successfully read. */
575 /* */
576 /* AuxType = 'F' full right-hand-side vector(s) */
577 /* AuxType = 'G' initial Guess vector(s) */
578 /* AuxType = 'X' eXact solution vector(s) */
579 /* */
580 /* ---------- */
581 /* **CAVEAT** */
582 /* ---------- */
583 /* Parsing real formats from Fortran is tricky, and this file reader */
584 /* does not claim to be foolproof. It has been tested for cases when */
585 /* the real values are printed consistently and evenly spaced on each */
586 /* line, with Fixed (F), and Exponential (E or D) formats. */
587 /* */
588 /* ** If the input file does not adhere to the H/B format, the ** */
589 /* ** results will be unpredictable. ** */
590 /* */
591 /****************************************************************************/
592 std::FILE* in_file;
593 int i, j, n, maxcol, start, stride, col, last, linel;
594 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
595 int Nrow, Ncol, Nnzero, Nentries;
596 int Nrhs, nvecs, rhsi;
597 int Rhsperline, Rhswidth, Rhsprec;
598 int Rhsflag;
599 char* ThisElement;
600 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
601 char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
602 char line[BUFSIZ];
603
604 if ((in_file = std::fopen(filename, "r")) == NULL) {
605 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
606 return 0;
607 }
608
609 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
610 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
611 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
612
613 if (Nrhs <= 0) {
614 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) when none are present.\n");
615 return 0;
616 }
617 if (Rhstype[0] != 'F') {
618 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) which are not stored in Full form.\n");
619 std::fprintf(stderr, " Rhs must be specified as full. \n");
620 return 0;
621 }
622
623 /* If reading complex data, allow for interleaved real and imaginary values. */
624 if (Type[0] == 'C') {
625 Nentries = 2 * Nrow;
626 } else {
627 Nentries = Nrow;
628 }
629
630 nvecs = 1;
631
632 if (Rhstype[1] == 'G') nvecs++;
633 if (Rhstype[2] == 'X') nvecs++;
634
635 if (AuxType == 'G' && Rhstype[1] != 'G') {
636 std::fprintf(stderr, "Warn: Attempt to read auxillary Guess vector(s) when none are present.\n");
637 return 0;
638 }
639 if (AuxType == 'X' && Rhstype[2] != 'X') {
640 std::fprintf(stderr, "Warn: Attempt to read auxillary eXact solution vector(s) when none are present.\n");
641 return 0;
642 }
643
644 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
645 maxcol = Rhsperline * Rhswidth;
646
647 /* Lines to skip before starting to read RHS values... */
648 n = Ptrcrd + Indcrd + Valcrd;
649
650 for (i = 0; i < n; i++) {
651 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
652 std::fprintf(stderr, "Error: Failed to read from file.\n");
653 return 0;
654 }
655 }
656
657 /* start - number of initial aux vector entries to skip */
658 /* to reach first vector requested */
659 /* stride - number of aux vector entries to skip between */
660 /* requested vectors */
661 if (AuxType == 'F')
662 start = 0;
663 else if (AuxType == 'G')
664 start = Nentries;
665 else
666 start = (nvecs - 1) * Nentries;
667 stride = (nvecs - 1) * Nentries;
668
669 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
670 std::fprintf(stderr, "Error: Failed to read from file.\n");
671 return 0;
672 }
673 linel = std::strchr(line, '\n') - line;
674 col = 0;
675 /* Skip to initial offset */
676
677 for (i = 0; i < start; i++) {
678 if (col >= (maxcol < linel ? maxcol : linel)) {
679 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
680 std::fprintf(stderr, "Error: Failed to read from file.\n");
681 return 0;
682 }
683 linel = std::strchr(line, '\n') - line;
684 col = 0;
685 }
686 col += Rhswidth;
687 }
688 if (Rhsflag == 'D') {
689 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
690 }
691
692 /* Read a vector of desired type, then skip to next */
693 /* repeating to fill Nrhs vectors */
694
695 ThisElement = (char*)malloc(Rhswidth + 1);
696 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
697 *(ThisElement + Rhswidth) = '\0';
698 for (rhsi = 0; rhsi < Nrhs; rhsi++) {
699 for (i = 0; i < Nentries; i++) {
700 if (col >= (maxcol < linel ? maxcol : linel)) {
701 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
702 std::fprintf(stderr, "Error: Failed to read from file.\n");
703 return 0;
704 }
705 linel = std::strchr(line, '\n') - line;
706 if (Rhsflag == 'D') {
707 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
708 }
709 col = 0;
710 }
711 std::strncpy(ThisElement, line + col, Rhswidth);
712 /*ThisElement = substr(line, col, Rhswidth);*/
713 if (Rhsflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
714 /* insert a char prefix for exp */
715 last = std::strlen(ThisElement);
716 for (j = last + 1; j >= 0; j--) {
717 ThisElement[j] = ThisElement[j - 1];
718 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
719 ThisElement[j - 1] = Rhsflag;
720 break;
721 }
722 }
723 }
724 b[i] = std::atof(ThisElement);
725 col += Rhswidth;
726 }
727
728 /* Skip any interleaved Guess/eXact vectors */
729
730 for (i = 0; i < stride; i++) {
731 if (col >= (maxcol < linel ? maxcol : linel)) {
732 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
733 std::fprintf(stderr, "Error: Failed to read from file.\n");
734 return 0;
735 }
736 linel = std::strchr(line, '\n') - line;
737 col = 0;
738 }
739 col += Rhswidth;
740 }
741 }
742 free(ThisElement);
743
744 std::fclose(in_file);
745 return Nrhs;
746}
747
748int readHB_newaux_double(const char* filename, const char AuxType, double** b) {
749 int Nrhs = 0;
750 int M = 0;
751 int N = 0;
752 int nonzeros = 0;
753 char* Type = NULL;
754
755 readHB_info(filename, &M, &N, &nonzeros, &Type, &Nrhs);
756 if (Nrhs <= 0) {
757 std::fprintf(stderr, "Warn: Requested read of aux vector(s) when none are present.\n");
758 return 0;
759 } else {
760 if (Type[0] == 'C') {
761 std::fprintf(stderr, "Warning: Reading complex aux vector(s) from HB file %s.", filename);
762 std::fprintf(stderr, " Real and imaginary parts will be interlaced in b[].");
763 *b = (double*)malloc(M * Nrhs * sizeof(double) * 2);
764 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
765 return readHB_aux_double(filename, AuxType, *b);
766 } else {
767 *b = (double*)malloc(M * Nrhs * sizeof(double));
768 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
769 return readHB_aux_double(filename, AuxType, *b);
770 }
771 }
772}
773
774int writeHB_mat_double(const char* filename, int M, int N,
775 int nz, const int colptr[], const int rowind[],
776 const double val[], int Nrhs, const double rhs[],
777 const double guess[], const double exact[],
778 const char* Title, const char* Key, const char* Type,
779 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
780 const char* Rhstype) {
781 /****************************************************************************/
782 /* The writeHB function opens the named file and writes the specified */
783 /* matrix and optional right-hand-side(s) to that file in Harwell-Boeing */
784 /* format. */
785 /* */
786 /* For a description of the Harwell Boeing standard, see: */
787 /* Duff, et al., ACM TOMS Vol.15, No.1, March 1989 */
788 /* */
789 /****************************************************************************/
790 std::FILE* out_file;
791 int i, j, entry, offset, acount, linemod;
792 int totcrd, ptrcrd, indcrd, valcrd, rhscrd;
793 int nvalentries, nrhsentries;
794 int Ptrperline, Ptrwidth, Indperline, Indwidth;
795 int Rhsperline, Rhswidth, Rhsprec;
796 int Rhsflag;
797 int Valperline, Valwidth, Valprec;
798 int Valflag; /* Indicates 'E','D', or 'F' float format */
799 char pformat[16], iformat[16], vformat[19], rformat[19];
800
801 if (Type[0] == 'C') {
802 nvalentries = 2 * nz;
803 nrhsentries = 2 * M;
804 } else {
805 nvalentries = nz;
806 nrhsentries = M;
807 }
808
809 if (filename != NULL) {
810 if ((out_file = std::fopen(filename, "w")) == NULL) {
811 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
812 return 0;
813 }
814 } else
815 out_file = stdout;
816
817 if (Ptrfmt != NULL) strcpy(Ptrfmt, "(8I10)");
818 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
819 std::sprintf(pformat, "%%%dd", Ptrwidth);
820 ptrcrd = (N + 1) / Ptrperline;
821 if ((N + 1) % Ptrperline != 0) ptrcrd++;
822
823 if (Indfmt == NULL) Indfmt = Ptrfmt;
824 ParseIfmt(Indfmt, &Indperline, &Indwidth);
825 std::sprintf(iformat, "%%%dd", Indwidth);
826 indcrd = nz / Indperline;
827 if (nz % Indperline != 0) indcrd++;
828
829 if (Type[0] != 'P') { /* Skip if pattern only */
830 if (Valfmt != NULL) strcpy(Valfmt, "(4E20.13)");
831 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
832 if (Valflag == 'D') *std::strchr(Valfmt, 'D') = 'E';
833 if (Valflag == 'F')
834 std::sprintf(vformat, "%% %d.%df", Valwidth, Valprec);
835 else
836 std::sprintf(vformat, "%% %d.%dE", Valwidth, Valprec);
837 valcrd = nvalentries / Valperline;
838 if (nvalentries % Valperline != 0) valcrd++;
839 } else
840 valcrd = 0;
841
842 if (Nrhs > 0) {
843 if (Rhsfmt == NULL) Rhsfmt = Valfmt;
844 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
845 if (Rhsflag == 'F')
846 std::sprintf(rformat, "%% %d.%df", Rhswidth, Rhsprec);
847 else
848 std::sprintf(rformat, "%% %d.%dE", Rhswidth, Rhsprec);
849 if (Rhsflag == 'D') *std::strchr(Rhsfmt, 'D') = 'E';
850 rhscrd = nrhsentries / Rhsperline;
851 if (nrhsentries % Rhsperline != 0) rhscrd++;
852 if (Rhstype[1] == 'G') rhscrd += rhscrd;
853 if (Rhstype[2] == 'X') rhscrd += rhscrd;
854 rhscrd *= Nrhs;
855 } else
856 rhscrd = 0;
857
858 totcrd = 4 + ptrcrd + indcrd + valcrd + rhscrd;
859
860 /* Print header information: */
861
862 std::fprintf(out_file, "%-72s%-8s\n%14d%14d%14d%14d%14d\n", Title, Key, totcrd,
863 ptrcrd, indcrd, valcrd, rhscrd);
864 std::fprintf(out_file, "%3s%11s%14d%14d%14d\n", Type, " ", M, N, nz);
865 std::fprintf(out_file, "%-16s%-16s%-20s", Ptrfmt, Indfmt, Valfmt);
866 if (Nrhs != 0) {
867 /* Print Rhsfmt on fourth line and */
868 /* optional fifth header line for auxillary vector information: */
869 std::fprintf(out_file, "%-20s\n%-14s%d\n", Rhsfmt, Rhstype, Nrhs);
870 } else
871 std::fprintf(out_file, "\n");
872
873 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
874 /* then storage entries are offset by 1 */
875
876 /* Print column pointers: */
877 for (i = 0; i < N + 1; i++) {
878 entry = colptr[i] + offset;
879 std::fprintf(out_file, pformat, entry);
880 if ((i + 1) % Ptrperline == 0) std::fprintf(out_file, "\n");
881 }
882
883 if ((N + 1) % Ptrperline != 0) std::fprintf(out_file, "\n");
884
885 /* Print row indices: */
886 for (i = 0; i < nz; i++) {
887 entry = rowind[i] + offset;
888 std::fprintf(out_file, iformat, entry);
889 if ((i + 1) % Indperline == 0) std::fprintf(out_file, "\n");
890 }
891
892 if (nz % Indperline != 0) std::fprintf(out_file, "\n");
893
894 /* Print values: */
895
896 if (Type[0] != 'P') { /* Skip if pattern only */
897
898 for (i = 0; i < nvalentries; i++) {
899 std::fprintf(out_file, vformat, val[i]);
900 if ((i + 1) % Valperline == 0) std::fprintf(out_file, "\n");
901 }
902
903 if (nvalentries % Valperline != 0) std::fprintf(out_file, "\n");
904
905 /* If available, print right hand sides,
906 guess vectors and exact solution vectors: */
907 acount = 1;
908 linemod = 0;
909 if (Nrhs > 0) {
910 for (i = 0; i < Nrhs; i++) {
911 for (j = 0; j < nrhsentries; j++) {
912 std::fprintf(out_file, rformat, rhs[j]);
913 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
914 }
915 if ((acount - 1) % Rhsperline != linemod) {
916 std::fprintf(out_file, "\n");
917 linemod = (acount - 1) % Rhsperline;
918 }
919 rhs += nrhsentries;
920 if (Rhstype[1] == 'G') {
921 for (j = 0; j < nrhsentries; j++) {
922 std::fprintf(out_file, rformat, guess[j]);
923 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
924 }
925 if ((acount - 1) % Rhsperline != linemod) {
926 std::fprintf(out_file, "\n");
927 linemod = (acount - 1) % Rhsperline;
928 }
929 guess += nrhsentries;
930 }
931 if (Rhstype[2] == 'X') {
932 for (j = 0; j < nrhsentries; j++) {
933 std::fprintf(out_file, rformat, exact[j]);
934 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
935 }
936 if ((acount - 1) % Rhsperline != linemod) {
937 std::fprintf(out_file, "\n");
938 linemod = (acount - 1) % Rhsperline;
939 }
940 exact += nrhsentries;
941 }
942 }
943 }
944 }
945
946 if (std::fclose(out_file) != 0) {
947 std::fprintf(stderr, "Error closing file in writeHB_mat_double().\n");
948 return 0;
949 } else
950 return 1;
951}
952
953int readHB_mat_char(const char* filename, int colptr[], int rowind[],
954 char val[], char* Valfmt) {
955 /****************************************************************************/
956 /* This function opens and reads the specified file, interpreting its */
957 /* contents as a sparse matrix stored in the Harwell/Boeing standard */
958 /* format and creating compressed column storage scheme vectors to hold */
959 /* the index and nonzero value information. */
960 /* */
961 /* ---------- */
962 /* **CAVEAT** */
963 /* ---------- */
964 /* Parsing real formats from Fortran is tricky, and this file reader */
965 /* does not claim to be foolproof. It has been tested for cases when */
966 /* the real values are printed consistently and evenly spaced on each */
967 /* line, with Fixed (F), and Exponential (E or D) formats. */
968 /* */
969 /* ** If the input file does not adhere to the H/B format, the ** */
970 /* ** results will be unpredictable. ** */
971 /* */
972 /****************************************************************************/
973 std::FILE* in_file;
974 int i, j, ind, col, offset, count, last;
975 int Nrow, Ncol, Nnzero, Nentries, Nrhs;
976 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
977 int Ptrperline, Ptrwidth, Indperline, Indwidth;
978 int Valperline, Valwidth, Valprec;
979 int Valflag; /* Indicates 'E','D', or 'F' float format */
980 char* ThisElement;
981 char line[BUFSIZ];
982 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
983 char Ptrfmt[17], Indfmt[17], Rhsfmt[21];
984
985 if ((in_file = std::fopen(filename, "r")) == NULL) {
986 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
987 return 0;
988 }
989
990 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
991 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
992 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
993
994 /* Parse the array input formats from Line 3 of HB file */
995 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
996 ParseIfmt(Indfmt, &Indperline, &Indwidth);
997 if (Type[0] != 'P') { /* Skip if pattern only */
998 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
999 if (Valflag == 'D') {
1000 *std::strchr(Valfmt, 'D') = 'E';
1001 }
1002 }
1003
1004 /* Read column pointer array: */
1005
1006 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
1007 /* then storage entries are offset by 1 */
1008
1009 ThisElement = (char*)malloc(Ptrwidth + 1);
1010 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
1011 *(ThisElement + Ptrwidth) = '\0';
1012 count = 0;
1013 for (i = 0; i < Ptrcrd; i++) {
1014 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1015 std::fprintf(stderr, "Error: Failed to read from file.\n");
1016 return 0;
1017 }
1018 if (std::sscanf(line, "%*s") < 0)
1019 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in pointer data region of HB file.\n");
1020 col = 0;
1021 for (ind = 0; ind < Ptrperline; ind++) {
1022 if (count > Ncol) break;
1023 std::strncpy(ThisElement, line + col, Ptrwidth);
1024 /*ThisElement = substr(line,col,Ptrwidth);*/
1025 colptr[count] = std::atoi(ThisElement) - offset;
1026 count++;
1027 col += Ptrwidth;
1028 }
1029 }
1030 free(ThisElement);
1031
1032 /* Read row index array: */
1033
1034 ThisElement = (char*)malloc(Indwidth + 1);
1035 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
1036 *(ThisElement + Indwidth) = '\0';
1037 count = 0;
1038 for (i = 0; i < Indcrd; i++) {
1039 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1040 std::fprintf(stderr, "Error: Failed to read from file.\n");
1041 return 0;
1042 }
1043 if (std::sscanf(line, "%*s") < 0)
1044 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in index data region of HB file.\n");
1045 col = 0;
1046 for (ind = 0; ind < Indperline; ind++) {
1047 if (count == Nnzero) break;
1048 std::strncpy(ThisElement, line + col, Indwidth);
1049 /*ThisElement = substr(line,col,Indwidth);*/
1050 rowind[count] = std::atoi(ThisElement) - offset;
1051 count++;
1052 col += Indwidth;
1053 }
1054 }
1055 free(ThisElement);
1056
1057 /* Read array of values: AS CHARACTERS*/
1058
1059 if (Type[0] != 'P') { /* Skip if pattern only */
1060
1061 if (Type[0] == 'C')
1062 Nentries = 2 * Nnzero;
1063 else
1064 Nentries = Nnzero;
1065
1066 ThisElement = (char*)malloc(Valwidth + 1);
1067 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
1068 *(ThisElement + Valwidth) = '\0';
1069 count = 0;
1070 for (i = 0; i < Valcrd; i++) {
1071 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1072 std::fprintf(stderr, "Error: Failed to read from file.\n");
1073 return 0;
1074 }
1075 if (std::sscanf(line, "%*s") < 0)
1076 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in value data region of HB file.\n");
1077 if (Valflag == 'D') {
1078 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
1079 }
1080 col = 0;
1081 for (ind = 0; ind < Valperline; ind++) {
1082 if (count == Nentries) break;
1083 ThisElement = &val[count * Valwidth];
1084 std::strncpy(ThisElement, line + col, Valwidth);
1085 /*std::strncpy(ThisElement,substr(line,col,Valwidth),Valwidth);*/
1086 if (Valflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
1087 /* insert a char prefix for exp */
1088 last = std::strlen(ThisElement);
1089 for (j = last + 1; j >= 0; j--) {
1090 ThisElement[j] = ThisElement[j - 1];
1091 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
1092 ThisElement[j - 1] = Valflag;
1093 break;
1094 }
1095 }
1096 }
1097 count++;
1098 col += Valwidth;
1099 }
1100 }
1101 }
1102
1103 return 1;
1104}
1105
1106int readHB_newmat_char(const char* filename, int* M, int* N, int* nonzeros, int** colptr,
1107 int** rowind, char** val, char** Valfmt) {
1108 std::FILE* in_file;
1109 int Nrhs;
1110 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
1111 int Valperline, Valwidth, Valprec;
1112 int Valflag; /* Indicates 'E','D', or 'F' float format */
1113 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
1114 char Ptrfmt[17], Indfmt[17], Rhsfmt[21];
1115
1116 if ((in_file = std::fopen(filename, "r")) == NULL) {
1117 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1118 return 0;
1119 }
1120
1121 *Valfmt = (char*)malloc(21 * sizeof(char));
1122 if (*Valfmt == NULL) IOHBTerminate("Insufficient memory for Valfmt.");
1123 readHB_header(in_file, Title, Key, Type, M, N, nonzeros, &Nrhs,
1124 Ptrfmt, Indfmt, (*Valfmt), Rhsfmt,
1125 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
1126 std::fclose(in_file);
1127 ParseRfmt(*Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
1128
1129 *colptr = (int*)malloc((*N + 1) * sizeof(int));
1130 if (*colptr == NULL) IOHBTerminate("Insufficient memory for colptr.\n");
1131 *rowind = (int*)malloc(*nonzeros * sizeof(int));
1132 if (*rowind == NULL) IOHBTerminate("Insufficient memory for rowind.\n");
1133 if (Type[0] == 'C') {
1134 /*
1135 std::fprintf(stderr, "Warning: Reading complex data from HB file %s.\n",filename);
1136 std::fprintf(stderr, " Real and imaginary parts will be interlaced in val[].\n");
1137 */
1138 /* Malloc enough space for real AND imaginary parts of val[] */
1139 *val = (char*)malloc(*nonzeros * Valwidth * sizeof(char) * 2);
1140 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
1141 } else {
1142 if (Type[0] != 'P') {
1143 /* Malloc enough space for real array val[] */
1144 *val = (char*)malloc(*nonzeros * Valwidth * sizeof(char));
1145 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
1146 }
1147 } /* No val[] space needed if pattern only */
1148 return readHB_mat_char(filename, *colptr, *rowind, *val, *Valfmt);
1149}
1150
1151int readHB_aux_char(const char* filename, const char AuxType, char b[]) {
1152 /****************************************************************************/
1153 /* This function opens and reads the specified file, placing auxilary */
1154 /* vector(s) of the given type (if available) in b : */
1155 /* Return value is the number of vectors successfully read. */
1156 /* */
1157 /* AuxType = 'F' full right-hand-side vector(s) */
1158 /* AuxType = 'G' initial Guess vector(s) */
1159 /* AuxType = 'X' eXact solution vector(s) */
1160 /* */
1161 /* ---------- */
1162 /* **CAVEAT** */
1163 /* ---------- */
1164 /* Parsing real formats from Fortran is tricky, and this file reader */
1165 /* does not claim to be foolproof. It has been tested for cases when */
1166 /* the real values are printed consistently and evenly spaced on each */
1167 /* line, with Fixed (F), and Exponential (E or D) formats. */
1168 /* */
1169 /* ** If the input file does not adhere to the H/B format, the ** */
1170 /* ** results will be unpredictable. ** */
1171 /* */
1172 /****************************************************************************/
1173 std::FILE* in_file;
1174 int i, j, n, maxcol, start, stride, col, last, linel, nvecs, rhsi;
1175 int Nrow, Ncol, Nnzero, Nentries, Nrhs;
1176 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
1177 int Rhsperline, Rhswidth, Rhsprec;
1178 int Rhsflag;
1179 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
1180 char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
1181 char line[BUFSIZ];
1182 char* ThisElement;
1183
1184 if ((in_file = std::fopen(filename, "r")) == NULL) {
1185 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1186 return 0;
1187 }
1188
1189 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
1190 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
1191 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
1192
1193 if (Nrhs <= 0) {
1194 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) when none are present.\n");
1195 return 0;
1196 }
1197 if (Rhstype[0] != 'F') {
1198 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) which are not stored in Full form.\n");
1199 std::fprintf(stderr, " Rhs must be specified as full. \n");
1200 return 0;
1201 }
1202
1203 /* If reading complex data, allow for interleaved real and imaginary values. */
1204 if (Type[0] == 'C') {
1205 Nentries = 2 * Nrow;
1206 } else {
1207 Nentries = Nrow;
1208 }
1209
1210 nvecs = 1;
1211
1212 if (Rhstype[1] == 'G') nvecs++;
1213 if (Rhstype[2] == 'X') nvecs++;
1214
1215 if (AuxType == 'G' && Rhstype[1] != 'G') {
1216 std::fprintf(stderr, "Warn: Attempt to read auxillary Guess vector(s) when none are present.\n");
1217 return 0;
1218 }
1219 if (AuxType == 'X' && Rhstype[2] != 'X') {
1220 std::fprintf(stderr, "Warn: Attempt to read auxillary eXact solution vector(s) when none are present.\n");
1221 return 0;
1222 }
1223
1224 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
1225 maxcol = Rhsperline * Rhswidth;
1226
1227 /* Lines to skip before starting to read RHS values... */
1228 n = Ptrcrd + Indcrd + Valcrd;
1229
1230 for (i = 0; i < n; i++) {
1231 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1232 std::fprintf(stderr, "Error: Failed to read from file.\n");
1233 return 0;
1234 }
1235 }
1236
1237 /* start - number of initial aux vector entries to skip */
1238 /* to reach first vector requested */
1239 /* stride - number of aux vector entries to skip between */
1240 /* requested vectors */
1241 if (AuxType == 'F')
1242 start = 0;
1243 else if (AuxType == 'G')
1244 start = Nentries;
1245 else
1246 start = (nvecs - 1) * Nentries;
1247 stride = (nvecs - 1) * Nentries;
1248
1249 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1250 std::fprintf(stderr, "Error: Failed to read from file.\n");
1251 return 0;
1252 }
1253 linel = std::strchr(line, '\n') - line;
1254 if (std::sscanf(line, "%*s") < 0)
1255 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1256 col = 0;
1257 /* Skip to initial offset */
1258
1259 for (i = 0; i < start; i++) {
1260 col += Rhswidth;
1261 if (col >= (maxcol < linel ? maxcol : linel)) {
1262 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1263 std::fprintf(stderr, "Error: Failed to read from file.\n");
1264 return 0;
1265 }
1266 linel = std::strchr(line, '\n') - line;
1267 if (std::sscanf(line, "%*s") < 0)
1268 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1269 col = 0;
1270 }
1271 }
1272
1273 if (Rhsflag == 'D') {
1274 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
1275 }
1276 /* Read a vector of desired type, then skip to next */
1277 /* repeating to fill Nrhs vectors */
1278
1279 for (rhsi = 0; rhsi < Nrhs; rhsi++) {
1280 for (i = 0; i < Nentries; i++) {
1281 if (col >= (maxcol < linel ? maxcol : linel)) {
1282 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1283 std::fprintf(stderr, "Error: Failed to read from file.\n");
1284 return 0;
1285 }
1286 linel = std::strchr(line, '\n') - line;
1287 if (std::sscanf(line, "%*s") < 0)
1288 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1289 if (Rhsflag == 'D') {
1290 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
1291 }
1292 col = 0;
1293 }
1294 ThisElement = &b[i * Rhswidth];
1295 std::strncpy(ThisElement, line + col, Rhswidth);
1296 if (Rhsflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
1297 /* insert a char prefix for exp */
1298 last = std::strlen(ThisElement);
1299 for (j = last + 1; j >= 0; j--) {
1300 ThisElement[j] = ThisElement[j - 1];
1301 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
1302 ThisElement[j - 1] = Rhsflag;
1303 break;
1304 }
1305 }
1306 }
1307 col += Rhswidth;
1308 }
1309 b += Nentries * Rhswidth;
1310
1311 /* Skip any interleaved Guess/eXact vectors */
1312
1313 for (i = 0; i < stride; i++) {
1314 col += Rhswidth;
1315 if (col >= (maxcol < linel ? maxcol : linel)) {
1316 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1317 std::fprintf(stderr, "Error: Failed to read from file.\n");
1318 return 0;
1319 }
1320 linel = std::strchr(line, '\n') - line;
1321 if (std::sscanf(line, "%*s") < 0)
1322 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1323 col = 0;
1324 }
1325 }
1326 }
1327
1328 std::fclose(in_file);
1329 return Nrhs;
1330}
1331
1332int readHB_newaux_char(const char* filename, const char AuxType, char** b, char** Rhsfmt) {
1333 std::FILE* in_file;
1334 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
1335 int Nrow, Ncol, Nnzero, Nrhs;
1336 int Rhsperline, Rhswidth, Rhsprec;
1337 int Rhsflag;
1338 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
1339 char Ptrfmt[17], Indfmt[17], Valfmt[21];
1340
1341 if ((in_file = std::fopen(filename, "r")) == NULL) {
1342 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1343 return 0;
1344 }
1345
1346 *Rhsfmt = (char*)malloc(21 * sizeof(char));
1347 if (*Rhsfmt == NULL) IOHBTerminate("Insufficient memory for Rhsfmt.");
1348 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
1349 Ptrfmt, Indfmt, Valfmt, (*Rhsfmt),
1350 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
1351 std::fclose(in_file);
1352 if (Nrhs == 0) {
1353 std::fprintf(stderr, "Warn: Requested read of aux vector(s) when none are present.\n");
1354 return 0;
1355 } else {
1356 ParseRfmt(*Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
1357 if (Type[0] == 'C') {
1358 std::fprintf(stderr, "Warning: Reading complex aux vector(s) from HB file %s.", filename);
1359 std::fprintf(stderr, " Real and imaginary parts will be interlaced in b[].");
1360 *b = (char*)malloc(Nrow * Nrhs * Rhswidth * sizeof(char) * 2);
1361 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
1362 return readHB_aux_char(filename, AuxType, *b);
1363 } else {
1364 *b = (char*)malloc(Nrow * Nrhs * Rhswidth * sizeof(char));
1365 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
1366 return readHB_aux_char(filename, AuxType, *b);
1367 }
1368 }
1369}
1370
1371int writeHB_mat_char(const char* filename, int M, int N,
1372 int nz, const int colptr[], const int rowind[],
1373 const char val[], int Nrhs, const char rhs[],
1374 const char guess[], const char exact[],
1375 const char* Title, const char* Key, const char* Type,
1376 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
1377 const char* Rhstype) {
1378 /****************************************************************************/
1379 /* The writeHB function opens the named file and writes the specified */
1380 /* matrix and optional right-hand-side(s) to that file in Harwell-Boeing */
1381 /* format. */
1382 /* */
1383 /* For a description of the Harwell Boeing standard, see: */
1384 /* Duff, et al., ACM TOMS Vol.15, No.1, March 1989 */
1385 /* */
1386 /****************************************************************************/
1387 std::FILE* out_file;
1388 int i, j, acount, linemod, entry, offset;
1389 int totcrd, ptrcrd, indcrd, valcrd, rhscrd;
1390 int nvalentries, nrhsentries;
1391 int Ptrperline, Ptrwidth, Indperline, Indwidth;
1392 int Rhsperline, Rhswidth, Rhsprec;
1393 int Rhsflag;
1394 int Valperline, Valwidth, Valprec;
1395 int Valflag; /* Indicates 'E','D', or 'F' float format */
1396 char pformat[16], iformat[16], vformat[19], rformat[19];
1397
1398 if (Type[0] == 'C') {
1399 nvalentries = 2 * nz;
1400 nrhsentries = 2 * M;
1401 } else {
1402 nvalentries = nz;
1403 nrhsentries = M;
1404 }
1405
1406 if (filename != NULL) {
1407 if ((out_file = std::fopen(filename, "w")) == NULL) {
1408 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1409 return 0;
1410 }
1411 } else
1412 out_file = stdout;
1413
1414 if (Ptrfmt != NULL) strcpy(Ptrfmt, "(8I10)");
1415 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
1416 std::sprintf(pformat, "%%%dd", Ptrwidth);
1417
1418 if (Indfmt == NULL) Indfmt = Ptrfmt;
1419 ParseIfmt(Indfmt, &Indperline, &Indwidth);
1420 std::sprintf(iformat, "%%%dd", Indwidth);
1421
1422 if (Type[0] != 'P') { /* Skip if pattern only */
1423 if (Valfmt != NULL) strcpy(Valfmt, "(4E20.13)");
1424 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
1425 std::sprintf(vformat, "%%%ds", Valwidth);
1426 }
1427
1428 ptrcrd = (N + 1) / Ptrperline;
1429 if ((N + 1) % Ptrperline != 0) ptrcrd++;
1430
1431 indcrd = nz / Indperline;
1432 if (nz % Indperline != 0) indcrd++;
1433
1434 valcrd = nvalentries / Valperline;
1435 if (nvalentries % Valperline != 0) valcrd++;
1436
1437 if (Nrhs > 0) {
1438 if (Rhsfmt == NULL) Rhsfmt = Valfmt;
1439 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
1440 std::sprintf(rformat, "%%%ds", Rhswidth);
1441 rhscrd = nrhsentries / Rhsperline;
1442 if (nrhsentries % Rhsperline != 0) rhscrd++;
1443 if (Rhstype[1] == 'G') rhscrd += rhscrd;
1444 if (Rhstype[2] == 'X') rhscrd += rhscrd;
1445 rhscrd *= Nrhs;
1446 } else
1447 rhscrd = 0;
1448
1449 totcrd = 4 + ptrcrd + indcrd + valcrd + rhscrd;
1450
1451 /* Print header information: */
1452
1453 std::fprintf(out_file, "%-72s%-8s\n%14d%14d%14d%14d%14d\n", Title, Key, totcrd,
1454 ptrcrd, indcrd, valcrd, rhscrd);
1455 std::fprintf(out_file, "%3s%11s%14d%14d%14d\n", Type, " ", M, N, nz);
1456 std::fprintf(out_file, "%-16s%-16s%-20s", Ptrfmt, Indfmt, Valfmt);
1457 if (Nrhs != 0) {
1458 /* Print Rhsfmt on fourth line and */
1459 /* optional fifth header line for auxillary vector information: */
1460 std::fprintf(out_file, "%-20s\n%-14s%d\n", Rhsfmt, Rhstype, Nrhs);
1461 } else
1462 std::fprintf(out_file, "\n");
1463
1464 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
1465 /* then storage entries are offset by 1 */
1466
1467 /* Print column pointers: */
1468 for (i = 0; i < N + 1; i++) {
1469 entry = colptr[i] + offset;
1470 std::fprintf(out_file, pformat, entry);
1471 if ((i + 1) % Ptrperline == 0) std::fprintf(out_file, "\n");
1472 }
1473
1474 if ((N + 1) % Ptrperline != 0) std::fprintf(out_file, "\n");
1475
1476 /* Print row indices: */
1477 for (i = 0; i < nz; i++) {
1478 entry = rowind[i] + offset;
1479 std::fprintf(out_file, iformat, entry);
1480 if ((i + 1) % Indperline == 0) std::fprintf(out_file, "\n");
1481 }
1482
1483 if (nz % Indperline != 0) std::fprintf(out_file, "\n");
1484
1485 /* Print values: */
1486
1487 if (Type[0] != 'P') { /* Skip if pattern only */
1488 for (i = 0; i < nvalentries; i++) {
1489 std::fprintf(out_file, vformat, val + i * Valwidth);
1490 if ((i + 1) % Valperline == 0) std::fprintf(out_file, "\n");
1491 }
1492
1493 if (nvalentries % Valperline != 0) std::fprintf(out_file, "\n");
1494
1495 /* Print right hand sides: */
1496 acount = 1;
1497 linemod = 0;
1498 if (Nrhs > 0) {
1499 for (j = 0; j < Nrhs; j++) {
1500 for (i = 0; i < nrhsentries; i++) {
1501 std::fprintf(out_file, rformat, rhs + i * Rhswidth);
1502 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
1503 }
1504 if (acount % Rhsperline != linemod) {
1505 std::fprintf(out_file, "\n");
1506 linemod = (acount - 1) % Rhsperline;
1507 }
1508 if (Rhstype[1] == 'G') {
1509 for (i = 0; i < nrhsentries; i++) {
1510 std::fprintf(out_file, rformat, guess + i * Rhswidth);
1511 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
1512 }
1513 if (acount % Rhsperline != linemod) {
1514 std::fprintf(out_file, "\n");
1515 linemod = (acount - 1) % Rhsperline;
1516 }
1517 }
1518 if (Rhstype[2] == 'X') {
1519 for (i = 0; i < nrhsentries; i++) {
1520 std::fprintf(out_file, rformat, exact + i * Rhswidth);
1521 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
1522 }
1523 if (acount % Rhsperline != linemod) {
1524 std::fprintf(out_file, "\n");
1525 linemod = (acount - 1) % Rhsperline;
1526 }
1527 }
1528 }
1529 }
1530 }
1531
1532 if (std::fclose(out_file) != 0) {
1533 std::fprintf(stderr, "Error closing file in writeHB_mat_char().\n");
1534 return 0;
1535 } else
1536 return 1;
1537}
1538
1539int ParseIfmt(char* fmt, int* perline, int* width) {
1540 /*************************************************/
1541 /* Parse an *integer* format field to determine */
1542 /* width and number of elements per line. */
1543 /*************************************************/
1544 char* tmp;
1545 if (fmt == NULL) {
1546 *perline = 0;
1547 *width = 0;
1548 return 0;
1549 }
1550 upcase(fmt);
1551 tmp = std::strchr(fmt, '(');
1552 tmp = substr(fmt, tmp - fmt + 1, std::strchr(fmt, 'I') - tmp - 1);
1553 *perline = std::atoi(tmp);
1554 if (*perline == 0) *perline = 1;
1555 if (tmp != NULL) free((void*)tmp);
1556 tmp = std::strchr(fmt, 'I');
1557 tmp = substr(fmt, tmp - fmt + 1, std::strchr(fmt, ')') - tmp - 1);
1558 *width = std::atoi(tmp);
1559 if (tmp != NULL) free((void*)tmp);
1560 return *width;
1561}
1562
1563int ParseRfmt(char* fmt, int* perline, int* width, int* prec, int* flag) {
1564 /*************************************************/
1565 /* Parse a *real* format field to determine */
1566 /* width and number of elements per line. */
1567 /* Also sets flag indicating 'E' 'F' 'P' or 'D' */
1568 /* format. */
1569 /*************************************************/
1570 char* tmp;
1571 char* tmp1;
1572 char* tmp2;
1573 char* tmp3;
1574 int len;
1575
1576 if (fmt == NULL) {
1577 *perline = 0;
1578 *width = 0;
1579 flag = NULL;
1580 return 0;
1581 }
1582
1583 upcase(fmt);
1584 if (std::strchr(fmt, '(') != NULL) fmt = std::strchr(fmt, '(');
1585 if (std::strchr(fmt, ')') != NULL) {
1586 tmp2 = std::strchr(fmt, ')');
1587 while (std::strchr(tmp2 + 1, ')') != NULL) {
1588 tmp2 = std::strchr(tmp2 + 1, ')');
1589 }
1590 *(tmp2 + 1) = '\0';
1591 }
1592 if (std::strchr(fmt, 'P') != NULL) /* Remove any scaling factor, which */
1593 { /* affects output only, not input */
1594 if (std::strchr(fmt, '(') != NULL) {
1595 tmp = std::strchr(fmt, 'P');
1596 if (*(++tmp) == ',') tmp++;
1597 tmp3 = std::strchr(fmt, '(') + 1;
1598 len = tmp - tmp3;
1599 tmp2 = tmp3;
1600 while (*(tmp2 + len) != '\0') {
1601 *tmp2 = *(tmp2 + len);
1602 tmp2++;
1603 }
1604 *(std::strchr(fmt, ')') + 1) = '\0';
1605 }
1606 }
1607 if (std::strchr(fmt, 'E') != NULL) {
1608 *flag = 'E';
1609 } else if (std::strchr(fmt, 'D') != NULL) {
1610 *flag = 'D';
1611 } else if (std::strchr(fmt, 'F') != NULL) {
1612 *flag = 'F';
1613 } else {
1614 std::fprintf(stderr, "Real format %s in H/B file not supported.\n", fmt);
1615 return 0;
1616 }
1617 tmp = std::strchr(fmt, '(');
1618 tmp = substr(fmt, tmp - fmt + 1, std::strchr(fmt, *flag) - tmp - 1);
1619 *perline = std::atoi(tmp);
1620 if (*perline == 0) *perline = 1;
1621 if (tmp != NULL) free((void*)tmp);
1622 tmp = std::strchr(fmt, *flag);
1623 if (std::strchr(fmt, '.')) {
1624 tmp1 = substr(fmt, std::strchr(fmt, '.') - fmt + 1, std::strchr(fmt, ')') - std::strchr(fmt, '.') - 1);
1625 *prec = std::atoi(tmp1);
1626 if (tmp1 != NULL) free((void*)tmp1);
1627 tmp1 = substr(fmt, tmp - fmt + 1, std::strchr(fmt, '.') - tmp - 1);
1628 } else {
1629 tmp1 = substr(fmt, tmp - fmt + 1, std::strchr(fmt, ')') - tmp - 1);
1630 }
1631 *width = std::atoi(tmp1);
1632 if (tmp1 != NULL) free((void*)tmp1);
1633 return *width;
1634}
1635
1636char* substr(const char* S, const int pos, const int len) {
1637 int i;
1638 char* SubS;
1639 if ((size_t)pos + len <= std::strlen(S)) {
1640 SubS = (char*)malloc(len + 1);
1641 if (SubS == NULL) IOHBTerminate("Insufficient memory for SubS.");
1642 for (i = 0; i < len; i++) SubS[i] = S[pos + i];
1643 SubS[len] = '\0';
1644 } else {
1645 SubS = NULL;
1646 }
1647 return SubS;
1648}
1649
1650void upcase(char* S) {
1651 /* Convert S to uppercase */
1652 int i, len;
1653 len = ::std::strlen(S);
1654 for (i = 0; i < len; i++)
1655 S[i] = ::std::toupper(S[i]);
1656}
1657
1658void IOHBTerminate(const char* message) {
1659 ::std::fprintf(stderr, "%s", message);
1660 ::std::exit(1);
1661}
1662
1663} // namespace Tpetra::HB
void start()
Start the deep_copy counter.