1
subroutine mmread(iunit,rep,field,symm,rows,cols,nnz,nnzmax,
2
* indx,jndx,ival,rval,cval)
3
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
5
c This routine will read data from a matrix market formatted file.
6
c The data may be either sparse coordinate format, or dense array format.
8
c The unit iunit must be open, and the file will be rewound on return.
10
c 20-Sept-96 Karin A. Remington, NIST ACMD (karin@cam.nist.gov)
11
c 18-Oct-96 Change in routine name to match C and Matlab routines.
12
c 30-Oct-96 Bug fixes in mmio.f:
13
c -looping for comment lines
14
c -fixed non-ansi zero stringlength
15
c -incorrect size calculation for skew-symmetric arrays
16
c Other changes in mmio.f:
17
c -added integer value parameter to calling sequences
18
c -enforced proper count in size info line
19
c -added routine to count words in string (countwd)
20
c (Thanks to G.P.Leendetse and H.Oudshoom for their review
21
c of the initial version and suggested fixes.)
22
c 15-Oct-08 fixed illegal attempt of mimicking "do while" construct
23
c by redifing limits inside loop. (lines 443-450)
24
c (Thanks to Geraldo Veiga for his comments.)
26
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
30
c name type in/out description
31
c ---------------------------------------------------------------
33
c iunit integer in Unit identifier for the file
34
c containing the data to be read.
35
c Must be open prior to call.
36
c Will be rewound on return.
38
c rep character*10 out Matrix Market 'representation'
39
c indicator. On return:
41
c coordinate (for sparse data)
42
c array (for dense data)
43
c elemental (to be added)
45
c field character*7 out Matrix Market 'field'. On return:
52
c symm character*19 out Matrix Market 'field'. On return:
59
c rows integer out Number of rows in matrix.
61
c cols integer out Number of columns in matrix.
63
c nnz integer out Number of nonzero entries required to
66
c nnzmax integer in Maximum dimension of data arrays.
68
c indx integer(nnz)out Row indices for coordinate format.
69
c Undefined for array format.
71
c jndx integer(nnz)out Column indices for coordinate format.
72
c Undefined for array format.
74
c ival integer(nnz) out Integer data (if applicable, see 'field')
76
c rval double(nnz) out Real data (if applicable, see 'field')
78
c cval complex(nnz)out Complex data (if applicable, see 'field')
80
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
85
double precision rval(*)
87
double precision rpart,ipart
90
integer i, rows, cols, nnz, nnzreq, nnzmax, iunit
100
c Read header line and check validity:
102
read (iunit,end=1000,fmt=5) tmp1
104
call getwd(mmhead,tmp1,1024,1,next,count)
105
if ( count .eq. 0 ) go to 5000
106
call getwd(mmtype,tmp1,1024,next,next,count)
107
if ( count .eq. 0 ) go to 5000
108
call getwd(rep,tmp1,1024,next,next,count)
109
if ( count .eq. 0 ) go to 5000
110
call getwd(field,tmp1,1024,next,next,count)
111
if ( count .eq. 0 ) go to 5000
112
call getwd(symm,tmp1,1024,next,next,count)
113
if ( count .eq. 0 ) go to 5000
114
if ( mmhead .ne. '%%MatrixMarket' ) go to 5000
116
c Convert type code to lower case for easier comparisons:
118
call lowerc(mmtype,1,6)
119
if ( mmtype .ne. 'matrix' ) then
120
print *,'Invalid matrix type: ',mmtype
121
print *,'This reader only understands type ''matrix''.'
124
call lowerc(rep,1,10)
125
call lowerc(field,1,7)
126
call lowerc(symm,1,19)
129
c Test input qualifiers:
131
if (rep .ne. 'coordinate' .and. rep .ne. 'array' )
133
if (rep .eq. 'coordinate' .and. field .ne. 'integer' .and.
134
* field .ne. 'real' .and. field .ne. 'complex' .and.
135
* field .ne. 'pattern') go to 7000
136
if (rep .eq. 'array' .and. field .ne. 'integer' .and.
137
* field .ne. 'real' .and. field .ne. 'complex' ) go to 8000
138
if (symm .ne. 'general' .and. symm .ne. 'symmetric' .and.
139
* symm .ne. 'hermitian' .and. symm .ne. 'skew-symmetric')
142
c Read through comment lines, ignoring content:
144
read (iunit,end=2000,fmt=200) tmp2
147
if ( tmp2(1:1) .ne. '%' ) then
150
read (iunit,end=2000,fmt=200) tmp2
154
c Just read a non-comment.
155
c Now, back up a line, and read for first int, and back up
156
c again. This will set pointer to just before apparent size
158
c Before continuing with free form input, count the number of
159
c words on the size info line to ensure there is the right amount
160
c of info (2 words for array matrices, 3 for coordinate matrices).
163
read (iunit,end=1000,fmt=5) tmp1
164
call countwd(tmp1,1024,1,count)
165
if ( rep .eq. 'array' .and. count .ne. 2 ) go to 3000
166
if ( rep .eq. 'coordinate' .and. count .ne. 3 ) go to 3500
168
c Correct number of words are present, now back up and read them.
172
if ( rep .eq. 'coordinate' ) then
174
c Read matrix in sparse coordinate format
176
read (iunit,fmt=*) rows,cols,nnz
178
c Check to ensure adequate storage is available
180
if ( nnz .gt. nnzmax ) then
181
print *,'insufficent array lengths for matrix of ',nnz,
183
print *,'resize nnzmax to at least ',nnz,'. (currently ',
188
c Read data according to data type (real,integer,complex, or pattern)
190
if ( field .eq. 'integer' ) then
192
read (iunit,fmt=*,end=4000) indx(i),jndx(i),ival(i)
194
elseif ( field .eq. 'real' ) then
196
read (iunit,fmt=*,end=4000) indx(i),jndx(i),rval(i)
198
elseif ( field .eq. 'complex' ) then
200
read (iunit,fmt=*,end=4000) indx(i),jndx(i),rpart,ipart
201
cval(i) = cmplx(rpart,ipart)
203
elseif ( field .eq. 'pattern' ) then
205
read (iunit,fmt=*,end=4000) indx(i),jndx(i)
208
print *,'''',field,''' data type not recognized.'
214
elseif ( rep .eq. 'array' ) then
216
c Read matrix in dense column-oriented array format
218
read (iunit,fmt=*) rows,cols
220
c Check to ensure adequate storage is available
222
if ( symm .eq. 'symmetric' .or. symm .eq. 'hermitian' ) then
223
nnzreq = (rows*cols - rows)/2 + rows
225
elseif ( symm .eq. 'skew-symmetric' ) then
226
nnzreq = (rows*cols - rows)/2
232
if ( nnzreq .gt. nnzmax ) then
233
print *,'insufficent array length for ',rows, ' by ',
234
* cols,' dense ',symm,' matrix.'
235
print *,'resize nnzmax to at least ',nnzreq,'. (currently ',
240
c Read data according to data type (real,integer,complex, or pattern)
242
if ( field .eq. 'integer' ) then
244
read (iunit,fmt=*,end=4000) ival(i)
246
elseif ( field .eq. 'real' ) then
248
read (iunit,fmt=*,end=4000) rval(i)
250
elseif ( field .eq. 'complex' ) then
252
read (iunit,fmt=*,end=4000) rpart,ipart
253
cval(i) = cmplx(rpart,ipart)
256
print *,'''pattern'' data not consistant with type ''array'''
262
print *,'''',rep,''' representation not recognized.'
263
print *, 'Recognized representations:'
265
print *, ' coordinate'
269
c Various error conditions:
271
1000 print *,'Premature end-of-file.'
272
print *,'No lines found.'
274
2000 print *,'Premature end-of-file.'
275
print *,'No data lines found.'
277
3000 print *,'Size info inconsistant with representation.'
278
print *,'Array matrices need exactly 2 size descriptors.'
279
print *, count,' were found.'
281
3500 print *,'Size info inconsistant with representation.'
282
print *,'Coordinate matrices need exactly 3 size descriptors.'
283
print *, count,' were found.'
285
4000 print *,'Premature end-of-file.'
286
print *,'Check that the data file contains ',nnz,
287
* ' lines of i,j,[val] data.'
288
print *,'(it appears there are only ',i,' such lines.)'
290
5000 print *,'Invalid matrix header: ',tmp1
291
print *,'Correct header format:'
292
print *,'%%MatrixMarket type representation field symmetry'
294
print *,'Check specification and try again.'
295
6000 print *,'''',rep,''' representation not recognized.'
296
print *, 'Recognized representations:'
298
print *, ' coordinate'
300
7000 print *,'''',field,''' field is not recognized.'
301
print *, 'Recognized fields:'
307
8000 print *,'''',field,''' arrays are not recognized.'
308
print *, 'Recognized fields:'
313
9000 print *,'''',symm,''' symmetry is not recognized.'
314
print *, 'Recognized symmetries:'
316
print *, ' symmetric'
317
print *, ' hermitian'
318
print *, ' skew-symmetric'
320
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
322
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
323
c End of subroutine mmread
324
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
326
subroutine mminfo(iunit,rep,field,symm,rows,cols,nnz)
327
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
329
c This routine will read header information from a Matrix Market
332
c The unit iunit must be open, and the file will be rewound on return.
334
c 20-Sept-96 Karin A. Remington, NIST ACMD (karin@cam.nist.gov)
335
c 18-Oct-96 Change in routine name to match C and Matlab routines.
336
c 30-Oct-96 Bug fixes in mmio.f:
337
c -looping for comment lines
338
c -fixed non-ansi zero stringlength
339
c -incorrect size calculation for skew-symmetric arrays
340
c Other changes in mmio.f:
341
c -added integer value parameter to calling sequences
342
c -enforced proper count in size info line
343
c -added routine to count words in string (countwd)
344
c (Thanks to G.P.Leendetse and H.Oudshoom for their review
345
c of the initial version and suggested fixes.)
346
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
350
c name type in/out description
351
c ---------------------------------------------------------------
353
c iunit integer in Unit identifier for the open file
354
c containing the data to be read.
356
c rep character*10 out Matrix Market 'representation'
357
c indicator. On return:
359
c coordinate (for sparse data)
360
c array (for dense data)
361
c elemental (to be added)
363
c field character*7 out Matrix Market 'field'. On return:
370
c symm character*19 out Matrix Market 'field'. On return:
377
c rows integer out Number of rows in matrix.
379
c cols integer out Number of columns in matrix.
381
c nnz integer out Number of nonzero entries required to store
384
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
388
integer i, rows, cols, nnz, iunit
398
c Read header line and check validity:
400
read (iunit,end=1000,fmt=5) tmp1
403
c Parse words from header line:
405
call getwd(mmhead,tmp1,1024,1,next,count)
406
if ( count .eq. 0 ) go to 5000
407
call getwd(mmtype,tmp1,1024,next,next,count)
408
if ( count .eq. 0 ) go to 5000
409
call getwd(rep,tmp1,1024,next,next,count)
410
if ( count .eq. 0 ) go to 5000
411
call getwd(field,tmp1,1024,next,next,count)
412
if ( count .eq. 0 ) go to 5000
413
call getwd(symm,tmp1,1024,next,next,count)
414
if ( count .eq. 0 ) go to 5000
415
if ( mmhead .ne. '%%MatrixMarket' ) go to 5000
417
c Convert type code to upper case for easier comparisons:
419
call lowerc(mmtype,1,6)
420
if ( mmtype .ne. 'matrix' ) then
421
print *,'Invalid matrix type: ',mmtype
422
print *,'This reader only understands type ''matrix''.'
425
call lowerc(rep,1,10)
426
call lowerc(field,1,7)
427
call lowerc(symm,1,19)
430
c Test input qualifiers:
432
if (rep .ne. 'coordinate' .and. rep .ne. 'array' )
434
if (rep .eq. 'coordinate' .and. field .ne. 'integer' .and.
435
* field .ne. 'real' .and. field .ne. 'complex' .and.
436
* field .ne. 'pattern') go to 7000
437
if (rep .eq. 'array' .and. field .ne. 'integer' .and.
438
* field .ne. 'real' .and. field .ne. 'complex' ) go to 8000
439
if (symm .ne. 'general' .and. symm .ne. 'symmetric' .and.
440
* symm .ne. 'hermitian' .and. symm .ne. 'skew-symmetric')
443
c Read through comment lines, ignoring content:
445
read (iunit,end=2000,fmt=200) tmp2
448
if ( tmp2(1:1) .ne. '%' ) then
451
read (iunit,end=2000,fmt=200) tmp2
455
c Just read a non-comment.
456
c Now, back up a line, and read for first int, and back up
457
c again. This will set pointer to just before apparent size
459
c Before continuing with free form input, count the number of
460
c words on the size info line to ensure there is the right amount
461
c of info (2 words for array matrices, 3 for coordinate matrices).
464
read (iunit,end=1000,fmt=5) tmp1
465
call countwd(tmp1,1024,1,count)
466
if ( rep .eq. 'array' .and. count .ne. 2 ) go to 3000
467
if ( rep .eq. 'coordinate' .and. count .ne. 3 ) go to 3500
469
c Correct number of words are present, now back up and read them.
473
if ( rep .eq. 'coordinate' ) then
475
c Read matrix in sparse coordinate format
477
read (iunit,fmt=*) rows,cols,nnz
479
c Rewind before returning
484
elseif ( rep .eq. 'array' ) then
486
c Read matrix in dense column-oriented array format
488
read (iunit,fmt=*) rows,cols
489
if ( symm .eq. 'symmetric' .or. symm .eq. 'hermitian' ) then
490
nnz = (rows*cols - rows)/2 + rows
491
elseif ( symm .eq. 'skew-symmetric' ) then
492
nnz = (rows*cols - rows)/2
497
c Rewind before returning
502
print *,'''',rep,''' representation not recognized.'
503
print *, 'Recognized representations:'
505
print *, ' coordinate'
509
c Various error conditions:
511
1000 print *,'Premature end-of-file.'
512
print *,'No lines found.'
514
2000 print *,'Premature end-of-file.'
515
print *,'No data found.'
517
3000 print *,'Size info inconsistant with representation.'
518
print *,'Array matrices need exactly 2 size descriptors.'
519
print *, count,' were found.'
521
3500 print *,'Size info inconsistant with representation.'
522
print *,'Coordinate matrices need exactly 3 size descriptors.'
523
print *, count,' were found.'
525
5000 print *,'Invalid matrix header: ',tmp1
526
print *,'Correct header format:'
527
print *,'%%MatrixMarket type representation field symmetry'
529
print *,'Check specification and try again.'
531
6000 print *,'''',rep,''' representation not recognized.'
532
print *, 'Recognized representations:'
534
print *, ' coordinate'
536
7000 print *,'''',field,''' field is not recognized.'
537
print *, 'Recognized fields:'
543
8000 print *,'''',field,''' arrays are not recognized.'
544
print *, 'Recognized fields:'
549
9000 print *,'''',symm,''' symmetry is not recognized.'
550
print *, 'Recognized symmetries:'
552
print *, ' symmetric'
553
print *, ' hermitian'
554
print *, ' skew-symmetric'
556
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
558
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
559
c End of subroutine mmread
560
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
562
subroutine mmwrite(ounit,rep,field,symm,rows,cols,nnz,
563
* indx,jndx,ival,rval,cval)
564
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
566
c This routine will write data to a matrix market formatted file.
567
c The data may be either sparse coordinate format, or dense array format.
569
c The unit ounit must be open.
571
c 20-Sept-96 Karin A. Remington, NIST ACMD (karin@cam.nist.gov)
572
c 18-Oct-96 Change in routine name to match C and Matlab routines.
573
c 30-Oct-96 Bug fixes in mmio.f:
574
c -looping for comment lines
575
c -fixed non-ansi zero stringlength
576
c -incorrect size calculation for skew-symmetric arrays
577
c Other changes in mmio.f:
578
c -added integer value parameter to calling sequences
579
c -enforced proper count in size info line
580
c -added routine to count words in string (countwd)
581
c (Thanks to G.P.Leendetse and H.Oudshoom for their review
582
c of the initial version and suggested fixes.)
583
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
587
c name type in/out description
588
c ---------------------------------------------------------------
590
c ounit integer in Unit identifier for the file
591
c to which the data will be written.
592
c Must be open prior to call.
594
c rep character* in Matrix Market 'representation'
595
c indicator. Valid inputs:
597
c coordinate (for sparse data)
598
c array (for dense data)
599
c *elemental* (to be added)
601
c field character* in Matrix Market 'field'. Valid inputs:
606
c pattern (not valid for dense arrays)
608
c symm character* in Matrix Market 'field'. Valid inputs:
615
c rows integer in Number of rows in matrix.
617
c cols integer in Number of columns in matrix.
619
c nnz integer in Number of nonzero entries in matrix.
620
c (rows*cols for array matrices)
622
c indx integer(nnz)in Row indices for coordinate format.
623
c Undefined for array format.
625
c jndx integer(nnz)in Column indices for coordinate format.
626
c Undefined for array format.
628
c ival integer(nnz) in Integer data (if applicable, see 'field')
630
c rval double(nnz) in Real data (if applicable, see 'field')
632
c cval complex(nnz)in Complex data (if applicable, see 'field')
634
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
639
double precision rval(*)
643
integer i, rows, cols, nnz, nnzreq, ounit
644
character*(*)rep,field,symm
646
c Test input qualifiers:
648
if (rep .ne. 'coordinate' .and. rep .ne. 'array' )
650
if (rep .eq. 'coordinate' .and. field .ne. 'integer' .and.
651
* field .ne. 'real' .and. field .ne. 'complex' .and.
652
* field .ne. 'pattern') go to 2000
653
if (rep .eq. 'array' .and. field .ne. 'integer' .and.
654
* field .ne. 'real' .and. field .ne. 'complex' ) go to 3000
655
if (symm .ne. 'general' .and. symm .ne. 'symmetric' .and.
656
* symm .ne. 'hermitian' .and. symm .ne. 'skew-symmetric')
661
write(unit=ounit,fmt=5)rep,' ',field,' ',symm
662
5 format('%%MatrixMarket matrix ',11A,1A,8A,1A,20A)
664
c Write size information:
666
if ( rep .eq. 'coordinate' ) then
668
write(unit=ounit,fmt=*) rows,cols,nnz
669
if ( field .eq. 'integer' ) then
671
write(unit=ounit,fmt=*)indx(i),jndx(i),ival(i)
673
elseif ( field .eq. 'real' ) then
675
write(unit=ounit,fmt=*)indx(i),jndx(i),rval(i)
677
elseif ( field .eq. 'complex' ) then
679
write(unit=ounit,fmt=*)indx(i),jndx(i),
680
* real(cval(i)),aimag(cval(i))
683
c field .eq. 'pattern'
685
write(unit=ounit,fmt=*)indx(i),jndx(i)
690
if ( symm .eq. 'general' ) then
692
elseif ( symm .eq. 'symmetric' .or.
693
* symm .eq. 'hermitian' ) then
694
nnzreq = (rows*cols - rows)/2 + rows
696
c symm .eq. 'skew-symmetric'
697
nnzreq = (rows*cols - rows)/2
699
write(unit=ounit,fmt=*)rows,cols
700
if ( field .eq. 'integer' ) then
702
write(unit=ounit,fmt=*)ival(i)
704
elseif ( field .eq. 'real' ) then
706
write(unit=ounit,fmt=*)rval(i)
709
c field .eq. 'complex'
711
write(unit=ounit,fmt=*)real(cval(i)),aimag(cval(i))
719
1000 print *,'''',rep,''' representation not recognized.'
720
print *, 'Recognized representations:'
722
print *, ' coordinate'
724
2000 print *,'''',field,''' field is not recognized.'
725
print *, 'Recognized fields:'
731
3000 print *,'''',field,''' arrays are not recognized.'
732
print *, 'Recognized fields:'
737
4000 print *,'''',symm,''' symmetry is not recognized.'
738
print *, 'Recognized symmetries:'
740
print *, ' symmetric'
741
print *, ' hermitian'
742
print *, ' skew-symmetric'
744
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
746
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
747
c End of subroutine mmwrite
748
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
750
subroutine lowerc(string,pos,len)
751
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
752
c Convert uppercase letters to lowercase letters in string with
753
c starting postion pos and length len.
754
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
758
character*26 lcase, ucase
760
data lcase/'abcdefghijklmnopqrstuvwxyz'/
761
data ucase/'ABCDEFGHIJKLMNOPQRSTUVWXYZ'/
764
k = index(ucase,string(i:i))
765
if (k.ne.0) string(i:i) = lcase(k:k)
770
subroutine getwd(word,string,slen,start,next,wlen)
771
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
772
c Getwd extracts the first word from string starting
773
c at position start. On return, next is the position
774
c of the blank which terminates the word in string.
775
c If the found word is longer than the allocated space
776
c for the word in the calling program, the word will be
778
c Count is set to the length of the word found.
780
c 30-Oct-96 Bug fix: fixed non-ansi zero stringlength
781
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
782
integer slen, start, next, begin, space, wlen
788
space = index(string(i:slen),' ')
789
if ( space .gt. 1) then
797
if ( wlen .le. 0 ) then
802
word=string(begin:begin+wlen)
806
subroutine countwd(string,slen,start,count)
807
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
808
c Countwd counts the number of words in string starting
809
c at position start. On return, count is the number of words.
810
c 30-Oct-96 Routine added
811
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
813
integer slen, start, next, wordlength, count
818
10 call getwd(tmp2,string,1024,next,next,wordlength)
819
if ( wordlength .gt. 0 ) then