1
/* $Id: mmio.c,v 1.6 2009/06/03 01:56:55 ellson Exp $Revision: */
2
/* vim:set shiftwidth=4 ts=8: */
4
/**********************************************************
5
* This software is part of the graphviz package *
6
* http://www.graphviz.org/ *
8
* Copyright (c) 1994-2004 AT&T Corp. *
9
* and is licensed under the *
10
* Common Public License, Version 1.0 *
13
* Information and Software Systems Research *
14
* AT&T Research, Florham Park NJ *
15
**********************************************************/
17
* Matrix Market I/O library for ANSI C
19
* See http://math.nist.gov/MatrixMarket for details.
32
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_,
33
int *nz_, double **val_, int **I_, int **J_)
42
if ((f = fopen(fname, "r")) == NULL)
46
if (mm_read_banner(f, &matcode) != 0) {
48
"mm_read_unsymetric: Could not process Matrix Market banner ");
49
fprintf(stderr, " in file [%s]\n", fname);
55
if (!(mm_is_real(matcode) && mm_is_matrix(matcode) &&
56
mm_is_sparse(matcode))) {
57
fprintf(stderr, "Sorry, this application does not support ");
58
fprintf(stderr, "Market Market type: [%s]\n",
59
mm_typecode_to_str(matcode));
63
/* find out size of sparse matrix: M, N, nz .... */
65
if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) {
67
"read_unsymmetric_sparse(): could not parse matrix size.\n");
75
/* reseve memory for matrices */
77
I = (int *) malloc(nz * sizeof(int));
78
J = (int *) malloc(nz * sizeof(int));
79
val = (double *) malloc(nz * sizeof(double));
85
/* NOTE: when reading in doubles, ANSI C requires the use of the "l" */
86
/* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
87
/* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */
89
for (i = 0; i < nz; i++) {
90
fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
91
I[i]--; /* adjust from 1-based to 0-based */
99
int mm_is_valid(MM_typecode matcode)
101
if (!mm_is_matrix(matcode))
103
if (mm_is_dense(matcode) && mm_is_pattern(matcode))
105
if (mm_is_real(matcode) && mm_is_hermitian(matcode))
107
if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||
108
mm_is_skew(matcode)))
113
int mm_read_banner(FILE * f, MM_typecode * matcode)
115
char line[MM_MAX_LINE_LENGTH];
116
char banner[MM_MAX_TOKEN_LENGTH];
117
char mtx[MM_MAX_TOKEN_LENGTH];
118
char crd[MM_MAX_TOKEN_LENGTH];
119
char data_type[MM_MAX_TOKEN_LENGTH];
120
char storage_scheme[MM_MAX_TOKEN_LENGTH];
124
mm_clear_typecode(matcode);
126
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
127
return MM_PREMATURE_EOF;
129
if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type,
130
storage_scheme) != 5)
131
return MM_PREMATURE_EOF;
133
for (p = mtx; *p != '\0'; *p = tolower(*p), p++); /* convert to lower case */
134
for (p = crd; *p != '\0'; *p = tolower(*p), p++);
135
for (p = data_type; *p != '\0'; *p = tolower(*p), p++);
136
for (p = storage_scheme; *p != '\0'; *p = tolower(*p), p++);
138
/* check for banner */
139
if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) !=
143
/* first field should be "mtx" */
144
if (strcmp(mtx, MM_MTX_STR) != 0)
145
return MM_UNSUPPORTED_TYPE;
146
mm_set_matrix(matcode);
149
/* second field describes whether this is a sparse matrix (in coordinate
150
storgae) or a dense array */
153
if (strcmp(crd, MM_SPARSE_STR) == 0)
154
mm_set_sparse(matcode);
155
else if (strcmp(crd, MM_DENSE_STR) == 0)
156
mm_set_dense(matcode);
158
return MM_UNSUPPORTED_TYPE;
163
if (strcmp(data_type, MM_REAL_STR) == 0)
164
mm_set_real(matcode);
165
else if (strcmp(data_type, MM_COMPLEX_STR) == 0)
166
mm_set_complex(matcode);
167
else if (strcmp(data_type, MM_PATTERN_STR) == 0)
168
mm_set_pattern(matcode);
169
else if (strcmp(data_type, MM_INT_STR) == 0)
170
mm_set_integer(matcode);
172
return MM_UNSUPPORTED_TYPE;
177
if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)
178
mm_set_general(matcode);
179
else if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
180
mm_set_symmetric(matcode);
181
else if (strcmp(storage_scheme, MM_HERM_STR) == 0)
182
mm_set_hermitian(matcode);
183
else if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
184
mm_set_skew(matcode);
186
return MM_UNSUPPORTED_TYPE;
192
int mm_write_mtx_crd_size(FILE * f, int M, int N, int nz)
194
if (fprintf(f, "%d %d %d\n", M, N, nz) != 3)
195
return MM_COULD_NOT_WRITE_FILE;
200
int mm_read_mtx_crd_size(FILE * f, int *M, int *N, int *nz)
202
char line[MM_MAX_LINE_LENGTH];
205
/* set return null parameter values, in case we exit with errors */
208
/* now continue scanning until you reach the end-of-comments */
210
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
211
return MM_PREMATURE_EOF;
212
} while (line[0] == '%');
214
/* line[] is either blank or has M,N, nz */
215
if (sscanf(line, "%d %d %d", M, N, nz) == 3)
220
num_items_read = fscanf(f, "%d %d %d", M, N, nz);
221
if (num_items_read == EOF)
222
return MM_PREMATURE_EOF;
224
while (num_items_read != 3);
230
int mm_read_mtx_array_size(FILE * f, int *M, int *N)
232
char line[MM_MAX_LINE_LENGTH];
234
/* set return null parameter values, in case we exit with errors */
237
/* now continue scanning until you reach the end-of-comments */
239
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
240
return MM_PREMATURE_EOF;
241
} while (line[0] == '%');
243
/* line[] is either blank or has M,N, nz */
244
if (sscanf(line, "%d %d", M, N) == 2)
247
else /* we have a blank line */
249
num_items_read = fscanf(f, "%d %d", M, N);
250
if (num_items_read == EOF)
251
return MM_PREMATURE_EOF;
253
while (num_items_read != 2);
258
int mm_write_mtx_array_size(FILE * f, int M, int N)
260
if (fprintf(f, "%d %d\n", M, N) != 2)
261
return MM_COULD_NOT_WRITE_FILE;
268
/*-------------------------------------------------------------------------*/
270
/******************************************************************/
271
/* use when I[], J[], and val[]J, and val[] are already allocated */
272
/******************************************************************/
274
int mm_read_mtx_crd_data(FILE * f, int M, int N, int nz, int I[], int J[],
275
double val[], MM_typecode matcode)
278
if (mm_is_complex(matcode)) {
279
for (i = 0; i < nz; i++)
281
(f, "%d %d %lg %lg", &I[i], &J[i], &val[2 * i],
284
return MM_PREMATURE_EOF;
285
} else if (mm_is_real(matcode)) {
286
for (i = 0; i < nz; i++) {
287
if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
289
return MM_PREMATURE_EOF;
294
else if (mm_is_pattern(matcode)) {
295
for (i = 0; i < nz; i++)
296
if (fscanf(f, "%d %d", &I[i], &J[i])
298
return MM_PREMATURE_EOF;
300
return MM_UNSUPPORTED_TYPE;
306
int mm_read_mtx_crd_entry(FILE * f, int *I, int *J,
307
double *real, double *imag, MM_typecode matcode)
309
if (mm_is_complex(matcode)) {
310
if (fscanf(f, "%d %d %lg %lg", I, J, real, imag)
312
return MM_PREMATURE_EOF;
313
} else if (mm_is_real(matcode)) {
314
if (fscanf(f, "%d %d %lg\n", I, J, real)
316
return MM_PREMATURE_EOF;
320
else if (mm_is_pattern(matcode)) {
321
if (fscanf(f, "%d %d", I, J) != 2)
322
return MM_PREMATURE_EOF;
324
return MM_UNSUPPORTED_TYPE;
331
/************************************************************************
332
mm_read_mtx_crd() fills M, N, nz, array of values, and return
333
type code, e.g. 'MCRS'
335
if matrix is complex, values[] is of size 2*nz,
336
(nz pairs of real/imaginary values)
337
************************************************************************/
339
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,
340
double **val, MM_typecode * matcode)
345
if (strcmp(fname, "stdin") == 0)
347
else if ((f = fopen(fname, "r")) == NULL)
348
return MM_COULD_NOT_READ_FILE;
351
if ((ret_code = mm_read_banner(f, matcode)) != 0)
354
if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&
355
mm_is_matrix(*matcode)))
356
return MM_UNSUPPORTED_TYPE;
358
if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)
362
*I = (int *) malloc(*nz * sizeof(int));
363
*J = (int *) malloc(*nz * sizeof(int));
366
if (mm_is_complex(*matcode)) {
367
*val = (double *) malloc(*nz * 2 * sizeof(double));
368
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
372
} else if (mm_is_real(*matcode)) {
373
*val = (double *) malloc(*nz * sizeof(double));
374
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
380
else if (mm_is_pattern(*matcode)) {
381
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
392
int mm_write_banner(FILE * f, MM_typecode matcode)
394
char *str = mm_typecode_to_str(matcode);
397
ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
400
return MM_COULD_NOT_WRITE_FILE;
405
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
406
double val[], MM_typecode matcode)
411
if (strcmp(fname, "stdout") == 0)
413
else if ((f = fopen(fname, "w")) == NULL)
414
return MM_COULD_NOT_WRITE_FILE;
416
/* print banner followed by typecode */
417
fprintf(f, "%s ", MatrixMarketBanner);
418
fprintf(f, "%s\n", mm_typecode_to_str(matcode));
420
/* print matrix sizes and nonzeros */
421
fprintf(f, "%d %d %d\n", M, N, nz);
424
if (mm_is_pattern(matcode))
425
for (i = 0; i < nz; i++)
426
fprintf(f, "%d %d\n", I[i], J[i]);
427
else if (mm_is_real(matcode))
428
for (i = 0; i < nz; i++)
429
fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
430
else if (mm_is_complex(matcode))
431
for (i = 0; i < nz; i++)
432
fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2 * i],
437
return MM_UNSUPPORTED_TYPE;
448
* Create a new copy of a string s. strdup() is a common routine, but
449
* not part of ANSI C, so it is included here. Used by mm_typecode_to_str().
453
char *strdup(const char *s)
456
char *s2 = (char *) malloc((len+1)*sizeof(char));
457
return strcpy(s2, s);
461
char *mm_typecode_to_str(MM_typecode matcode)
463
char buffer[MM_MAX_LINE_LENGTH];
465
/* char *strdup(const char *); */
468
/* check for MTX type */
469
if (mm_is_matrix(matcode))
470
types[0] = MM_MTX_STR;
474
/* check for CRD or ARR matrix */
475
if (mm_is_sparse(matcode))
476
types[1] = MM_SPARSE_STR;
477
else if (mm_is_dense(matcode))
478
types[1] = MM_DENSE_STR;
482
/* check for element data type */
483
if (mm_is_real(matcode))
484
types[2] = MM_REAL_STR;
485
else if (mm_is_complex(matcode))
486
types[2] = MM_COMPLEX_STR;
487
else if (mm_is_pattern(matcode))
488
types[2] = MM_PATTERN_STR;
489
else if (mm_is_integer(matcode))
490
types[2] = MM_INT_STR;
495
/* check for symmetry type */
496
if (mm_is_general(matcode))
497
types[3] = MM_GENERAL_STR;
498
else if (mm_is_symmetric(matcode))
499
types[3] = MM_SYMM_STR;
500
else if (mm_is_hermitian(matcode))
501
types[3] = MM_HERM_STR;
502
else if (mm_is_skew(matcode))
503
types[3] = MM_SKEW_STR;
507
sprintf(buffer, "%s %s %s %s", types[0], types[1], types[2], types[3]);
508
return strdup(buffer);