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