1
c=======================================================================
2
c=== RBio/RBwrite_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 RBkind: determine the type of a MATLAB matrix
12
c-----------------------------------------------------------------------
14
c input: a zero-based MATLAB sparse matrix
16
c nrow number of rows of A
17
c ncol number of columns of A
18
c Ap size ncol+1, column pointers
19
c Ai size nnz, row indices (nnz = Ap (ncol+1))
20
c Ax size nnz, real values
21
c Az size nnz, imaginary values (not accessed if A is real)
22
c cmplex 1 if A is complex, 0 otherwise
25
c mkind: r: 0 (real), p: 1 (pattern), c: 2 (complex),
27
c skind: r: -1 (rectangular), u: 0 (unsymmetric), s: 1 symmetric,
28
c h: 2 (Hermitian), z: 3 (skew symmetric)
31
c munch size ncol+1, not defined on input or output
33
c Note that the MATLAB matrix is zero-based (Ap and Ai). 1 must be
34
c added whenever they are used (see "1+" in the code below).
36
c See also SuiteSparse/CHOLMOD/MatrixOps/cholmod_symmetry.c, which
37
c also determines if the diagonal is positive.
38
c-----------------------------------------------------------------------
40
subroutine RBkind (nrow, ncol, Ap, Ai, Ax, Az,
41
$ cmplex, mkind, skind, mtype, nnz, munch, kmin, kmax)
44
$ nrow, ncol, Ap (ncol+1), Ai (*), mkind, skind,
45
$ munch (ncol+1), p, i, j, pt, nnz, k, kmin, kmax
47
double precision Ax (*), Az (*), x_r, x_i, xtr, xti
48
logical is_p, is_s, is_h, is_z, is_int
51
c ----------------------------------------------------------------
52
c determine numeric type (I*A, R*A, P*A, C*A)
53
c ----------------------------------------------------------------
55
c pattern: if real and all entries are 1.
56
c integer: if real and all entries are integers.
57
c complex: if cmplex is 1.
60
nnz = 1+ (Ap (ncol+1) - 1)
64
if (cmplex .eq. 1) then
65
c complex matrix (C*A)
69
c select P** format if all entries are equal to 1
70
c select I** format if all entries are integer and
71
c between -99,999,999 and +999,999,999
78
if (Ax (p) .ne. 1) then
84
if (k .ne. Ax (p)) then
87
if (k .le. -99999999 .or. k .ge. 999999999) then
88
c use real format for really big integers
91
if (.not. is_int .and. .not. is_p) then
97
c pattern-only matrix (P*A)
101
c integer matrix (I*A)
111
c only assembled matrices are handled
114
c ----------------------------------------------------------------
115
c determine symmetry (*RA, *UA, *SA, *HA, *ZA)
116
c ----------------------------------------------------------------
118
c Note that A must have sorted columns for this method to work.
119
c This is not checked, since all MATLAB matrices "should" have
120
c sorted columns. Use spcheck(A) to check for this, if needed.
122
if (nrow .ne. ncol) then
123
c rectangular matrix (*RA), no need to check values or pattern
129
c if complex, the matrix is Hermitian until proven otherwise
130
is_h = (cmplex .eq. 1)
132
c the matrix is symmetric until proven otherwise
135
c a non-pattern matrix is skew symmetric until proven otherwise
136
is_z = (mkind .ne. 1)
138
c if this method returns early, the matrix is unsymmetric
142
c initialize the munch pointers
144
munch (j) = 1+ (Ap (j))
149
c consider all entries not yet munched in column j
150
do 40 p = munch (j), 1+ (Ap (j+1)-1)
155
c entry A(i,j) is unmatched, matrix is unsymmetric
159
c get the A(j,i) entry, if it exists
162
c munch the A(j,i) entry
165
if (pt .ge. 1+ (Ap (i+1))) then
166
c entry A(j,i) doesn't exist, matrix unsymmetric
170
if (1+ (Ai (pt)) .ne. j) then
171
c entry A(j,i) doesn't exist, matrix unsymmetric
175
c A(j,i) exists; check its value with A(i,j)
177
if (cmplex .eq. 1) then
185
if (x_r .ne. xtr .or. x_i .ne. xti) then
186
c the matrix cannot be *SA
189
if (x_r .ne. -xtr .or. x_i .ne. -xti) then
190
c the matrix cannot be *ZA
193
if (x_r .ne. xtr .or. x_i .ne. -xti) then
194
c the matrix cannot be *HA
204
if (x_r .ne. xtr) then
205
c the matrix cannot be *SA
208
if (x_r .ne. -xtr) then
209
c the matrix cannot be *ZA
215
if (.not. (is_s .or. is_z .or. is_h)) then
216
c matrix is unsymmetric; terminate the test
223
c ----------------------------------------------------------------
224
c return the symmetry
225
c ----------------------------------------------------------------
228
c Hermitian matrix (*HA)
232
c symmetric matrix (*SA)
236
c skew symmetric matrix (*ZA)
245
c-----------------------------------------------------------------------
246
c RBformat: determine the format required for an array of values
247
c-----------------------------------------------------------------------
249
c This function ensures that a sufficiently wide format is used that
250
c can accurately represent the data. It also ensures that when printed,
251
c the numerical values all have at least one blank space between them.
252
c This makes it trivial for a program written in C (say) to read in a
253
c matrix generated by RBwrite.
255
c ww, valfmt, valn, and is_int must be defined on input. They
256
c are modified on output.
257
c-----------------------------------------------------------------------
259
subroutine RBformat (nnz, x, ww, valfmt, valn, is_int,
262
$ nnz, i, ww, k, nf (18), valn, nd (9), kmin, kmax
263
double precision x (nnz), e, a, b
265
character*20 f (18), d (9), valfmt
268
c ----------------------------------------------------------------
269
c define all possible formats
270
c ----------------------------------------------------------------
281
f (10) = '(4E18.10) '
282
f (11) = '(4E19.11) '
283
f (12) = '(4E20.12) '
284
f (13) = '(3E21.13) '
285
f (14) = '(3E22.14) '
286
f (15) = '(3E23.15) '
287
f (16) = '(3E24.16) '
288
f (17) = '(3E25.17) '
289
f (18) = '(3E26.18) '
312
c ------------------------------------------------------------
313
c use an integer format
314
c ------------------------------------------------------------
316
call RBiformat (kmin, kmax, valfmt, valn, ww)
320
c ------------------------------------------------------------
321
c determine if the matrix has huge values or NaN's
322
c ------------------------------------------------------------
327
if (a .ne. a .or. a < 1e-90 .or. a > 1e90) then
329
valfmt = '(2E30.18E3) '
336
c ------------------------------------------------------------
337
c find the required precision for a real or complex matrix
338
c ------------------------------------------------------------
343
c write the value to a string, read back in, and check
344
write (unit = s, fmt = f(k)) a
345
read (unit = s, fmt = f(k)) b
355
c valn is the number of entries per line
365
c-----------------------------------------------------------------------
366
c RBwrite: write portions of the matrix to the file
367
c-----------------------------------------------------------------------
369
c task 0: just count the total number of entries in the matrix
370
c task 1: do task 0, and also construct w and cp
371
c task 2: write the row indices
372
c task 3: write the numerical values
374
c Note that the MATLAB arrays A and Z are zero-based. "1+" is added
375
c to each use of Ap, Ai, Zp, and Zi.
376
c-----------------------------------------------------------------------
378
subroutine RBwrite (task, nrow, ncol, skind, cmplex, doZ, Ap,
379
$ Ai, Ax, Az, Zp, Zi, mkind,
380
$ indfmt, indn, valfmt, valn, nnz, w, cp)
383
$ task, nrow, ncol, Ap (*), Ai (*), Zp (*), Zi (*),
384
$ cp (*), w (*), nnz, znz, ibuf (80), j, i, nbuf, pa, pz,
385
$ cmplex, paend, pzend, ia, iz, skind, indn, valn, p, mkind
387
double precision xbuf (80), xr, xi, Ax (*), Az (*)
388
character valfmt*20, indfmt*20
390
c ----------------------------------------------------------------
391
c determine number of entries in Z
392
c ----------------------------------------------------------------
395
znz = 1+ (Zp (ncol+1) - 1)
400
c clear the nonzero counts
406
c start with an empty buffer
411
c ------------------------------------------------------------
413
c ------------------------------------------------------------
417
do 20 pa = 1+ (Ap (j)), 1+ (Ap (j+1) - 1)
421
if (cmplex .eq. 1) then
425
if (skind .le. 0 .or. i .ge. j) then
427
c consider the (i,j) entry with value (xr,xi)
429
if (task .eq. 1) then
430
c only determining nonzero counts
432
elseif (task .eq. 2) then
433
c printing the row indices
434
call RBiprint (indfmt, ibuf, nbuf, i, indn)
435
elseif (task .eq. 3) then
436
c printing the numerical values
437
call RBxprint (valfmt, xbuf, nbuf, xr,
439
if (cmplex .eq. 1) then
440
call RBxprint (valfmt, xbuf, nbuf, xi,
452
c ------------------------------------------------------------
453
c symmetric, unsymmetric or rectangular matrix, with Z present
454
c ------------------------------------------------------------
458
c find the set union of A (:,j) and Z (:,j)
462
paend = 1+ (Ap (j+1) - 1)
463
pzend = 1+ (Zp (j+1) - 1)
465
c while entries appear in A or Z
468
c get the next entry from A(:,j)
469
if (pa .le. paend) then
475
c get the next entry from Z(:,j)
476
if (pz .le. pzend) then
482
c exit loop if neither entry is present
483
if (ia .gt. nrow .and. iz .gt. nrow) goto 80
489
if (cmplex .eq. 1) then
493
else if (iz .lt. ia) then
500
c get A (i,j), and delete its matched Z(i,j)
503
if (cmplex .eq. 1) then
510
if (skind .le. 0 .or. i .ge. j) then
512
c consider the (i,j) entry with value (xr,xi)
514
if (task .eq. 1) then
515
c only determining nonzero counts
517
elseif (task .eq. 2) then
518
c printing the row indices
519
call RBiprint (indfmt, ibuf, nbuf, i, indn)
520
elseif (task .eq. 3) then
521
c printing the numerical values
522
call RBxprint (valfmt, xbuf, nbuf, xr,
524
if (cmplex .eq. 1) then
525
call RBxprint (valfmt, xbuf, nbuf, xi,
541
c ----------------------------------------------------------------
542
c determine the new column pointers, or finish printing
543
c ----------------------------------------------------------------
545
if (task .eq. 1) then
549
cp (j) = cp (j-1) + w (j-1)
552
else if (task .eq. 2) then
554
call RBiflush (indfmt, ibuf, nbuf)
556
elseif (task .eq. 3) then
558
call RBxflush (valfmt, xbuf, nbuf, mkind)
566
c-----------------------------------------------------------------------
567
c RBiprint: print a single integer to the file, flush buffer if needed
568
c-----------------------------------------------------------------------
570
subroutine RBiprint (indfmt, ibuf, nbuf, i, indn)
573
$ ibuf (80), nbuf, i, indn
574
if (nbuf .ge. indn) then
575
call RBiflush (indfmt, ibuf, nbuf)
584
c-----------------------------------------------------------------------
585
c RBiflush: flush the integer buffer to the file
586
c-----------------------------------------------------------------------
588
subroutine RBiflush (indfmt, ibuf, nbuf)
592
write (unit = 7, fmt = indfmt, err = 999) (ibuf (k), k = 1,nbuf)
594
999 call mexErrMsgTxt ('error writing ints')
599
c-----------------------------------------------------------------------
600
c RBxprint: print a single real to the file, flush the buffer if needed
601
c-----------------------------------------------------------------------
603
subroutine RBxprint (valfmt, xbuf, nbuf, x, valn, mkind)
607
double precision xbuf (80), x
608
if (nbuf .ge. valn) then
609
call RBxflush (valfmt, xbuf, nbuf, mkind)
618
c-----------------------------------------------------------------------
619
c RBxflush: flush the real buffer to the file
620
c-----------------------------------------------------------------------
622
subroutine RBxflush (valfmt, xbuf, nbuf, mkind)
625
$ nbuf, k, ibuf (80), mkind
626
double precision xbuf (80)
627
if (mkind .eq. 3) then
628
c convert to integer first; valfmt is (10I8), for example
630
ibuf (k) = dint (xbuf (k))
632
write (unit = 7, fmt = valfmt, err = 999)
633
$ (ibuf (k), k = 1,nbuf)
635
write (unit = 7, fmt = valfmt, err = 999)
636
$ (xbuf (k), k = 1,nbuf)
639
999 call mexErrMsgTxt ('error writing numerical values')
644
c-----------------------------------------------------------------------
645
c RBiformat: determine format for printing an integer
646
c-----------------------------------------------------------------------
648
subroutine RBiformat (kmin, kmax, indfmt, indn, ww)
650
$ n, indn, kmin, kmax, ww
653
if (kmin .ge. 0. and. kmax .le. 9) then
657
elseif (kmin .ge. -9 .and. kmax .le. 99) then
661
elseif (kmin .ge. -99 .and. kmax .le. 999) then
665
elseif (kmin .ge. -999 .and. kmax .le. 9999) then
669
elseif (kmin .ge. -9999 .and. kmax .le. 99999) then
673
elseif (kmin .ge. -99999 .and. kmax .le. 999999) then
677
elseif (kmin .ge. -999999 .and. kmax .le. 9999999) then
681
elseif (kmin .ge. -9999999 .and. kmax .le. 99999999) then
685
elseif (kmin .ge. -99999999 .and. kmax .le. 999999999) then
698
c-----------------------------------------------------------------------
699
c RBcards: determine number of cards required
700
c-----------------------------------------------------------------------
702
subroutine RBcards (nitems, nperline, ncards)
704
$ nitems, nperline, ncards
705
if (nitems .eq. 0) then
708
ncards = ((nitems-1) / nperline) + 1