EVSL  1.1.0
EigenValues Slicing Library
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
mmio.c
Go to the documentation of this file.
1 /*
2 * Matrix Market I/O library for ANSI C
3 *
4 * See http://math.nist.gov/MatrixMarket for details.
5 *
6 *
7 */
8 
9 
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14 #include "mmio.h"
15 
16 int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
17  double **val_, int **I_, int **J_)
18 {
19  FILE *f;
20  MM_typecode matcode;
21  int M, N, nz;
22  int i;
23  double *val;
24  int *I, *J;
25 
26  if ((f = fopen(fname, "r")) == NULL)
27  return -1;
28  if (mm_read_banner(f, &matcode) != 0)
29  {
30  printf("mm_read_unsymetric: Could not process Matrix Market banner ");
31  printf(" in file [%s]\n", fname);
32  return -1;
33  }
34 
35  if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) &&
36  mm_is_sparse(matcode)))
37  {
38  fprintf(stderr, "Sorry, this application does not support ");
39  fprintf(stderr, "Market Market type: [%s]\n",
40  mm_typecode_to_str(matcode));
41  return -1;
42  }
43 
44  /* find out size of sparse matrix: M, N, nz .... */
45 
46  if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0)
47  {
48  fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n");
49  return -1;
50  }
51 
52  *M_ = M;
53  *N_ = N;
54  *nz_ = nz;
55 
56  /* reseve memory for matrices */
57 
58  I = (int *) malloc(nz * sizeof(int));
59  J = (int *) malloc(nz * sizeof(int));
60  val = (double *) malloc(nz * sizeof(double));
61 
62  *val_ = val;
63  *I_ = I;
64  *J_ = J;
65 
66  /* NOTE: when reading in doubles, ANSI C requires the use of the "l" */
67  /* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
68  /* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */
69 
70  for (i=0; i<nz; i++) {
71  if (3 != fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])) {
72  printf("warning: fscanf may not be successfully done\n");
73  }
74  I[i]--; /* adjust from 1-based to 0-based */
75  J[i]--;
76  }
77  fclose(f);
78 
79  return 0;
80 }
81 
83 {
84  if (!mm_is_matrix(matcode)) return 0;
85  if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;
86  if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;
87  if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||
88  mm_is_skew(matcode))) return 0;
89  return 1;
90 }
91 
92 int mm_read_banner(FILE *f, MM_typecode *matcode)
93 {
94  char line[MM_MAX_LINE_LENGTH];
95  char banner[MM_MAX_TOKEN_LENGTH];
96  char mtx[MM_MAX_TOKEN_LENGTH];
97  char crd[MM_MAX_TOKEN_LENGTH];
98  char data_type[MM_MAX_TOKEN_LENGTH];
99  char storage_scheme[MM_MAX_TOKEN_LENGTH];
100  char *p;
101 
102  mm_clear_typecode(matcode);
103 
104  if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
105  return MM_PREMATURE_EOF;
106 
107  if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type,
108  storage_scheme) != 5)
109  return MM_PREMATURE_EOF;
110 
111  for (p=mtx; *p!='\0'; *p=tolower(*p),p++); /* convert to lower case */
112  for (p=crd; *p!='\0'; *p=tolower(*p),p++);
113  for (p=data_type; *p!='\0'; *p=tolower(*p),p++);
114  for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++);
115 
116  /* check for banner */
117  if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)
118  return MM_NO_HEADER;
119 
120  /* first field should be "mtx" */
121  if (strcmp(mtx, MM_MTX_STR) != 0)
122  return MM_UNSUPPORTED_TYPE;
123  mm_set_matrix(matcode);
124 
125 
126  /* second field describes whether this is a sparse matrix (in coordinate
127  storgae) or a dense array */
128 
129 
130  if (strcmp(crd, MM_SPARSE_STR) == 0)
131  mm_set_sparse(matcode);
132  else
133  if (strcmp(crd, MM_DENSE_STR) == 0)
134  mm_set_dense(matcode);
135  else
136  return MM_UNSUPPORTED_TYPE;
137 
138 
139  /* third field */
140 
141  if (strcmp(data_type, MM_REAL_STR) == 0)
142  mm_set_real(matcode);
143  else
144  if (strcmp(data_type, MM_COMPLEX_STR) == 0)
145  mm_set_complex(matcode);
146  else
147  if (strcmp(data_type, MM_PATTERN_STR) == 0)
148  mm_set_pattern(matcode);
149  else
150  if (strcmp(data_type, MM_INT_STR) == 0)
151  mm_set_integer(matcode);
152  else
153  return MM_UNSUPPORTED_TYPE;
154 
155 
156  /* fourth field */
157 
158  if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)
159  mm_set_general(matcode);
160  else
161  if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
162  mm_set_symmetric(matcode);
163  else
164  if (strcmp(storage_scheme, MM_HERM_STR) == 0)
165  mm_set_hermitian(matcode);
166  else
167  if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
168  mm_set_skew(matcode);
169  else
170  return MM_UNSUPPORTED_TYPE;
171 
172 
173  return 0;
174 }
175 
176 int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)
177 {
178  if (fprintf(f, "%d %d %d\n", M, N, nz) != 3)
180  else
181  return 0;
182 }
183 
184 int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz )
185 {
186  char line[MM_MAX_LINE_LENGTH];
187  int num_items_read;
188 
189  /* set return null parameter values, in case we exit with errors */
190  *M = *N = *nz = 0;
191 
192  /* now continue scanning until you reach the end-of-comments */
193  do
194  {
195  if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
196  return MM_PREMATURE_EOF;
197  }while (line[0] == '%');
198 
199  /* line[] is either blank or has M,N, nz */
200  if (sscanf(line, "%d %d %d", M, N, nz) == 3)
201  return 0;
202 
203  else
204  do
205  {
206  num_items_read = fscanf(f, "%d %d %d", M, N, nz);
207  if (num_items_read == EOF) return MM_PREMATURE_EOF;
208  }
209  while (num_items_read != 3);
210 
211  return 0;
212 }
213 
214 
215 int mm_read_mtx_array_size(FILE *f, int *M, int *N)
216 {
217  char line[MM_MAX_LINE_LENGTH];
218  int num_items_read;
219  /* set return null parameter values, in case we exit with errors */
220  *M = *N = 0;
221 
222  /* now continue scanning until you reach the end-of-comments */
223  do
224  {
225  if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
226  return MM_PREMATURE_EOF;
227  }while (line[0] == '%');
228 
229  /* line[] is either blank or has M,N, nz */
230  if (sscanf(line, "%d %d", M, N) == 2)
231  return 0;
232 
233  else /* we have a blank line */
234  do
235  {
236  num_items_read = fscanf(f, "%d %d", M, N);
237  if (num_items_read == EOF) return MM_PREMATURE_EOF;
238  }
239  while (num_items_read != 2);
240 
241  return 0;
242 }
243 
244 int mm_write_mtx_array_size(FILE *f, int M, int N)
245 {
246  if (fprintf(f, "%d %d\n", M, N) != 2)
248  else
249  return 0;
250 }
251 
252 
253 
254 /*-------------------------------------------------------------------------*/
255 
256 /******************************************************************/
257 /* use when I[], J[], and val[]J, and val[] are already allocated */
258 /******************************************************************/
259 
260 int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
261  double val[], MM_typecode matcode)
262 {
263  int i;
264  if (mm_is_complex(matcode))
265  {
266  for (i=0; i<nz; i++)
267  if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2*i], &val[2*i+1])
268  != 4) return MM_PREMATURE_EOF;
269  }
270  else if (mm_is_real(matcode))
271  {
272  for (i=0; i<nz; i++)
273  {
274  if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
275  != 3) return MM_PREMATURE_EOF;
276 
277  }
278  }
279 
280  else if (mm_is_pattern(matcode))
281  {
282  for (i=0; i<nz; i++)
283  if (fscanf(f, "%d %d", &I[i], &J[i])
284  != 2) return MM_PREMATURE_EOF;
285  }
286  else
287  return MM_UNSUPPORTED_TYPE;
288 
289  return 0;
290 
291 }
292 
293 int mm_read_mtx_crd_entry(FILE *f, int *I, int *J,
294  double *real, double *imag, MM_typecode matcode)
295 {
296  if (mm_is_complex(matcode))
297  {
298  if (fscanf(f, "%d %d %lg %lg", I, J, real, imag)
299  != 4) return MM_PREMATURE_EOF;
300  }
301  else if (mm_is_real(matcode))
302  {
303  if (fscanf(f, "%d %d %lg\n", I, J, real)
304  != 3) return MM_PREMATURE_EOF;
305 
306  }
307 
308  else if (mm_is_pattern(matcode))
309  {
310  if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF;
311  }
312  else
313  return MM_UNSUPPORTED_TYPE;
314 
315  return 0;
316 
317 }
318 
319 
320 /************************************************************************
321  mm_read_mtx_crd() fills M, N, nz, array of values, and return
322  type code, e.g. 'MCRS'
323 
324  if matrix is complex, values[] is of size 2*nz,
325  (nz pairs of real/imaginary values)
326 ************************************************************************/
327 
328 int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,
329  double **val, MM_typecode *matcode)
330 {
331  int ret_code;
332  FILE *f;
333 
334  if (strcmp(fname, "stdin") == 0) f=stdin;
335  else
336  if ((f = fopen(fname, "r")) == NULL)
337  return MM_COULD_NOT_READ_FILE;
338 
339 
340  if ((ret_code = mm_read_banner(f, matcode)) != 0)
341  return ret_code;
342 
343  if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&
344  mm_is_matrix(*matcode)))
345  return MM_UNSUPPORTED_TYPE;
346 
347  if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)
348  return ret_code;
349 
350 
351  *I = (int *) malloc(*nz * sizeof(int));
352  *J = (int *) malloc(*nz * sizeof(int));
353  *val = NULL;
354 
355  if (mm_is_complex(*matcode))
356  {
357  *val = (double *) malloc(*nz * 2 * sizeof(double));
358  ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
359  *matcode);
360  if (ret_code != 0) return ret_code;
361  }
362  else if (mm_is_real(*matcode))
363  {
364  *val = (double *) malloc(*nz * sizeof(double));
365  ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
366  *matcode);
367  if (ret_code != 0) return ret_code;
368  }
369 
370  else if (mm_is_pattern(*matcode))
371  {
372  ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
373  *matcode);
374  if (ret_code != 0) return ret_code;
375  }
376 
377  if (f != stdin) fclose(f);
378  return 0;
379 }
380 
381 int mm_write_banner(FILE *f, MM_typecode matcode)
382 {
383  char *str = mm_typecode_to_str(matcode);
384  int ret_code;
385 
386  ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
387  free(str);
388  if (ret_code !=2 )
390  else
391  return 0;
392 }
393 
394 int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
395  double val[], MM_typecode matcode)
396 {
397  FILE *f;
398  int i;
399 
400  if (strcmp(fname, "stdout") == 0)
401  f = stdout;
402  else
403  if ((f = fopen(fname, "w")) == NULL)
405 
406  /* print banner followed by typecode */
407  fprintf(f, "%s ", MatrixMarketBanner);
408  fprintf(f, "%s\n", mm_typecode_to_str(matcode));
409 
410  /* print matrix sizes and nonzeros */
411  fprintf(f, "%d %d %d\n", M, N, nz);
412 
413  /* print values */
414  if (mm_is_pattern(matcode))
415  for (i=0; i<nz; i++)
416  fprintf(f, "%d %d\n", I[i], J[i]);
417  else
418  if (mm_is_real(matcode))
419  for (i=0; i<nz; i++)
420  fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
421  else
422  if (mm_is_complex(matcode))
423  for (i=0; i<nz; i++)
424  fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i],
425  val[2*i+1]);
426  else
427  {
428  if (f != stdout) fclose(f);
429  return MM_UNSUPPORTED_TYPE;
430  }
431 
432  if (f !=stdout) fclose(f);
433 
434  return 0;
435 }
436 
437 
443 char *mm_strdup(const char *s)
444 {
445  int len = strlen(s);
446  char *s2 = (char *) malloc((len+1)*sizeof(char));
447  return strcpy(s2, s);
448 }
449 
451 {
452  char buffer[MM_MAX_LINE_LENGTH];
453  char *types[4];
454  char *mm_strdup(const char *);
455  //int error =0;
456 
457  /* check for MTX type */
458  if (mm_is_matrix(matcode))
459  types[0] = MM_MTX_STR;
460  //else
461  // error=1;
462 
463  /* check for CRD or ARR matrix */
464  if (mm_is_sparse(matcode))
465  types[1] = MM_SPARSE_STR;
466  else
467  if (mm_is_dense(matcode))
468  types[1] = MM_DENSE_STR;
469  else
470  return NULL;
471 
472  /* check for element data type */
473  if (mm_is_real(matcode))
474  types[2] = MM_REAL_STR;
475  else
476  if (mm_is_complex(matcode))
477  types[2] = MM_COMPLEX_STR;
478  else
479  if (mm_is_pattern(matcode))
480  types[2] = MM_PATTERN_STR;
481  else
482  if (mm_is_integer(matcode))
483  types[2] = MM_INT_STR;
484  else
485  return NULL;
486 
487 
488  /* check for symmetry type */
489  if (mm_is_general(matcode))
490  types[3] = MM_GENERAL_STR;
491  else
492  if (mm_is_symmetric(matcode))
493  types[3] = MM_SYMM_STR;
494  else
495  if (mm_is_hermitian(matcode))
496  types[3] = MM_HERM_STR;
497  else
498  if (mm_is_skew(matcode))
499  types[3] = MM_SKEW_STR;
500  else
501  return NULL;
502 
503  sprintf(buffer,"%s %s %s %s", types[0], types[1], types[2], types[3]);
504  return mm_strdup(buffer);
505 }
506 
#define MM_PATTERN_STR
Definition: mmio.h:116
#define mm_is_pattern(typecode)
Definition: mmio.h:40
#define MM_MAX_LINE_LENGTH
Definition: mmio.h:12
#define MM_SYMM_STR
Definition: mmio.h:113
#define mm_clear_typecode(typecode)
Definition: mmio.h:70
#define mm_set_real(typecode)
Definition: mmio.h:60
#define mm_set_pattern(typecode)
Definition: mmio.h:61
#define MM_GENERAL_STR
Definition: mmio.h:112
#define MM_UNSUPPORTED_TYPE
Definition: mmio.h:83
#define mm_set_complex(typecode)
Definition: mmio.h:59
#define MM_PREMATURE_EOF
Definition: mmio.h:80
#define mm_set_matrix(typecode)
Definition: mmio.h:53
int mm_write_banner(FILE *f, MM_typecode matcode)
Definition: mmio.c:381
#define mm_set_dense(typecode)
Definition: mmio.h:56
#define mm_is_dense(typecode)
Definition: mmio.h:35
#define mm_is_skew(typecode)
Definition: mmio.h:45
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz)
Definition: mmio.c:184
#define MM_SPARSE_STR
Definition: mmio.h:108
#define MatrixMarketBanner
Definition: mmio.h:13
#define mm_set_hermitian(typecode)
Definition: mmio.h:68
#define MM_DENSE_STR
Definition: mmio.h:106
char * mm_strdup(const char *s)
Definition: mmio.c:443
#define MM_MAX_TOKEN_LENGTH
Definition: mmio.h:14
#define MM_INT_STR
Definition: mmio.h:111
#define mm_set_skew(typecode)
Definition: mmio.h:67
int mm_read_banner(FILE *f, MM_typecode *matcode)
Definition: mmio.c:92
#define mm_set_general(typecode)
Definition: mmio.h:66
#define mm_is_general(typecode)
Definition: mmio.h:44
#define mm_is_real(typecode)
Definition: mmio.h:39
int mm_read_mtx_array_size(FILE *f, int *M, int *N)
Definition: mmio.c:215
#define mm_is_sparse(typecode)
Definition: mmio.h:33
#define mm_is_hermitian(typecode)
Definition: mmio.h:46
#define MM_MTX_STR
Definition: mmio.h:104
#define MM_COULD_NOT_READ_FILE
Definition: mmio.h:79
int mm_is_valid(MM_typecode matcode)
Definition: mmio.c:82
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode)
Definition: mmio.c:394
#define MM_COMPLEX_STR
Definition: mmio.h:109
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, double **val_, int **I_, int **J_)
Definition: mmio.c:16
char * mm_typecode_to_str(MM_typecode matcode)
Definition: mmio.c:450
int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode)
Definition: mmio.c:260
#define MM_SKEW_STR
Definition: mmio.h:115
#define mm_is_integer(typecode)
Definition: mmio.h:41
#define MM_REAL_STR
Definition: mmio.h:110
#define MM_HERM_STR
Definition: mmio.h:114
char MM_typecode[4]
Definition: mmio.h:16
int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)
Definition: mmio.c:176
#define MM_NO_HEADER
Definition: mmio.h:82
int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *real, double *imag, MM_typecode matcode)
Definition: mmio.c:293
#define mm_is_matrix(typecode)
Definition: mmio.h:31
#define mm_set_symmetric(typecode)
Definition: mmio.h:65
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J, double **val, MM_typecode *matcode)
Definition: mmio.c:328
#define MM_COULD_NOT_WRITE_FILE
Definition: mmio.h:85
#define mm_is_complex(typecode)
Definition: mmio.h:38
int mm_write_mtx_array_size(FILE *f, int M, int N)
Definition: mmio.c:244
#define mm_is_symmetric(typecode)
Definition: mmio.h:43
#define mm_set_sparse(typecode)
Definition: mmio.h:57
#define mm_set_integer(typecode)
Definition: mmio.h:62