1
c=======================================================================
2
c=== RBio/RBread =======================================================
3
c=======================================================================
5
c RBio: a MATLAB toolbox for reading and writing sparse matrices in
6
c Rutherford/Boeing format.
7
c Copyright (c) 2006, Timothy A. Davis, Univ. Florida. Version 1.0.
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, cmplex, info
42
character title*72, key*8, mtype*3, ptrfmt*16, indfmt*16,
46
c ----------------------------------------------------------------
47
c read header lines 1-4
48
c ----------------------------------------------------------------
50
read (7, 10, err = 91, end = 91)
52
$ totcrd, ptrcrd, indcrd, valcrd,
53
$ mtype, nrow, ncol, nnz, nelnz,
54
$ ptrfmt, indfmt, valfmt
55
10 format (a72, a8 / 4i14 / a3, 11x, 4i14 / 2a16, a20)
57
if (nrow .lt. 0 .or. ncol .lt. 0 .or. nnz .lt. 0) then
58
c error: invalid matrix dimensions
63
c ----------------------------------------------------------------
64
c skip the Harwell/Boeing header line 5, if present
65
c ----------------------------------------------------------------
67
read (7, 20, err = 91, end = 91) rhstyp
69
if ((rhstyp (1:1) .eq. 'F' .or. rhstyp (1:1) .eq. 'f' .or.
70
$ rhstyp (1:1) .eq. 'M' .or. rhstyp (1:1) .eq. 'm')) then
71
c This is the 5th line Harwell/Boeing format. Ignore it.
72
call mexErrMsgTxt ('Harwell/Boeing RHS ignored')
74
c Backspace one record, since we just read in one row of
75
c the column pointers.
79
c ----------------------------------------------------------------
80
c determine if real, pattern, integer, or complex
81
c ----------------------------------------------------------------
83
if (mtype (1:1) .eq. 'R' .or. mtype (1:1) .eq. 'r') then
89
elseif (mtype (1:1) .eq. 'P' .or. mtype (1:1) .eq. 'p') then
95
elseif (mtype (1:1) .eq. 'C' .or. mtype (1:1) .eq. 'c') then
101
elseif (mtype (1:1) .eq. 'I' .or. mtype (1:1) .eq. 'i') then
109
c error: invalid matrix type
115
c ----------------------------------------------------------------
116
c determine if the upper part must be constructed
117
c ----------------------------------------------------------------
119
if (mtype (2:2) .eq. 'R' .or. mtype (2:2) .eq. 'r') then
121
c rectangular: RRA, PRA, IRA, and CRA matrices
124
elseif (mtype (2:2) .eq. 'U' .or. mtype (2:2) .eq. 'u') then
126
c unsymmetric: RUA, PUA, IUA, and CUA matrices
129
elseif (mtype (2:2) .eq. 'S' .or. mtype (2:2) .eq. 's') then
131
c symmetric: RSA, PSA, ISA, and CSA matrices
134
elseif (mtype (2:2) .eq. 'H' .or. mtype (2:2) .eq. 'h') then
136
c Hermitian: CHA (PHA, IHA, and RHA are valid, but atypical)
139
elseif (mtype (2:2) .eq. 'Z' .or. mtype (2:2) .eq. 'z') then
141
c skew symmetric: RZA, PZA, IZA, and CZA
146
c error: invalid matrix type
152
c ----------------------------------------------------------------
153
c assembled matrices or elemental matrices (**A, **E)
154
c ----------------------------------------------------------------
156
if (mtype (3:3) .eq. 'A' .or. mtype (3:3) .eq. 'a') then
158
c assembled - ignore nelnz
162
elseif (mtype (3:3) .eq. 'E' .or. mtype (3:3) .eq. 'e') then
170
c error: invalid matrix type
176
c ----------------------------------------------------------------
177
c assembled matrices must be square if skind is not R
178
c ----------------------------------------------------------------
180
if (.not. fem .and. skind .ne. -1 .and. nrow .ne. ncol) then
182
c error: invalid matrix dimensions
188
c ----------------------------------------------------------------
190
c ----------------------------------------------------------------
195
c ----------------------------------------------------------------
197
c ----------------------------------------------------------------
204
c-----------------------------------------------------------------------
205
c RBpattern: read the column pointers and row indices
206
c-----------------------------------------------------------------------
208
c w and cp are both of size ncol+1 (undefined on input).
210
c The matrix is contained in Ap, Ai, and Ax on output (undefined on
211
c input). It has nzeros explicit zero entries. cp (1..ncol+1) are
212
c the column pointers for the matrix Z that will contain all the
213
c explicit zero entries. Ax is not read in (see RBrread and
216
c info is returned as:
218
c -1 invalid column pointers
219
c -2 row index out of range
221
c -4 entries in upper triangular part of symmetric matrix
222
c -5 invalid matrix type
223
c -6 invalid dimensions
224
c -7 matrix contains unsorted columns
225
c -91 error reading file (header)
226
c -92 error reading file (column pointers)
227
c -93 error reading file (row indices)
228
c -94 error reading file (numerical values: A, or sparse b)
229
c-----------------------------------------------------------------------
231
subroutine RBpattern (ptrfmt, indfmt, nrow, ncol, nnz, skind,
232
$ Ap, Ai, w, cp, info, nw)
234
$ nrow, ncol, nnz, skind, info, Ap (ncol+1), Ai (nnz),
235
$ nw, w (nw), cp (ncol+1)
236
character ptrfmt*16, indfmt*16
240
c ----------------------------------------------------------------
241
c read the pointers and check them
242
c ----------------------------------------------------------------
244
call RBiread (ptrfmt, ncol+1, Ap, info)
245
if (info .lt. 0) then
249
if (Ap (1) .ne. 1 .or. Ap (ncol+1) - 1 .ne. nnz) then
250
c error: invalid matrix (col pointers)
255
if (Ap (j) .lt. Ap (j-1)) then
256
c error: invalid matrix (col pointers)
262
c ----------------------------------------------------------------
263
c read the row indices and check them
264
c ----------------------------------------------------------------
266
call RBiread (indfmt, nnz, Ai, info)
267
if (info .lt. 0) then
278
do 30 p = Ap (j), Ap (j+1) - 1
280
if (i .lt. 1 .or. i .gt. nrow) then
281
c error: row index out of range
282
c print *, 'column j, rows!', j, i, nrow
286
if (w (i) .eq. j) then
287
c error: duplicate entry in matrix
288
print *, 'column j, duplicate!', j, i
293
if (i .lt. ilast) then
294
c error: matrix contains unsorted columns
295
print *, 'column j, unsorted!', j, i, ilast
303
c ----------------------------------------------------------------
304
c construct new column pointers for symmetric matrices
305
c ----------------------------------------------------------------
307
if (skind .gt. 0) then
309
c ------------------------------------------------------------
310
c compute the column counts for the whole matrix
311
c ------------------------------------------------------------
318
do 60 p = Ap (j), Ap (j+1)-1
321
c diagonal entry, only appears as A(j,j)
323
elseif (i .gt. j) then
324
c entry in lower triangular part, A(i,j) will be
325
c duplicated as A(j,i), so count it in both cols
329
c error: entry in upper triangular part
331
c print *, 'column j, entries in upper!',j
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)')