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 if (std::sscanf(line, "%3c", Type) != 1)
340 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid Type info, line 3 of Harwell-Boeing file.\n");
341 upcase(Type);
342 if (std::sscanf(line, "%*3c%i", Nrow) != 1) *Nrow = 0;
343 if (std::sscanf(line, "%*3c%*i%i", Ncol) != 1) *Ncol = 0;
344 if (std::sscanf(line, "%*3c%*i%*i%i", Nnzero) != 1) *Nnzero = 0;
345 if (std::sscanf(line, "%*3c%*i%*i%*i%i", &Neltvl) != 1) Neltvl = 0;
346
347 /* Fourth line: */
348 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
349 std::fprintf(stderr, "Error: Failed to read from file.\n");
350 return 0;
351 }
352 if (std::sscanf(line, "%*s") < 0)
353 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) fourth line of HB file.\n");
354 if (std::sscanf(line, "%16c", Ptrfmt) != 1)
355 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid format info, line 4 of Harwell-Boeing file.\n");
356 if (std::sscanf(line, "%*16c%16c", Indfmt) != 1)
357 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid format info, line 4 of Harwell-Boeing file.\n");
358 if (std::sscanf(line, "%*16c%*16c%20c", Valfmt) != 1)
359 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid format info, line 4 of Harwell-Boeing file.\n");
360 std::sscanf(line, "%*16c%*16c%*20c%20c", Rhsfmt);
361 *(Ptrfmt + 16) = '\0';
362 *(Indfmt + 16) = '\0';
363 *(Valfmt + 20) = '\0';
364 *(Rhsfmt + 20) = '\0';
365
366 /* (Optional) Fifth line: */
367 if (*Rhscrd != 0) {
368 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
369 std::fprintf(stderr, "Error: Failed to read from file.\n");
370 return 0;
371 }
372 if (std::sscanf(line, "%*s") < 0)
373 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) fifth line of HB file.\n");
374 if (std::sscanf(line, "%3c", Rhstype) != 1)
375 IOHBTerminate("Trilinos_Util_iohb.cpp: Invalid RHS type information, line 5 of Harwell-Boeing file.\n");
376 if (std::sscanf(line, "%*3c%i", Nrhs) != 1) *Nrhs = 0;
377 if (std::sscanf(line, "%*3c%*i%i", &Nrhsix) != 1) Nrhsix = 0;
378 }
379 return 1;
380}
381
382int readHB_mat_double(const char* filename, int colptr[], int rowind[],
383 double val[]) {
384 /****************************************************************************/
385 /* This function opens and reads the specified file, interpreting its */
386 /* contents as a sparse matrix stored in the Harwell/Boeing standard */
387 /* format and creating compressed column storage scheme vectors to hold */
388 /* the index and nonzero value information. */
389 /* */
390 /* ---------- */
391 /* **CAVEAT** */
392 /* ---------- */
393 /* Parsing real formats from Fortran is tricky, and this file reader */
394 /* does not claim to be foolproof. It has been tested for cases when */
395 /* the real values are printed consistently and evenly spaced on each */
396 /* line, with Fixed (F), and Exponential (E or D) formats. */
397 /* */
398 /* ** If the input file does not adhere to the H/B format, the ** */
399 /* ** results will be unpredictable. ** */
400 /* */
401 /****************************************************************************/
402 std::FILE* in_file;
403 int i, j, ind, col, offset, count, last, Nrhs;
404 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
405 int Nrow, Ncol, Nnzero, Nentries;
406 int Ptrperline, Ptrwidth, Indperline, Indwidth;
407 int Valperline, Valwidth, Valprec;
408 int Valflag; /* Indicates 'E','D', or 'F' float format */
409 char* ThisElement;
410 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
411 char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
412 char line[BUFSIZ];
413
414 if ((in_file = std::fopen(filename, "r")) == NULL) {
415 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
416 return 0;
417 }
418
419 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
420 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
421 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
422
423 /* Parse the array input formats from Line 3 of HB file */
424 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
425 ParseIfmt(Indfmt, &Indperline, &Indwidth);
426 if (Type[0] != 'P') { /* Skip if pattern only */
427 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
428 }
429
430 /* Read column pointer array: */
431
432 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
433 /* then storage entries are offset by 1 */
434
435 ThisElement = (char*)malloc(Ptrwidth + 1);
436 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
437 *(ThisElement + Ptrwidth) = '\0';
438 count = 0;
439 for (i = 0; i < Ptrcrd; i++) {
440 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
441 std::fprintf(stderr, "Error: Failed to read from file.\n");
442 return 0;
443 }
444 if (std::sscanf(line, "%*s") < 0)
445 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in pointer data region of HB file.\n");
446 col = 0;
447 for (ind = 0; ind < Ptrperline; ind++) {
448 if (count > Ncol) break;
449 std::strncpy(ThisElement, line + col, Ptrwidth);
450 /* ThisElement = substr(line,col,Ptrwidth); */
451 colptr[count] = std::atoi(ThisElement) - offset;
452 count++;
453 col += Ptrwidth;
454 }
455 }
456 free(ThisElement);
457
458 /* Read row index array: */
459
460 ThisElement = (char*)malloc(Indwidth + 1);
461 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
462 *(ThisElement + Indwidth) = '\0';
463 count = 0;
464 for (i = 0; i < Indcrd; i++) {
465 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
466 std::fprintf(stderr, "Error: Failed to read from file.\n");
467 return 0;
468 }
469 if (std::sscanf(line, "%*s") < 0)
470 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in index data region of HB file.\n");
471 col = 0;
472 for (ind = 0; ind < Indperline; ind++) {
473 if (count == Nnzero) break;
474 std::strncpy(ThisElement, line + col, Indwidth);
475 /* ThisElement = substr(line,col,Indwidth); */
476 rowind[count] = std::atoi(ThisElement) - offset;
477 count++;
478 col += Indwidth;
479 }
480 }
481 free(ThisElement);
482
483 /* Read array of values: */
484
485 if (Type[0] != 'P') { /* Skip if pattern only */
486
487 if (Type[0] == 'C')
488 Nentries = 2 * Nnzero;
489 else
490 Nentries = Nnzero;
491
492 ThisElement = (char*)malloc(Valwidth + 2);
493 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
494 *(ThisElement + Valwidth) = '\0';
495 *(ThisElement + Valwidth + 1) = '\0';
496 count = 0;
497 for (i = 0; i < Valcrd; i++) {
498 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
499 std::fprintf(stderr, "Error: Failed to read from file.\n");
500 return 0;
501 }
502 if (std::sscanf(line, "%*s") < 0)
503 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in value data region of HB file.\n");
504 if (Valflag == 'D') {
505 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
506 /* *std::strchr(Valfmt,'D') = 'E'; */
507 }
508 col = 0;
509 for (ind = 0; ind < Valperline; ind++) {
510 if (count == Nentries) break;
511 std::strncpy(ThisElement, line + col, Valwidth);
512 /*ThisElement = substr(line,col,Valwidth);*/
513 if (Valflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
514 /* insert a char prefix for exp */
515 last = std::strlen(ThisElement);
516 for (j = last + 1; j >= 0; j--) {
517 ThisElement[j] = ThisElement[j - 1];
518 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
519 ThisElement[j - 1] = Valflag;
520 break;
521 }
522 }
523 }
524 val[count] = std::atof(ThisElement);
525 count++;
526 col += Valwidth;
527 *(ThisElement + Valwidth) = '\0';
528 *(ThisElement + Valwidth + 1) = '\0';
529 }
530 }
531 free(ThisElement);
532 }
533
534 std::fclose(in_file);
535 return 1;
536}
537
538int readHB_newmat_double(const char* filename, int* M, int* N, int* nonzeros,
539 int** colptr, int** rowind, double** val) {
540 int Nrhs;
541 char* Type;
542
543 if (readHB_info(filename, M, N, nonzeros, &Type, &Nrhs) == 0) {
544 return 0;
545 }
546
547 *colptr = (int*)malloc((*N + 1) * sizeof(int));
548 if (*colptr == NULL) IOHBTerminate("Insufficient memory for colptr.\n");
549 *rowind = (int*)malloc(*nonzeros * sizeof(int));
550 if (*rowind == NULL) IOHBTerminate("Insufficient memory for rowind.\n");
551 if (Type[0] == 'C') {
552 /*
553 std::fprintf(stderr, "Warning: Reading complex data from HB file %s.\n",filename);
554 std::fprintf(stderr, " Real and imaginary parts will be interlaced in val[].\n");
555 */
556 /* Malloc enough space for real AND imaginary parts of val[] */
557 *val = (double*)malloc(*nonzeros * sizeof(double) * 2);
558 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
559 } else {
560 if (Type[0] != 'P') {
561 /* Malloc enough space for real array val[] */
562 *val = (double*)malloc(*nonzeros * sizeof(double));
563 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
564 }
565 } /* No val[] space needed if pattern only */
566 return readHB_mat_double(filename, *colptr, *rowind, *val);
567}
568
569int readHB_aux_double(const char* filename, const char AuxType, double b[]) {
570 /****************************************************************************/
571 /* This function opens and reads the specified file, placing auxillary */
572 /* vector(s) of the given type (if available) in b. */
573 /* Return value is the number of vectors successfully read. */
574 /* */
575 /* AuxType = 'F' full right-hand-side vector(s) */
576 /* AuxType = 'G' initial Guess vector(s) */
577 /* AuxType = 'X' eXact solution vector(s) */
578 /* */
579 /* ---------- */
580 /* **CAVEAT** */
581 /* ---------- */
582 /* Parsing real formats from Fortran is tricky, and this file reader */
583 /* does not claim to be foolproof. It has been tested for cases when */
584 /* the real values are printed consistently and evenly spaced on each */
585 /* line, with Fixed (F), and Exponential (E or D) formats. */
586 /* */
587 /* ** If the input file does not adhere to the H/B format, the ** */
588 /* ** results will be unpredictable. ** */
589 /* */
590 /****************************************************************************/
591 std::FILE* in_file;
592 int i, j, n, maxcol, start, stride, col, last, linel;
593 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
594 int Nrow, Ncol, Nnzero, Nentries;
595 int Nrhs, nvecs, rhsi;
596 int Rhsperline, Rhswidth, Rhsprec;
597 int Rhsflag;
598 char* ThisElement;
599 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
600 char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
601 char line[BUFSIZ];
602
603 if ((in_file = std::fopen(filename, "r")) == NULL) {
604 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
605 return 0;
606 }
607
608 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
609 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
610 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
611
612 if (Nrhs <= 0) {
613 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) when none are present.\n");
614 return 0;
615 }
616 if (Rhstype[0] != 'F') {
617 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) which are not stored in Full form.\n");
618 std::fprintf(stderr, " Rhs must be specified as full. \n");
619 return 0;
620 }
621
622 /* If reading complex data, allow for interleaved real and imaginary values. */
623 if (Type[0] == 'C') {
624 Nentries = 2 * Nrow;
625 } else {
626 Nentries = Nrow;
627 }
628
629 nvecs = 1;
630
631 if (Rhstype[1] == 'G') nvecs++;
632 if (Rhstype[2] == 'X') nvecs++;
633
634 if (AuxType == 'G' && Rhstype[1] != 'G') {
635 std::fprintf(stderr, "Warn: Attempt to read auxillary Guess vector(s) when none are present.\n");
636 return 0;
637 }
638 if (AuxType == 'X' && Rhstype[2] != 'X') {
639 std::fprintf(stderr, "Warn: Attempt to read auxillary eXact solution vector(s) when none are present.\n");
640 return 0;
641 }
642
643 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
644 maxcol = Rhsperline * Rhswidth;
645
646 /* Lines to skip before starting to read RHS values... */
647 n = Ptrcrd + Indcrd + Valcrd;
648
649 for (i = 0; i < n; i++) {
650 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
651 std::fprintf(stderr, "Error: Failed to read from file.\n");
652 return 0;
653 }
654 }
655
656 /* start - number of initial aux vector entries to skip */
657 /* to reach first vector requested */
658 /* stride - number of aux vector entries to skip between */
659 /* requested vectors */
660 if (AuxType == 'F')
661 start = 0;
662 else if (AuxType == 'G')
663 start = Nentries;
664 else
665 start = (nvecs - 1) * Nentries;
666 stride = (nvecs - 1) * Nentries;
667
668 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
669 std::fprintf(stderr, "Error: Failed to read from file.\n");
670 return 0;
671 }
672 linel = std::strchr(line, '\n') - line;
673 col = 0;
674 /* Skip to initial offset */
675
676 for (i = 0; i < start; i++) {
677 if (col >= (maxcol < linel ? maxcol : linel)) {
678 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
679 std::fprintf(stderr, "Error: Failed to read from file.\n");
680 return 0;
681 }
682 linel = std::strchr(line, '\n') - line;
683 col = 0;
684 }
685 col += Rhswidth;
686 }
687 if (Rhsflag == 'D') {
688 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
689 }
690
691 /* Read a vector of desired type, then skip to next */
692 /* repeating to fill Nrhs vectors */
693
694 ThisElement = (char*)malloc(Rhswidth + 1);
695 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
696 *(ThisElement + Rhswidth) = '\0';
697 for (rhsi = 0; rhsi < Nrhs; rhsi++) {
698 for (i = 0; i < Nentries; i++) {
699 if (col >= (maxcol < linel ? maxcol : linel)) {
700 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
701 std::fprintf(stderr, "Error: Failed to read from file.\n");
702 return 0;
703 }
704 linel = std::strchr(line, '\n') - line;
705 if (Rhsflag == 'D') {
706 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
707 }
708 col = 0;
709 }
710 std::strncpy(ThisElement, line + col, Rhswidth);
711 /*ThisElement = substr(line, col, Rhswidth);*/
712 if (Rhsflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
713 /* insert a char prefix for exp */
714 last = std::strlen(ThisElement);
715 for (j = last + 1; j >= 0; j--) {
716 ThisElement[j] = ThisElement[j - 1];
717 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
718 ThisElement[j - 1] = Rhsflag;
719 break;
720 }
721 }
722 }
723 b[i] = std::atof(ThisElement);
724 col += Rhswidth;
725 }
726
727 /* Skip any interleaved Guess/eXact vectors */
728
729 for (i = 0; i < stride; i++) {
730 if (col >= (maxcol < linel ? maxcol : linel)) {
731 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
732 std::fprintf(stderr, "Error: Failed to read from file.\n");
733 return 0;
734 }
735 linel = std::strchr(line, '\n') - line;
736 col = 0;
737 }
738 col += Rhswidth;
739 }
740 }
741 free(ThisElement);
742
743 std::fclose(in_file);
744 return Nrhs;
745}
746
747int readHB_newaux_double(const char* filename, const char AuxType, double** b) {
748 int Nrhs = 0;
749 int M = 0;
750 int N = 0;
751 int nonzeros = 0;
752 char* Type = NULL;
753
754 readHB_info(filename, &M, &N, &nonzeros, &Type, &Nrhs);
755 if (Nrhs <= 0) {
756 std::fprintf(stderr, "Warn: Requested read of aux vector(s) when none are present.\n");
757 return 0;
758 } else {
759 if (Type[0] == 'C') {
760 std::fprintf(stderr, "Warning: Reading complex aux vector(s) from HB file %s.", filename);
761 std::fprintf(stderr, " Real and imaginary parts will be interlaced in b[].");
762 *b = (double*)malloc(M * Nrhs * sizeof(double) * 2);
763 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
764 return readHB_aux_double(filename, AuxType, *b);
765 } else {
766 *b = (double*)malloc(M * Nrhs * sizeof(double));
767 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
768 return readHB_aux_double(filename, AuxType, *b);
769 }
770 }
771}
772
773int writeHB_mat_double(const char* filename, int M, int N,
774 int nz, const int colptr[], const int rowind[],
775 const double val[], int Nrhs, const double rhs[],
776 const double guess[], const double exact[],
777 const char* Title, const char* Key, const char* Type,
778 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
779 const char* Rhstype) {
780 /****************************************************************************/
781 /* The writeHB function opens the named file and writes the specified */
782 /* matrix and optional right-hand-side(s) to that file in Harwell-Boeing */
783 /* format. */
784 /* */
785 /* For a description of the Harwell Boeing standard, see: */
786 /* Duff, et al., ACM TOMS Vol.15, No.1, March 1989 */
787 /* */
788 /****************************************************************************/
789 std::FILE* out_file;
790 int i, j, entry, offset, acount, linemod;
791 int totcrd, ptrcrd, indcrd, valcrd, rhscrd;
792 int nvalentries, nrhsentries;
793 int Ptrperline, Ptrwidth, Indperline, Indwidth;
794 int Rhsperline, Rhswidth, Rhsprec;
795 int Rhsflag;
796 int Valperline, Valwidth, Valprec;
797 int Valflag; /* Indicates 'E','D', or 'F' float format */
798 char pformat[16], iformat[16], vformat[19], rformat[19];
799
800 if (Type[0] == 'C') {
801 nvalentries = 2 * nz;
802 nrhsentries = 2 * M;
803 } else {
804 nvalentries = nz;
805 nrhsentries = M;
806 }
807
808 if (filename != NULL) {
809 if ((out_file = std::fopen(filename, "w")) == NULL) {
810 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
811 return 0;
812 }
813 } else
814 out_file = stdout;
815
816 if (Ptrfmt != NULL) strcpy(Ptrfmt, "(8I10)");
817 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
818 std::sprintf(pformat, "%%%dd", Ptrwidth);
819 ptrcrd = (N + 1) / Ptrperline;
820 if ((N + 1) % Ptrperline != 0) ptrcrd++;
821
822 if (Indfmt == NULL) Indfmt = Ptrfmt;
823 ParseIfmt(Indfmt, &Indperline, &Indwidth);
824 std::sprintf(iformat, "%%%dd", Indwidth);
825 indcrd = nz / Indperline;
826 if (nz % Indperline != 0) indcrd++;
827
828 if (Type[0] != 'P') { /* Skip if pattern only */
829 if (Valfmt != NULL) strcpy(Valfmt, "(4E20.13)");
830 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
831 if (Valflag == 'D') *std::strchr(Valfmt, 'D') = 'E';
832 if (Valflag == 'F')
833 std::sprintf(vformat, "%% %d.%df", Valwidth, Valprec);
834 else
835 std::sprintf(vformat, "%% %d.%dE", Valwidth, Valprec);
836 valcrd = nvalentries / Valperline;
837 if (nvalentries % Valperline != 0) valcrd++;
838 } else
839 valcrd = 0;
840
841 if (Nrhs > 0) {
842 if (Rhsfmt == NULL) Rhsfmt = Valfmt;
843 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
844 if (Rhsflag == 'F')
845 std::sprintf(rformat, "%% %d.%df", Rhswidth, Rhsprec);
846 else
847 std::sprintf(rformat, "%% %d.%dE", Rhswidth, Rhsprec);
848 if (Rhsflag == 'D') *std::strchr(Rhsfmt, 'D') = 'E';
849 rhscrd = nrhsentries / Rhsperline;
850 if (nrhsentries % Rhsperline != 0) rhscrd++;
851 if (Rhstype[1] == 'G') rhscrd += rhscrd;
852 if (Rhstype[2] == 'X') rhscrd += rhscrd;
853 rhscrd *= Nrhs;
854 } else
855 rhscrd = 0;
856
857 totcrd = 4 + ptrcrd + indcrd + valcrd + rhscrd;
858
859 /* Print header information: */
860
861 std::fprintf(out_file, "%-72s%-8s\n%14d%14d%14d%14d%14d\n", Title, Key, totcrd,
862 ptrcrd, indcrd, valcrd, rhscrd);
863 std::fprintf(out_file, "%3s%11s%14d%14d%14d\n", Type, " ", M, N, nz);
864 std::fprintf(out_file, "%-16s%-16s%-20s", Ptrfmt, Indfmt, Valfmt);
865 if (Nrhs != 0) {
866 /* Print Rhsfmt on fourth line and */
867 /* optional fifth header line for auxillary vector information: */
868 std::fprintf(out_file, "%-20s\n%-14s%d\n", Rhsfmt, Rhstype, Nrhs);
869 } else
870 std::fprintf(out_file, "\n");
871
872 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
873 /* then storage entries are offset by 1 */
874
875 /* Print column pointers: */
876 for (i = 0; i < N + 1; i++) {
877 entry = colptr[i] + offset;
878 std::fprintf(out_file, pformat, entry);
879 if ((i + 1) % Ptrperline == 0) std::fprintf(out_file, "\n");
880 }
881
882 if ((N + 1) % Ptrperline != 0) std::fprintf(out_file, "\n");
883
884 /* Print row indices: */
885 for (i = 0; i < nz; i++) {
886 entry = rowind[i] + offset;
887 std::fprintf(out_file, iformat, entry);
888 if ((i + 1) % Indperline == 0) std::fprintf(out_file, "\n");
889 }
890
891 if (nz % Indperline != 0) std::fprintf(out_file, "\n");
892
893 /* Print values: */
894
895 if (Type[0] != 'P') { /* Skip if pattern only */
896
897 for (i = 0; i < nvalentries; i++) {
898 std::fprintf(out_file, vformat, val[i]);
899 if ((i + 1) % Valperline == 0) std::fprintf(out_file, "\n");
900 }
901
902 if (nvalentries % Valperline != 0) std::fprintf(out_file, "\n");
903
904 /* If available, print right hand sides,
905 guess vectors and exact solution vectors: */
906 acount = 1;
907 linemod = 0;
908 if (Nrhs > 0) {
909 for (i = 0; i < Nrhs; i++) {
910 for (j = 0; j < nrhsentries; j++) {
911 std::fprintf(out_file, rformat, rhs[j]);
912 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
913 }
914 if ((acount - 1) % Rhsperline != linemod) {
915 std::fprintf(out_file, "\n");
916 linemod = (acount - 1) % Rhsperline;
917 }
918 rhs += nrhsentries;
919 if (Rhstype[1] == 'G') {
920 for (j = 0; j < nrhsentries; j++) {
921 std::fprintf(out_file, rformat, guess[j]);
922 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
923 }
924 if ((acount - 1) % Rhsperline != linemod) {
925 std::fprintf(out_file, "\n");
926 linemod = (acount - 1) % Rhsperline;
927 }
928 guess += nrhsentries;
929 }
930 if (Rhstype[2] == 'X') {
931 for (j = 0; j < nrhsentries; j++) {
932 std::fprintf(out_file, rformat, exact[j]);
933 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
934 }
935 if ((acount - 1) % Rhsperline != linemod) {
936 std::fprintf(out_file, "\n");
937 linemod = (acount - 1) % Rhsperline;
938 }
939 exact += nrhsentries;
940 }
941 }
942 }
943 }
944
945 if (std::fclose(out_file) != 0) {
946 std::fprintf(stderr, "Error closing file in writeHB_mat_double().\n");
947 return 0;
948 } else
949 return 1;
950}
951
952int readHB_mat_char(const char* filename, int colptr[], int rowind[],
953 char val[], char* Valfmt) {
954 /****************************************************************************/
955 /* This function opens and reads the specified file, interpreting its */
956 /* contents as a sparse matrix stored in the Harwell/Boeing standard */
957 /* format and creating compressed column storage scheme vectors to hold */
958 /* the index and nonzero value information. */
959 /* */
960 /* ---------- */
961 /* **CAVEAT** */
962 /* ---------- */
963 /* Parsing real formats from Fortran is tricky, and this file reader */
964 /* does not claim to be foolproof. It has been tested for cases when */
965 /* the real values are printed consistently and evenly spaced on each */
966 /* line, with Fixed (F), and Exponential (E or D) formats. */
967 /* */
968 /* ** If the input file does not adhere to the H/B format, the ** */
969 /* ** results will be unpredictable. ** */
970 /* */
971 /****************************************************************************/
972 std::FILE* in_file;
973 int i, j, ind, col, offset, count, last;
974 int Nrow, Ncol, Nnzero, Nentries, Nrhs;
975 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
976 int Ptrperline, Ptrwidth, Indperline, Indwidth;
977 int Valperline, Valwidth, Valprec;
978 int Valflag; /* Indicates 'E','D', or 'F' float format */
979 char* ThisElement;
980 char line[BUFSIZ];
981 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
982 char Ptrfmt[17], Indfmt[17], Rhsfmt[21];
983
984 if ((in_file = std::fopen(filename, "r")) == NULL) {
985 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
986 return 0;
987 }
988
989 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
990 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
991 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
992
993 /* Parse the array input formats from Line 3 of HB file */
994 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
995 ParseIfmt(Indfmt, &Indperline, &Indwidth);
996 if (Type[0] != 'P') { /* Skip if pattern only */
997 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
998 if (Valflag == 'D') {
999 *std::strchr(Valfmt, 'D') = 'E';
1000 }
1001 }
1002
1003 /* Read column pointer array: */
1004
1005 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
1006 /* then storage entries are offset by 1 */
1007
1008 ThisElement = (char*)malloc(Ptrwidth + 1);
1009 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
1010 *(ThisElement + Ptrwidth) = '\0';
1011 count = 0;
1012 for (i = 0; i < Ptrcrd; i++) {
1013 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1014 std::fprintf(stderr, "Error: Failed to read from file.\n");
1015 return 0;
1016 }
1017 if (std::sscanf(line, "%*s") < 0)
1018 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in pointer data region of HB file.\n");
1019 col = 0;
1020 for (ind = 0; ind < Ptrperline; ind++) {
1021 if (count > Ncol) break;
1022 std::strncpy(ThisElement, line + col, Ptrwidth);
1023 /*ThisElement = substr(line,col,Ptrwidth);*/
1024 colptr[count] = std::atoi(ThisElement) - offset;
1025 count++;
1026 col += Ptrwidth;
1027 }
1028 }
1029 free(ThisElement);
1030
1031 /* Read row index array: */
1032
1033 ThisElement = (char*)malloc(Indwidth + 1);
1034 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
1035 *(ThisElement + Indwidth) = '\0';
1036 count = 0;
1037 for (i = 0; i < Indcrd; i++) {
1038 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1039 std::fprintf(stderr, "Error: Failed to read from file.\n");
1040 return 0;
1041 }
1042 if (std::sscanf(line, "%*s") < 0)
1043 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in index data region of HB file.\n");
1044 col = 0;
1045 for (ind = 0; ind < Indperline; ind++) {
1046 if (count == Nnzero) break;
1047 std::strncpy(ThisElement, line + col, Indwidth);
1048 /*ThisElement = substr(line,col,Indwidth);*/
1049 rowind[count] = std::atoi(ThisElement) - offset;
1050 count++;
1051 col += Indwidth;
1052 }
1053 }
1054 free(ThisElement);
1055
1056 /* Read array of values: AS CHARACTERS*/
1057
1058 if (Type[0] != 'P') { /* Skip if pattern only */
1059
1060 if (Type[0] == 'C')
1061 Nentries = 2 * Nnzero;
1062 else
1063 Nentries = Nnzero;
1064
1065 ThisElement = (char*)malloc(Valwidth + 1);
1066 if (ThisElement == NULL) IOHBTerminate("Insufficient memory for ThisElement.");
1067 *(ThisElement + Valwidth) = '\0';
1068 count = 0;
1069 for (i = 0; i < Valcrd; i++) {
1070 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1071 std::fprintf(stderr, "Error: Failed to read from file.\n");
1072 return 0;
1073 }
1074 if (std::sscanf(line, "%*s") < 0)
1075 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in value data region of HB file.\n");
1076 if (Valflag == 'D') {
1077 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
1078 }
1079 col = 0;
1080 for (ind = 0; ind < Valperline; ind++) {
1081 if (count == Nentries) break;
1082 ThisElement = &val[count * Valwidth];
1083 std::strncpy(ThisElement, line + col, Valwidth);
1084 /*std::strncpy(ThisElement,substr(line,col,Valwidth),Valwidth);*/
1085 if (Valflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
1086 /* insert a char prefix for exp */
1087 last = std::strlen(ThisElement);
1088 for (j = last + 1; j >= 0; j--) {
1089 ThisElement[j] = ThisElement[j - 1];
1090 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
1091 ThisElement[j - 1] = Valflag;
1092 break;
1093 }
1094 }
1095 }
1096 count++;
1097 col += Valwidth;
1098 }
1099 }
1100 }
1101
1102 return 1;
1103}
1104
1105int readHB_newmat_char(const char* filename, int* M, int* N, int* nonzeros, int** colptr,
1106 int** rowind, char** val, char** Valfmt) {
1107 std::FILE* in_file;
1108 int Nrhs;
1109 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
1110 int Valperline, Valwidth, Valprec;
1111 int Valflag; /* Indicates 'E','D', or 'F' float format */
1112 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
1113 char Ptrfmt[17], Indfmt[17], Rhsfmt[21];
1114
1115 if ((in_file = std::fopen(filename, "r")) == NULL) {
1116 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1117 return 0;
1118 }
1119
1120 *Valfmt = (char*)malloc(21 * sizeof(char));
1121 if (*Valfmt == NULL) IOHBTerminate("Insufficient memory for Valfmt.");
1122 readHB_header(in_file, Title, Key, Type, M, N, nonzeros, &Nrhs,
1123 Ptrfmt, Indfmt, (*Valfmt), Rhsfmt,
1124 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
1125 std::fclose(in_file);
1126 ParseRfmt(*Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
1127
1128 *colptr = (int*)malloc((*N + 1) * sizeof(int));
1129 if (*colptr == NULL) IOHBTerminate("Insufficient memory for colptr.\n");
1130 *rowind = (int*)malloc(*nonzeros * sizeof(int));
1131 if (*rowind == NULL) IOHBTerminate("Insufficient memory for rowind.\n");
1132 if (Type[0] == 'C') {
1133 /*
1134 std::fprintf(stderr, "Warning: Reading complex data from HB file %s.\n",filename);
1135 std::fprintf(stderr, " Real and imaginary parts will be interlaced in val[].\n");
1136 */
1137 /* Malloc enough space for real AND imaginary parts of val[] */
1138 *val = (char*)malloc(*nonzeros * Valwidth * sizeof(char) * 2);
1139 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
1140 } else {
1141 if (Type[0] != 'P') {
1142 /* Malloc enough space for real array val[] */
1143 *val = (char*)malloc(*nonzeros * Valwidth * sizeof(char));
1144 if (*val == NULL) IOHBTerminate("Insufficient memory for val.\n");
1145 }
1146 } /* No val[] space needed if pattern only */
1147 return readHB_mat_char(filename, *colptr, *rowind, *val, *Valfmt);
1148}
1149
1150int readHB_aux_char(const char* filename, const char AuxType, char b[]) {
1151 /****************************************************************************/
1152 /* This function opens and reads the specified file, placing auxilary */
1153 /* vector(s) of the given type (if available) in b : */
1154 /* Return value is the number of vectors successfully read. */
1155 /* */
1156 /* AuxType = 'F' full right-hand-side vector(s) */
1157 /* AuxType = 'G' initial Guess vector(s) */
1158 /* AuxType = 'X' eXact solution vector(s) */
1159 /* */
1160 /* ---------- */
1161 /* **CAVEAT** */
1162 /* ---------- */
1163 /* Parsing real formats from Fortran is tricky, and this file reader */
1164 /* does not claim to be foolproof. It has been tested for cases when */
1165 /* the real values are printed consistently and evenly spaced on each */
1166 /* line, with Fixed (F), and Exponential (E or D) formats. */
1167 /* */
1168 /* ** If the input file does not adhere to the H/B format, the ** */
1169 /* ** results will be unpredictable. ** */
1170 /* */
1171 /****************************************************************************/
1172 std::FILE* in_file;
1173 int i, j, n, maxcol, start, stride, col, last, linel, nvecs, rhsi;
1174 int Nrow, Ncol, Nnzero, Nentries, Nrhs;
1175 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
1176 int Rhsperline, Rhswidth, Rhsprec;
1177 int Rhsflag;
1178 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
1179 char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
1180 char line[BUFSIZ];
1181 char* ThisElement;
1182
1183 if ((in_file = std::fopen(filename, "r")) == NULL) {
1184 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1185 return 0;
1186 }
1187
1188 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
1189 Ptrfmt, Indfmt, Valfmt, Rhsfmt,
1190 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
1191
1192 if (Nrhs <= 0) {
1193 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) when none are present.\n");
1194 return 0;
1195 }
1196 if (Rhstype[0] != 'F') {
1197 std::fprintf(stderr, "Warn: Attempt to read auxillary vector(s) which are not stored in Full form.\n");
1198 std::fprintf(stderr, " Rhs must be specified as full. \n");
1199 return 0;
1200 }
1201
1202 /* If reading complex data, allow for interleaved real and imaginary values. */
1203 if (Type[0] == 'C') {
1204 Nentries = 2 * Nrow;
1205 } else {
1206 Nentries = Nrow;
1207 }
1208
1209 nvecs = 1;
1210
1211 if (Rhstype[1] == 'G') nvecs++;
1212 if (Rhstype[2] == 'X') nvecs++;
1213
1214 if (AuxType == 'G' && Rhstype[1] != 'G') {
1215 std::fprintf(stderr, "Warn: Attempt to read auxillary Guess vector(s) when none are present.\n");
1216 return 0;
1217 }
1218 if (AuxType == 'X' && Rhstype[2] != 'X') {
1219 std::fprintf(stderr, "Warn: Attempt to read auxillary eXact solution vector(s) when none are present.\n");
1220 return 0;
1221 }
1222
1223 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
1224 maxcol = Rhsperline * Rhswidth;
1225
1226 /* Lines to skip before starting to read RHS values... */
1227 n = Ptrcrd + Indcrd + Valcrd;
1228
1229 for (i = 0; i < n; i++) {
1230 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1231 std::fprintf(stderr, "Error: Failed to read from file.\n");
1232 return 0;
1233 }
1234 }
1235
1236 /* start - number of initial aux vector entries to skip */
1237 /* to reach first vector requested */
1238 /* stride - number of aux vector entries to skip between */
1239 /* requested vectors */
1240 if (AuxType == 'F')
1241 start = 0;
1242 else if (AuxType == 'G')
1243 start = Nentries;
1244 else
1245 start = (nvecs - 1) * Nentries;
1246 stride = (nvecs - 1) * Nentries;
1247
1248 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1249 std::fprintf(stderr, "Error: Failed to read from file.\n");
1250 return 0;
1251 }
1252 linel = std::strchr(line, '\n') - line;
1253 if (std::sscanf(line, "%*s") < 0)
1254 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1255 col = 0;
1256 /* Skip to initial offset */
1257
1258 for (i = 0; i < start; i++) {
1259 col += Rhswidth;
1260 if (col >= (maxcol < linel ? maxcol : linel)) {
1261 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1262 std::fprintf(stderr, "Error: Failed to read from file.\n");
1263 return 0;
1264 }
1265 linel = std::strchr(line, '\n') - line;
1266 if (std::sscanf(line, "%*s") < 0)
1267 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1268 col = 0;
1269 }
1270 }
1271
1272 if (Rhsflag == 'D') {
1273 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
1274 }
1275 /* Read a vector of desired type, then skip to next */
1276 /* repeating to fill Nrhs vectors */
1277
1278 for (rhsi = 0; rhsi < Nrhs; rhsi++) {
1279 for (i = 0; i < Nentries; i++) {
1280 if (col >= (maxcol < linel ? maxcol : linel)) {
1281 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1282 std::fprintf(stderr, "Error: Failed to read from file.\n");
1283 return 0;
1284 }
1285 linel = std::strchr(line, '\n') - line;
1286 if (std::sscanf(line, "%*s") < 0)
1287 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1288 if (Rhsflag == 'D') {
1289 while (std::strchr(line, 'D')) *std::strchr(line, 'D') = 'E';
1290 }
1291 col = 0;
1292 }
1293 ThisElement = &b[i * Rhswidth];
1294 std::strncpy(ThisElement, line + col, Rhswidth);
1295 if (Rhsflag != 'F' && std::strchr(ThisElement, 'E') == NULL) {
1296 /* insert a char prefix for exp */
1297 last = std::strlen(ThisElement);
1298 for (j = last + 1; j >= 0; j--) {
1299 ThisElement[j] = ThisElement[j - 1];
1300 if (ThisElement[j] == '+' || ThisElement[j] == '-') {
1301 ThisElement[j - 1] = Rhsflag;
1302 break;
1303 }
1304 }
1305 }
1306 col += Rhswidth;
1307 }
1308 b += Nentries * Rhswidth;
1309
1310 /* Skip any interleaved Guess/eXact vectors */
1311
1312 for (i = 0; i < stride; i++) {
1313 col += Rhswidth;
1314 if (col >= (maxcol < linel ? maxcol : linel)) {
1315 if (std::fgets(line, BUFSIZ, in_file) == NULL) {
1316 std::fprintf(stderr, "Error: Failed to read from file.\n");
1317 return 0;
1318 }
1319 linel = std::strchr(line, '\n') - line;
1320 if (std::sscanf(line, "%*s") < 0)
1321 IOHBTerminate("Trilinos_Util_iohb.cpp: Null (or blank) line in auxillary vector data region of HB file.\n");
1322 col = 0;
1323 }
1324 }
1325 }
1326
1327 std::fclose(in_file);
1328 return Nrhs;
1329}
1330
1331int readHB_newaux_char(const char* filename, const char AuxType, char** b, char** Rhsfmt) {
1332 std::FILE* in_file;
1333 int Ptrcrd, Indcrd, Valcrd, Rhscrd;
1334 int Nrow, Ncol, Nnzero, Nrhs;
1335 int Rhsperline, Rhswidth, Rhsprec;
1336 int Rhsflag;
1337 char Title[73], Key[9], Type[4] = "XXX", Rhstype[4];
1338 char Ptrfmt[17], Indfmt[17], Valfmt[21];
1339
1340 if ((in_file = std::fopen(filename, "r")) == NULL) {
1341 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1342 return 0;
1343 }
1344
1345 *Rhsfmt = (char*)malloc(21 * sizeof(char));
1346 if (*Rhsfmt == NULL) IOHBTerminate("Insufficient memory for Rhsfmt.");
1347 readHB_header(in_file, Title, Key, Type, &Nrow, &Ncol, &Nnzero, &Nrhs,
1348 Ptrfmt, Indfmt, Valfmt, (*Rhsfmt),
1349 &Ptrcrd, &Indcrd, &Valcrd, &Rhscrd, Rhstype);
1350 std::fclose(in_file);
1351 if (Nrhs == 0) {
1352 std::fprintf(stderr, "Warn: Requested read of aux vector(s) when none are present.\n");
1353 return 0;
1354 } else {
1355 ParseRfmt(*Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
1356 if (Type[0] == 'C') {
1357 std::fprintf(stderr, "Warning: Reading complex aux vector(s) from HB file %s.", filename);
1358 std::fprintf(stderr, " Real and imaginary parts will be interlaced in b[].");
1359 *b = (char*)malloc(Nrow * Nrhs * Rhswidth * sizeof(char) * 2);
1360 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
1361 return readHB_aux_char(filename, AuxType, *b);
1362 } else {
1363 *b = (char*)malloc(Nrow * Nrhs * Rhswidth * sizeof(char));
1364 if (*b == NULL) IOHBTerminate("Insufficient memory for rhs.\n");
1365 return readHB_aux_char(filename, AuxType, *b);
1366 }
1367 }
1368}
1369
1370int writeHB_mat_char(const char* filename, int M, int N,
1371 int nz, const int colptr[], const int rowind[],
1372 const char val[], int Nrhs, const char rhs[],
1373 const char guess[], const char exact[],
1374 const char* Title, const char* Key, const char* Type,
1375 char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt,
1376 const char* Rhstype) {
1377 /****************************************************************************/
1378 /* The writeHB function opens the named file and writes the specified */
1379 /* matrix and optional right-hand-side(s) to that file in Harwell-Boeing */
1380 /* format. */
1381 /* */
1382 /* For a description of the Harwell Boeing standard, see: */
1383 /* Duff, et al., ACM TOMS Vol.15, No.1, March 1989 */
1384 /* */
1385 /****************************************************************************/
1386 std::FILE* out_file;
1387 int i, j, acount, linemod, entry, offset;
1388 int totcrd, ptrcrd, indcrd, valcrd, rhscrd;
1389 int nvalentries, nrhsentries;
1390 int Ptrperline, Ptrwidth, Indperline, Indwidth;
1391 int Rhsperline, Rhswidth, Rhsprec;
1392 int Rhsflag;
1393 int Valperline, Valwidth, Valprec;
1394 int Valflag; /* Indicates 'E','D', or 'F' float format */
1395 char pformat[16], iformat[16], vformat[19], rformat[19];
1396
1397 if (Type[0] == 'C') {
1398 nvalentries = 2 * nz;
1399 nrhsentries = 2 * M;
1400 } else {
1401 nvalentries = nz;
1402 nrhsentries = M;
1403 }
1404
1405 if (filename != NULL) {
1406 if ((out_file = std::fopen(filename, "w")) == NULL) {
1407 std::fprintf(stderr, "Error: Cannot open file: %s\n", filename);
1408 return 0;
1409 }
1410 } else
1411 out_file = stdout;
1412
1413 if (Ptrfmt != NULL) strcpy(Ptrfmt, "(8I10)");
1414 ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
1415 std::sprintf(pformat, "%%%dd", Ptrwidth);
1416
1417 if (Indfmt == NULL) Indfmt = Ptrfmt;
1418 ParseIfmt(Indfmt, &Indperline, &Indwidth);
1419 std::sprintf(iformat, "%%%dd", Indwidth);
1420
1421 if (Type[0] != 'P') { /* Skip if pattern only */
1422 if (Valfmt != NULL) strcpy(Valfmt, "(4E20.13)");
1423 ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
1424 std::sprintf(vformat, "%%%ds", Valwidth);
1425 }
1426
1427 ptrcrd = (N + 1) / Ptrperline;
1428 if ((N + 1) % Ptrperline != 0) ptrcrd++;
1429
1430 indcrd = nz / Indperline;
1431 if (nz % Indperline != 0) indcrd++;
1432
1433 valcrd = nvalentries / Valperline;
1434 if (nvalentries % Valperline != 0) valcrd++;
1435
1436 if (Nrhs > 0) {
1437 if (Rhsfmt == NULL) Rhsfmt = Valfmt;
1438 ParseRfmt(Rhsfmt, &Rhsperline, &Rhswidth, &Rhsprec, &Rhsflag);
1439 std::sprintf(rformat, "%%%ds", Rhswidth);
1440 rhscrd = nrhsentries / Rhsperline;
1441 if (nrhsentries % Rhsperline != 0) rhscrd++;
1442 if (Rhstype[1] == 'G') rhscrd += rhscrd;
1443 if (Rhstype[2] == 'X') rhscrd += rhscrd;
1444 rhscrd *= Nrhs;
1445 } else
1446 rhscrd = 0;
1447
1448 totcrd = 4 + ptrcrd + indcrd + valcrd + rhscrd;
1449
1450 /* Print header information: */
1451
1452 std::fprintf(out_file, "%-72s%-8s\n%14d%14d%14d%14d%14d\n", Title, Key, totcrd,
1453 ptrcrd, indcrd, valcrd, rhscrd);
1454 std::fprintf(out_file, "%3s%11s%14d%14d%14d\n", Type, " ", M, N, nz);
1455 std::fprintf(out_file, "%-16s%-16s%-20s", Ptrfmt, Indfmt, Valfmt);
1456 if (Nrhs != 0) {
1457 /* Print Rhsfmt on fourth line and */
1458 /* optional fifth header line for auxillary vector information: */
1459 std::fprintf(out_file, "%-20s\n%-14s%d\n", Rhsfmt, Rhstype, Nrhs);
1460 } else
1461 std::fprintf(out_file, "\n");
1462
1463 offset = 1 - _SP_base; /* if base 0 storage is declared (via macro definition), */
1464 /* then storage entries are offset by 1 */
1465
1466 /* Print column pointers: */
1467 for (i = 0; i < N + 1; i++) {
1468 entry = colptr[i] + offset;
1469 std::fprintf(out_file, pformat, entry);
1470 if ((i + 1) % Ptrperline == 0) std::fprintf(out_file, "\n");
1471 }
1472
1473 if ((N + 1) % Ptrperline != 0) std::fprintf(out_file, "\n");
1474
1475 /* Print row indices: */
1476 for (i = 0; i < nz; i++) {
1477 entry = rowind[i] + offset;
1478 std::fprintf(out_file, iformat, entry);
1479 if ((i + 1) % Indperline == 0) std::fprintf(out_file, "\n");
1480 }
1481
1482 if (nz % Indperline != 0) std::fprintf(out_file, "\n");
1483
1484 /* Print values: */
1485
1486 if (Type[0] != 'P') { /* Skip if pattern only */
1487 for (i = 0; i < nvalentries; i++) {
1488 std::fprintf(out_file, vformat, val + i * Valwidth);
1489 if ((i + 1) % Valperline == 0) std::fprintf(out_file, "\n");
1490 }
1491
1492 if (nvalentries % Valperline != 0) std::fprintf(out_file, "\n");
1493
1494 /* Print right hand sides: */
1495 acount = 1;
1496 linemod = 0;
1497 if (Nrhs > 0) {
1498 for (j = 0; j < Nrhs; j++) {
1499 for (i = 0; i < nrhsentries; i++) {
1500 std::fprintf(out_file, rformat, rhs + i * Rhswidth);
1501 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
1502 }
1503 if (acount % Rhsperline != linemod) {
1504 std::fprintf(out_file, "\n");
1505 linemod = (acount - 1) % Rhsperline;
1506 }
1507 if (Rhstype[1] == 'G') {
1508 for (i = 0; i < nrhsentries; i++) {
1509 std::fprintf(out_file, rformat, guess + i * Rhswidth);
1510 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
1511 }
1512 if (acount % Rhsperline != linemod) {
1513 std::fprintf(out_file, "\n");
1514 linemod = (acount - 1) % Rhsperline;
1515 }
1516 }
1517 if (Rhstype[2] == 'X') {
1518 for (i = 0; i < nrhsentries; i++) {
1519 std::fprintf(out_file, rformat, exact + i * Rhswidth);
1520 if (acount++ % Rhsperline == linemod) std::fprintf(out_file, "\n");
1521 }
1522 if (acount % Rhsperline != linemod) {
1523 std::fprintf(out_file, "\n");
1524 linemod = (acount - 1) % Rhsperline;
1525 }
1526 }
1527 }
1528 }
1529 }
1530
1531 if (std::fclose(out_file) != 0) {
1532 std::fprintf(stderr, "Error closing file in writeHB_mat_char().\n");
1533 return 0;
1534 } else
1535 return 1;
1536}
1537
1538int ParseIfmt(char* fmt, int* perline, int* width) {
1539 /*************************************************/
1540 /* Parse an *integer* format field to determine */
1541 /* width and number of elements per line. */
1542 /*************************************************/
1543 char* tmp;
1544 if (fmt == NULL) {
1545 *perline = 0;
1546 *width = 0;
1547 return 0;
1548 }
1549 upcase(fmt);
1550 tmp = std::strchr(fmt, '(');
1551 tmp = substr(fmt, tmp - fmt + 1, std::strchr(fmt, 'I') - tmp - 1);
1552 *perline = std::atoi(tmp);
1553 if (*perline == 0) *perline = 1;
1554 if (tmp != NULL) free((void*)tmp);
1555 tmp = std::strchr(fmt, 'I');
1556 tmp = substr(fmt, tmp - fmt + 1, std::strchr(fmt, ')') - tmp - 1);
1557 *width = std::atoi(tmp);
1558 if (tmp != NULL) free((void*)tmp);
1559 return *width;
1560}
1561
1562int ParseRfmt(char* fmt, int* perline, int* width, int* prec, int* flag) {
1563 /*************************************************/
1564 /* Parse a *real* format field to determine */
1565 /* width and number of elements per line. */
1566 /* Also sets flag indicating 'E' 'F' 'P' or 'D' */
1567 /* format. */
1568 /*************************************************/
1569 char* tmp;
1570 char* tmp1;
1571 char* tmp2;
1572 char* tmp3;
1573 int len;
1574
1575 if (fmt == NULL) {
1576 *perline = 0;
1577 *width = 0;
1578 flag = NULL;
1579 return 0;
1580 }
1581
1582 upcase(fmt);
1583 if (std::strchr(fmt, '(') != NULL) fmt = std::strchr(fmt, '(');
1584 if (std::strchr(fmt, ')') != NULL) {
1585 tmp2 = std::strchr(fmt, ')');
1586 while (std::strchr(tmp2 + 1, ')') != NULL) {
1587 tmp2 = std::strchr(tmp2 + 1, ')');
1588 }
1589 *(tmp2 + 1) = '\0';
1590 }
1591 if (std::strchr(fmt, 'P') != NULL) /* Remove any scaling factor, which */
1592 { /* affects output only, not input */
1593 if (std::strchr(fmt, '(') != NULL) {
1594 tmp = std::strchr(fmt, 'P');
1595 if (*(++tmp) == ',') tmp++;
1596 tmp3 = std::strchr(fmt, '(') + 1;
1597 len = tmp - tmp3;
1598 tmp2 = tmp3;
1599 while (*(tmp2 + len) != '\0') {
1600 *tmp2 = *(tmp2 + len);
1601 tmp2++;
1602 }
1603 *(std::strchr(fmt, ')') + 1) = '\0';
1604 }
1605 }
1606 if (std::strchr(fmt, 'E') != NULL) {
1607 *flag = 'E';
1608 } else if (std::strchr(fmt, 'D') != NULL) {
1609 *flag = 'D';
1610 } else if (std::strchr(fmt, 'F') != NULL) {
1611 *flag = 'F';
1612 } else {
1613 std::fprintf(stderr, "Real format %s in H/B file not supported.\n", fmt);
1614 return 0;
1615 }
1616 tmp = std::strchr(fmt, '(');
1617 tmp = substr(fmt, tmp - fmt + 1, std::strchr(fmt, *flag) - tmp - 1);
1618 *perline = std::atoi(tmp);
1619 if (*perline == 0) *perline = 1;
1620 if (tmp != NULL) free((void*)tmp);
1621 tmp = std::strchr(fmt, *flag);
1622 if (std::strchr(fmt, '.')) {
1623 tmp1 = substr(fmt, std::strchr(fmt, '.') - fmt + 1, std::strchr(fmt, ')') - std::strchr(fmt, '.') - 1);
1624 *prec = std::atoi(tmp1);
1625 if (tmp1 != NULL) free((void*)tmp1);
1626 tmp1 = substr(fmt, tmp - fmt + 1, std::strchr(fmt, '.') - tmp - 1);
1627 } else {
1628 tmp1 = substr(fmt, tmp - fmt + 1, std::strchr(fmt, ')') - tmp - 1);
1629 }
1630 *width = std::atoi(tmp1);
1631 if (tmp1 != NULL) free((void*)tmp1);
1632 return *width;
1633}
1634
1635char* substr(const char* S, const int pos, const int len) {
1636 int i;
1637 char* SubS;
1638 if ((size_t)pos + len <= std::strlen(S)) {
1639 SubS = (char*)malloc(len + 1);
1640 if (SubS == NULL) IOHBTerminate("Insufficient memory for SubS.");
1641 for (i = 0; i < len; i++) SubS[i] = S[pos + i];
1642 SubS[len] = '\0';
1643 } else {
1644 SubS = NULL;
1645 }
1646 return SubS;
1647}
1648
1649void upcase(char* S) {
1650 /* Convert S to uppercase */
1651 int i, len;
1652 len = ::std::strlen(S);
1653 for (i = 0; i < len; i++)
1654 S[i] = ::std::toupper(S[i]);
1655}
1656
1657void IOHBTerminate(const char* message) {
1658 ::std::fprintf(stderr, "%s", message);
1659 ::std::exit(1);
1660}
1661
1662} // namespace Tpetra::HB
void start()
Start the deep_copy counter.