1
c=======================================================================
2
c=== RBio/RBread_64 ====================================================
3
c=======================================================================
5
c RBio: a MATLAB toolbox for reading and writing sparse matrices in
6
c Rutherford/Boeing format.
7
c Copyright (c) 2007, Timothy A. Davis, Univ. of Florida
10
c-----------------------------------------------------------------------
11
c RBheader: read Rutherford/Boeing header lines
12
c-----------------------------------------------------------------------
14
c Rutherford/Boeing file type is a 3-character string:
16
c (1) R: real, C: complex, P: pattern only, I: integer
17
c mkind: R: 0, P: 1, C: 2, I: 3
19
c (2) S: symmetric, U: unsymmetric, H: Hermitian, Z: skew symmetric,
21
c skind: R: -1, U: 0, S: 1, H: 2, Z: 3
23
c (3) A: assembled, E: element form
24
c nelnz = 0 for A, number of elements for E
26
c pattern matrices are given numerical values of 1 (except PZA).
27
c PZA matrices have +1 in the lower triangular part and -1 in
28
c the upper triangular part.
30
c The matrix is nrow-by-ncol with nnz entries.
31
c For symmetric matrices, Ai and Ax are of size 2*nnz (the upper
32
c triangular part is constructed). To skip this construction,
33
c pass skind = 0 to RBpattern.
34
c-----------------------------------------------------------------------
36
subroutine RBheader (title, key, mtype, nrow, ncol, nnz,
37
$ ptrfmt, indfmt, valfmt, mkind, cmplex, skind, nelnz, info)
40
$ nrow, ncol, nnz, totcrd, ptrcrd, nelnz,
41
$ indcrd, valcrd, mkind, skind, info
43
character title*72, key*8, mtype*3, ptrfmt*16, indfmt*16,
47
c ----------------------------------------------------------------
48
c read header lines 1-4
49
c ----------------------------------------------------------------
51
read (7, 10, err = 91, end = 91)
53
$ totcrd, ptrcrd, indcrd, valcrd,
54
$ mtype, nrow, ncol, nnz, nelnz,
55
$ ptrfmt, indfmt, valfmt
56
10 format (a72, a8 / 4i14 / a3, 11x, 4i14 / 2a16, a20)
58
if (nrow .lt. 0 .or. ncol .lt. 0 .or. nnz .lt. 0) then
59
c error: invalid matrix dimensions
64
c ----------------------------------------------------------------
65
c skip the Harwell/Boeing header line 5, if present
66
c ----------------------------------------------------------------
68
read (7, 20, err = 91, end = 91) rhstyp
70
if ((rhstyp (1:1) .eq. 'F' .or. rhstyp (1:1) .eq. 'f' .or.
71
$ rhstyp (1:1) .eq. 'M' .or. rhstyp (1:1) .eq. 'm')) then
72
c This is the 5th line Harwell/Boeing format. Ignore it.
73
call mexErrMsgTxt ('Harwell/Boeing RHS ignored')
75
c Backspace one record, since we just read in one row of
76
c the column pointers.
80
c ----------------------------------------------------------------
81
c determine if real, pattern, integer, or complex
82
c ----------------------------------------------------------------
84
if (mtype (1:1) .eq. 'R' .or. mtype (1:1) .eq. 'r') then
90
elseif (mtype (1:1) .eq. 'P' .or. mtype (1:1) .eq. 'p') then
96
elseif (mtype (1:1) .eq. 'C' .or. mtype (1:1) .eq. 'c') then
102
elseif (mtype (1:1) .eq. 'I' .or. mtype (1:1) .eq. 'i') then
110
c error: invalid matrix type
116
c ----------------------------------------------------------------
117
c determine if the upper part must be constructed
118
c ----------------------------------------------------------------
120
if (mtype (2:2) .eq. 'R' .or. mtype (2:2) .eq. 'r') then
122
c rectangular: RRA, PRA, IRA, and CRA matrices
125
elseif (mtype (2:2) .eq. 'U' .or. mtype (2:2) .eq. 'u') then
127
c unsymmetric: RUA, PUA, IUA, and CUA matrices
130
elseif (mtype (2:2) .eq. 'S' .or. mtype (2:2) .eq. 's') then
132
c symmetric: RSA, PSA, ISA, and CSA matrices
135
elseif (mtype (2:2) .eq. 'H' .or. mtype (2:2) .eq. 'h') then
137
c Hermitian: CHA (PHA, IHA, and RHA are valid, but atypical)
140
elseif (mtype (2:2) .eq. 'Z' .or. mtype (2:2) .eq. 'z') then
142
c skew symmetric: RZA, PZA, IZA, and CZA
147
c error: invalid matrix type
153
c ----------------------------------------------------------------
154
c assembled matrices or elemental matrices (**A, **E)
155
c ----------------------------------------------------------------
157
if (mtype (3:3) .eq. 'A' .or. mtype (3:3) .eq. 'a') then
159
c assembled - ignore nelnz
163
elseif (mtype (3:3) .eq. 'E' .or. mtype (3:3) .eq. 'e') then
171
c error: invalid matrix type
177
c ----------------------------------------------------------------
178
c assembled matrices must be square if skind is not R
179
c ----------------------------------------------------------------
181
if (.not. fem .and. skind .ne. -1 .and. nrow .ne. ncol) then
183
c error: invalid matrix dimensions
189
c ----------------------------------------------------------------
191
c ----------------------------------------------------------------
196
c ----------------------------------------------------------------
198
c ----------------------------------------------------------------
205
c-----------------------------------------------------------------------
206
c RBpattern: read the column pointers and row indices
207
c-----------------------------------------------------------------------
209
c w and cp are both of size ncol+1 (undefined on input).
211
c The matrix is contained in Ap, Ai, and Ax on output (undefined on
212
c input). It has nzeros explicit zero entries. cp (1..ncol+1) are
213
c the column pointers for the matrix Z that will contain all the
214
c explicit zero entries. Ax is not read in (see RBrread and
217
c info is returned as:
219
c -1 invalid column pointers
220
c -2 row index out of range
222
c -4 entries in upper triangular part of symmetric matrix
223
c -5 invalid matrix type
224
c -6 invalid dimensions
225
c -7 matrix contains unsorted columns
226
c -91 error reading file (header)
227
c -92 error reading file (column pointers)
228
c -93 error reading file (row indices)
229
c -94 error reading file (numerical values: A, or sparse b)
230
c-----------------------------------------------------------------------
232
subroutine RBpattern (ptrfmt, indfmt, nrow, ncol, nnz, skind,
233
$ Ap, Ai, w, cp, info, nw)
235
$ nrow, ncol, nnz, skind, info, Ap (ncol+1), Ai (nnz),
236
$ nw, w (nw), cp (ncol+1)
237
character ptrfmt*16, indfmt*16
241
c ----------------------------------------------------------------
242
c read the pointers and check them
243
c ----------------------------------------------------------------
245
call RBiread (ptrfmt, ncol+1, Ap, info)
246
if (info .lt. 0) then
250
if (Ap (1) .ne. 1 .or. Ap (ncol+1) - 1 .ne. nnz) then
251
c error: invalid matrix (col pointers)
256
if (Ap (j) .lt. Ap (j-1)) then
257
c error: invalid matrix (col pointers)
263
c ----------------------------------------------------------------
264
c read the row indices and check them
265
c ----------------------------------------------------------------
267
call RBiread (indfmt, nnz, Ai, info)
268
if (info .lt. 0) then
279
do 30 p = Ap (j), Ap (j+1) - 1
281
if (i .lt. 1 .or. i .gt. nrow) then
282
c error: row index out of range
283
c print *, 'column j, rows!', j, i, nrow
287
if (w (i) .eq. j) then
288
c error: duplicate entry in matrix
289
c print *, 'column j, duplicate!', j, i
294
if (i .lt. ilast) then
295
c error: matrix contains unsorted columns
296
c print *, 'column j, unsorted!', j, i, ilast
304
c ----------------------------------------------------------------
305
c construct new column pointers for symmetric matrices
306
c ----------------------------------------------------------------
308
if (skind .gt. 0) then
310
c ------------------------------------------------------------
311
c compute the column counts for the whole matrix
312
c ------------------------------------------------------------
319
do 60 p = Ap (j), Ap (j+1)-1
322
c diagonal entry, only appears as A(j,j)
324
elseif (i .gt. j) then
325
c entry in lower triangular part, A(i,j) will be
326
c duplicated as A(j,i), so count it in both cols
330
c error: entry in upper triangular part
337
c ------------------------------------------------------------
338
c compute the new column pointers
339
c ------------------------------------------------------------
343
cp (j) = cp (j-1) + w (j-1)
348
c ----------------------------------------------------------------
350
c ----------------------------------------------------------------
357
c-----------------------------------------------------------------------
358
c RBmangle: convert 1-based matrix into 0-based
359
c-----------------------------------------------------------------------
361
subroutine RBmangle (ncol, Ap, Ai, nnz)
363
$ ncol, nnz, p, j, Ap (ncol+1), Ai (*)
364
nnz = Ap (ncol + 1) - 1
376
c-----------------------------------------------------------------------
378
subroutine RBiread (ifmt, n, I, info)
383
read (7, ifmt, err = 92, end = 92) (I (p), p = 1, n)
389
c-----------------------------------------------------------------------
391
subroutine RBxread (xfmt, n, X, info)
394
double precision X (n)
397
read (7, xfmt, err = 94, end = 94) (X (p), p = 1, n)
404
c-----------------------------------------------------------------------
405
c RBerr: report an error to MATLAB
406
c-----------------------------------------------------------------------
408
c info = 0 is OK, info < 0 is a fatal error, info > 0 is a warning
410
subroutine RBerr (info)
414
if (info .eq. -7) then
415
call mexErrMsgTxt ('matrix contains unsorted columns')
417
elseif (info .eq. -1) then
418
call mexErrMsgTxt ('invalid matrix (col pointers)')
420
elseif (info .eq. -2) then
421
call mexErrMsgTxt ('row index out of range)')
423
elseif (info .eq. -3) then
424
call mexErrMsgTxt ('duplicate entry in matrix')
426
elseif (info .eq. -4) then
427
call mexErrMsgTxt ('invalid symmetric matrix')
429
elseif (info .eq. -5) then
430
call mexErrMsgTxt ('invalid matrix type')
432
elseif (info .eq. -6) then
433
call mexErrMsgTxt ('invalid matrix dimensions')
435
elseif (info .eq. -911) then
436
call mexErrMsgTxt ('finite-element form not supported')
438
elseif (info .eq. -91) then
439
call mexErrMsgTxt ('error reading file (header)')
441
elseif (info .eq. -92) then
442
call mexErrMsgTxt ('error reading file (column pointers)')
444
elseif (info .eq. -93) then
445
call mexErrMsgTxt ('error reading file (row indices)')
447
elseif (info .eq. -94) then
448
call mexErrMsgTxt ('error reading file (numerical values)')
450
elseif (info .eq. -95) then
451
call mexErrMsgTxt ('error reading file (right-hand-side)')
453
elseif (info .lt. 0) then
455
call mexErrMsgTxt ('error (unspecified)')
457
elseif (info .gt. 0) then
459
call mexErrMsgTxt ('warning (unspecified)')