xref: /petsc/src/mat/tests/mmio.c (revision d8e47b638cf8f604a99e9678e1df24f82d959cd7)
189928cc5SHong Zhang /*
289928cc5SHong Zhang    Matrix Market I/O library for ANSI C
389928cc5SHong Zhang 
489928cc5SHong Zhang    See https://math.nist.gov/MatrixMarket/ for details.
589928cc5SHong Zhang */
689928cc5SHong Zhang 
789928cc5SHong Zhang #include <stdlib.h>
889928cc5SHong Zhang #include <stdio.h>
989928cc5SHong Zhang #include <string.h>
1089928cc5SHong Zhang #include <ctype.h>
1189928cc5SHong Zhang 
1289928cc5SHong Zhang #include "mmio.h"
1389928cc5SHong Zhang 
1489928cc5SHong Zhang static char mm_buffer[MM_MAX_LINE_LENGTH];
1589928cc5SHong Zhang 
mm_read_unsymmetric_sparse(const char * fname,int * M_,int * N_,int * nz_,double ** val_,int ** I_,int ** J_)1689928cc5SHong Zhang int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, double **val_, int **I_, int **J_)
1789928cc5SHong Zhang {
1889928cc5SHong Zhang   FILE       *f;
1989928cc5SHong Zhang   MM_typecode matcode;
2089928cc5SHong Zhang   int         M, N, nz;
2189928cc5SHong Zhang   int         i;
2289928cc5SHong Zhang   double     *val;
2389928cc5SHong Zhang   int        *ia, *ja;
2489928cc5SHong Zhang 
2589928cc5SHong Zhang   if ((f = fopen(fname, "r")) == NULL) return -1;
2689928cc5SHong Zhang 
2789928cc5SHong Zhang   if (mm_read_banner(f, &matcode) != 0) {
2889928cc5SHong Zhang     printf("mm_read_unsymmetric: Could not process Matrix Market banner ");
2989928cc5SHong Zhang     printf(" in file [%s]\n", fname);
3089928cc5SHong Zhang     return -1;
3189928cc5SHong Zhang   }
3289928cc5SHong Zhang 
3389928cc5SHong Zhang   if (!(mm_is_real(matcode) && mm_is_matrix(matcode) && mm_is_sparse(matcode))) {
3489928cc5SHong Zhang     fprintf(stderr, "This application does not support ");
3589928cc5SHong Zhang     fprintf(stderr, "Market Market type: [%s]\n", mm_typecode_to_str(matcode));
3689928cc5SHong Zhang     return -1;
3789928cc5SHong Zhang   }
3889928cc5SHong Zhang 
3989928cc5SHong Zhang   /* find out size of sparse matrix: M, N, nz .... */
4089928cc5SHong Zhang 
4189928cc5SHong Zhang   if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) {
4289928cc5SHong Zhang     fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n");
4389928cc5SHong Zhang     return -1;
4489928cc5SHong Zhang   }
4589928cc5SHong Zhang 
4689928cc5SHong Zhang   *M_  = M;
4789928cc5SHong Zhang   *N_  = N;
4889928cc5SHong Zhang   *nz_ = nz;
4989928cc5SHong Zhang 
50baca6076SPierre Jolivet   /* reserve memory for matrices */
5189928cc5SHong Zhang 
5289928cc5SHong Zhang   ia  = (int *)malloc(nz * sizeof(int));
5389928cc5SHong Zhang   ja  = (int *)malloc(nz * sizeof(int));
5489928cc5SHong Zhang   val = (double *)malloc(nz * sizeof(double));
5589928cc5SHong Zhang 
5689928cc5SHong Zhang   *val_ = val;
5789928cc5SHong Zhang   *I_   = ia;
5889928cc5SHong Zhang   *J_   = ja;
5989928cc5SHong Zhang 
6089928cc5SHong Zhang   /* NOTE: when reading in doubles, ANSI C requires the use of the "l"  */
6189928cc5SHong Zhang   /*   specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
6289928cc5SHong Zhang   /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */
6389928cc5SHong Zhang 
6489928cc5SHong Zhang   for (i = 0; i < nz; i++) {
6589928cc5SHong Zhang     if (fscanf(f, "%d %d %lg\n", &ia[i], &ja[i], &val[i]) != 3) {
6689928cc5SHong Zhang       fprintf(stderr, "read_unsymmetric_sparse(): could not parse i, j and nonzero.\n");
6789928cc5SHong Zhang       return -1;
6889928cc5SHong Zhang     }
6989928cc5SHong Zhang     ia[i]--; /* adjust from 1-based to 0-based */
7089928cc5SHong Zhang     ja[i]--;
7189928cc5SHong Zhang   }
7289928cc5SHong Zhang   fclose(f);
7389928cc5SHong Zhang 
7489928cc5SHong Zhang   return 0;
7589928cc5SHong Zhang }
7689928cc5SHong Zhang 
mm_is_valid(MM_typecode matcode)7789928cc5SHong Zhang int mm_is_valid(MM_typecode matcode)
7889928cc5SHong Zhang {
7989928cc5SHong Zhang   if (!mm_is_matrix(matcode)) return 0;
8089928cc5SHong Zhang   if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;
8189928cc5SHong Zhang   if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;
8289928cc5SHong Zhang   if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) || mm_is_skew(matcode))) return 0;
8389928cc5SHong Zhang   return 1;
8489928cc5SHong Zhang }
8589928cc5SHong Zhang 
mm_read_banner(FILE * f,MM_typecode * matcode)8689928cc5SHong Zhang int mm_read_banner(FILE *f, MM_typecode *matcode)
8789928cc5SHong Zhang {
8889928cc5SHong Zhang   char  line[MM_MAX_LINE_LENGTH];
8989928cc5SHong Zhang   char  banner[MM_MAX_TOKEN_LENGTH];
9089928cc5SHong Zhang   char  mtx[MM_MAX_TOKEN_LENGTH];
9189928cc5SHong Zhang   char  crd[MM_MAX_TOKEN_LENGTH];
9289928cc5SHong Zhang   char  data_type[MM_MAX_TOKEN_LENGTH];
9389928cc5SHong Zhang   char  storage_scheme[MM_MAX_TOKEN_LENGTH];
9489928cc5SHong Zhang   char *p;
9589928cc5SHong Zhang 
9689928cc5SHong Zhang   mm_clear_typecode(matcode);
9789928cc5SHong Zhang 
9889928cc5SHong Zhang   if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF;
9989928cc5SHong Zhang 
10089928cc5SHong Zhang   if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type, storage_scheme) != 5) return MM_PREMATURE_EOF;
10189928cc5SHong Zhang 
102*6497c311SBarry Smith   for (p = mtx; *p != '\0'; *p = (char)tolower(*p), p++); /* convert to lower case */
103*6497c311SBarry Smith   for (p = crd; *p != '\0'; *p = (char)tolower(*p), p++);
104*6497c311SBarry Smith   for (p = data_type; *p != '\0'; *p = (char)tolower(*p), p++);
105*6497c311SBarry Smith   for (p = storage_scheme; *p != '\0'; *p = (char)tolower(*p), p++);
10689928cc5SHong Zhang 
10789928cc5SHong Zhang   /* check for banner */
10889928cc5SHong Zhang   if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0) return MM_NO_HEADER;
10989928cc5SHong Zhang 
11089928cc5SHong Zhang   /* first field should be "mtx" */
11189928cc5SHong Zhang   if (strcmp(mtx, MM_MTX_STR) != 0) return MM_UNSUPPORTED_TYPE;
11289928cc5SHong Zhang   mm_set_matrix(matcode);
11389928cc5SHong Zhang 
11489928cc5SHong Zhang   /* second field describes whether this is a sparse matrix (in coordinate
11589928cc5SHong Zhang             storgae) or a dense array */
11689928cc5SHong Zhang 
11789928cc5SHong Zhang   if (strcmp(crd, MM_SPARSE_STR) == 0) mm_set_sparse(matcode);
11889928cc5SHong Zhang   else if (strcmp(crd, MM_DENSE_STR) == 0) mm_set_dense(matcode);
11989928cc5SHong Zhang   else return MM_UNSUPPORTED_TYPE;
12089928cc5SHong Zhang 
12189928cc5SHong Zhang   /* third field */
12289928cc5SHong Zhang 
12389928cc5SHong Zhang   if (strcmp(data_type, MM_REAL_STR) == 0) mm_set_real(matcode);
12489928cc5SHong Zhang   else if (strcmp(data_type, MM_COMPLEX_STR) == 0) mm_set_complex(matcode);
12589928cc5SHong Zhang   else if (strcmp(data_type, MM_PATTERN_STR) == 0) mm_set_pattern(matcode);
12689928cc5SHong Zhang   else if (strcmp(data_type, MM_INT_STR) == 0) mm_set_integer(matcode);
12789928cc5SHong Zhang   else return MM_UNSUPPORTED_TYPE;
12889928cc5SHong Zhang 
12989928cc5SHong Zhang   /* fourth field */
13089928cc5SHong Zhang 
13189928cc5SHong Zhang   if (strcmp(storage_scheme, MM_GENERAL_STR) == 0) mm_set_general(matcode);
13289928cc5SHong Zhang   else if (strcmp(storage_scheme, MM_SYMM_STR) == 0) mm_set_symmetric(matcode);
13389928cc5SHong Zhang   else if (strcmp(storage_scheme, MM_HERM_STR) == 0) mm_set_hermitian(matcode);
13489928cc5SHong Zhang   else if (strcmp(storage_scheme, MM_SKEW_STR) == 0) mm_set_skew(matcode);
13589928cc5SHong Zhang   else return MM_UNSUPPORTED_TYPE;
13689928cc5SHong Zhang 
13789928cc5SHong Zhang   return 0;
13889928cc5SHong Zhang }
13989928cc5SHong Zhang 
mm_write_mtx_crd_size(FILE * f,int M,int N,int nz)14089928cc5SHong Zhang int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)
14189928cc5SHong Zhang {
14289928cc5SHong Zhang   if (fprintf(f, "%d %d %d\n", M, N, nz) < 0) return MM_COULD_NOT_WRITE_FILE;
14389928cc5SHong Zhang   else return 0;
14489928cc5SHong Zhang }
14589928cc5SHong Zhang 
mm_read_mtx_crd_size(FILE * f,int * M,int * N,int * nz)14689928cc5SHong Zhang int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz)
14789928cc5SHong Zhang {
14889928cc5SHong Zhang   char line[MM_MAX_LINE_LENGTH];
14989928cc5SHong Zhang   int  num_items_read;
15089928cc5SHong Zhang 
15189928cc5SHong Zhang   /* set return null parameter values, in case we exit with errors */
15289928cc5SHong Zhang   *M = *N = *nz = 0;
15389928cc5SHong Zhang 
15489928cc5SHong Zhang   /* now continue scanning until you reach the end-of-comments */
15589928cc5SHong Zhang   do {
15689928cc5SHong Zhang     if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF;
15789928cc5SHong Zhang   } while (line[0] == '%');
15889928cc5SHong Zhang 
15989928cc5SHong Zhang   /* line[] is either blank or has M,N, nz */
16089928cc5SHong Zhang   if (sscanf(line, "%d %d %d", M, N, nz) == 3) return 0;
16189928cc5SHong Zhang 
16289928cc5SHong Zhang   else do {
16389928cc5SHong Zhang       num_items_read = fscanf(f, "%d %d %d", M, N, nz);
16489928cc5SHong Zhang       if (num_items_read == EOF) return MM_PREMATURE_EOF;
16589928cc5SHong Zhang     } while (num_items_read != 3);
16689928cc5SHong Zhang 
16789928cc5SHong Zhang   return 0;
16889928cc5SHong Zhang }
16989928cc5SHong Zhang 
mm_read_mtx_array_size(FILE * f,int * M,int * N)17089928cc5SHong Zhang int mm_read_mtx_array_size(FILE *f, int *M, int *N)
17189928cc5SHong Zhang {
17289928cc5SHong Zhang   char line[MM_MAX_LINE_LENGTH];
17389928cc5SHong Zhang   int  num_items_read;
17489928cc5SHong Zhang   /* set return null parameter values, in case we exit with errors */
17589928cc5SHong Zhang   *M = *N = 0;
17689928cc5SHong Zhang 
17789928cc5SHong Zhang   /* now continue scanning until you reach the end-of-comments */
17889928cc5SHong Zhang   do {
17989928cc5SHong Zhang     if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF;
18089928cc5SHong Zhang   } while (line[0] == '%');
18189928cc5SHong Zhang 
18289928cc5SHong Zhang   /* line[] is either blank or has M,N, nz */
18389928cc5SHong Zhang   if (sscanf(line, "%d %d", M, N) == 2) return 0;
18489928cc5SHong Zhang 
18589928cc5SHong Zhang   else /* we have a blank line */ do {
18689928cc5SHong Zhang       num_items_read = fscanf(f, "%d %d", M, N);
18789928cc5SHong Zhang       if (num_items_read == EOF) return MM_PREMATURE_EOF;
18889928cc5SHong Zhang     } while (num_items_read != 2);
18989928cc5SHong Zhang 
19089928cc5SHong Zhang   return 0;
19189928cc5SHong Zhang }
19289928cc5SHong Zhang 
mm_write_mtx_array_size(FILE * f,int M,int N)19389928cc5SHong Zhang int mm_write_mtx_array_size(FILE *f, int M, int N)
19489928cc5SHong Zhang {
19589928cc5SHong Zhang   if (fprintf(f, "%d %d\n", M, N) < 0) return MM_COULD_NOT_WRITE_FILE;
19689928cc5SHong Zhang   else return 0;
19789928cc5SHong Zhang }
19889928cc5SHong Zhang 
19989928cc5SHong Zhang /*-------------------------------------------------------------------------*/
20089928cc5SHong Zhang 
20189928cc5SHong Zhang /******************************************************************/
20289928cc5SHong Zhang /* use when ia[], ja[], and val[] are already allocated */
20389928cc5SHong Zhang /******************************************************************/
20489928cc5SHong Zhang 
mm_read_mtx_crd_data(FILE * f,int M,int N,int nz,int ia[],int ja[],double val[],MM_typecode matcode)20589928cc5SHong Zhang int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int ia[], int ja[], double val[], MM_typecode matcode)
20689928cc5SHong Zhang {
20789928cc5SHong Zhang   int i;
20889928cc5SHong Zhang   if (mm_is_complex(matcode)) {
20989928cc5SHong Zhang     for (i = 0; i < nz; i++)
21089928cc5SHong Zhang       if (fscanf(f, "%d %d %lg %lg", &ia[i], &ja[i], &val[2 * i], &val[2 * i + 1]) != 4) return MM_PREMATURE_EOF;
21189928cc5SHong Zhang   } else if (mm_is_real(matcode)) {
21289928cc5SHong Zhang     for (i = 0; i < nz; i++) {
21389928cc5SHong Zhang       if (fscanf(f, "%d %d %lg\n", &ia[i], &ja[i], &val[i]) != 3) return MM_PREMATURE_EOF;
21489928cc5SHong Zhang     }
21589928cc5SHong Zhang   }
21689928cc5SHong Zhang 
21789928cc5SHong Zhang   else if (mm_is_pattern(matcode)) {
21889928cc5SHong Zhang     for (i = 0; i < nz; i++)
21989928cc5SHong Zhang       if (fscanf(f, "%d %d", &ia[i], &ja[i]) != 2) return MM_PREMATURE_EOF;
22089928cc5SHong Zhang   } else return MM_UNSUPPORTED_TYPE;
22189928cc5SHong Zhang 
22289928cc5SHong Zhang   return 0;
22389928cc5SHong Zhang }
22489928cc5SHong Zhang 
mm_read_mtx_crd_entry(FILE * f,int * ia,int * ja,double * real,double * imag,MM_typecode matcode)22589928cc5SHong Zhang int mm_read_mtx_crd_entry(FILE *f, int *ia, int *ja, double *real, double *imag, MM_typecode matcode)
22689928cc5SHong Zhang {
22789928cc5SHong Zhang   if (mm_is_complex(matcode)) {
22889928cc5SHong Zhang     if (fscanf(f, "%d %d %lg %lg", ia, ja, real, imag) != 4) return MM_PREMATURE_EOF;
22989928cc5SHong Zhang   } else if (mm_is_real(matcode)) {
23089928cc5SHong Zhang     if (fscanf(f, "%d %d %lg\n", ia, ja, real) != 3) return MM_PREMATURE_EOF;
23189928cc5SHong Zhang 
23289928cc5SHong Zhang   }
23389928cc5SHong Zhang 
23489928cc5SHong Zhang   else if (mm_is_pattern(matcode)) {
23589928cc5SHong Zhang     if (fscanf(f, "%d %d", ia, ja) != 2) return MM_PREMATURE_EOF;
23689928cc5SHong Zhang   } else return MM_UNSUPPORTED_TYPE;
23789928cc5SHong Zhang 
23889928cc5SHong Zhang   return 0;
23989928cc5SHong Zhang }
24089928cc5SHong Zhang 
24189928cc5SHong Zhang /************************************************************************
24289928cc5SHong Zhang     mm_read_mtx_crd()  fills M, N, nz, array of values, and return
24389928cc5SHong Zhang                         type code, e.g. 'MCRS'
24489928cc5SHong Zhang 
24589928cc5SHong Zhang                         if matrix is complex, values[] is of size 2*nz,
24689928cc5SHong Zhang                             (nz pairs of real/imaginary values)
24789928cc5SHong Zhang ************************************************************************/
24889928cc5SHong Zhang 
mm_read_mtx_crd(char * fname,int * M,int * N,int * nz,int ** ia,int ** ja,double ** val,MM_typecode * matcode)24989928cc5SHong Zhang int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **ia, int **ja, double **val, MM_typecode *matcode)
25089928cc5SHong Zhang {
25189928cc5SHong Zhang   int   ret_code;
25289928cc5SHong Zhang   FILE *f;
25389928cc5SHong Zhang 
25489928cc5SHong Zhang   if (strcmp(fname, "stdin") == 0) f = stdin;
25589928cc5SHong Zhang   else if ((f = fopen(fname, "r")) == NULL) return MM_COULD_NOT_READ_FILE;
25689928cc5SHong Zhang 
25789928cc5SHong Zhang   if ((ret_code = mm_read_banner(f, matcode)) != 0) return ret_code;
25889928cc5SHong Zhang 
25989928cc5SHong Zhang   if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) && mm_is_matrix(*matcode))) return MM_UNSUPPORTED_TYPE;
26089928cc5SHong Zhang 
26189928cc5SHong Zhang   if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0) return ret_code;
26289928cc5SHong Zhang 
26389928cc5SHong Zhang   *ia  = (int *)malloc(*nz * sizeof(int));
26489928cc5SHong Zhang   *ja  = (int *)malloc(*nz * sizeof(int));
26589928cc5SHong Zhang   *val = NULL;
26689928cc5SHong Zhang 
26789928cc5SHong Zhang   if (mm_is_complex(*matcode)) {
26889928cc5SHong Zhang     *val     = (double *)malloc(*nz * 2 * sizeof(double));
26989928cc5SHong Zhang     ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *ia, *ja, *val, *matcode);
27089928cc5SHong Zhang     if (ret_code != 0) return ret_code;
27189928cc5SHong Zhang   } else if (mm_is_real(*matcode)) {
27289928cc5SHong Zhang     *val     = (double *)malloc(*nz * sizeof(double));
27389928cc5SHong Zhang     ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *ia, *ja, *val, *matcode);
27489928cc5SHong Zhang     if (ret_code != 0) return ret_code;
27589928cc5SHong Zhang   }
27689928cc5SHong Zhang 
27789928cc5SHong Zhang   else if (mm_is_pattern(*matcode)) {
27889928cc5SHong Zhang     ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *ia, *ja, *val, *matcode);
27989928cc5SHong Zhang     if (ret_code != 0) return ret_code;
28089928cc5SHong Zhang   }
28189928cc5SHong Zhang 
28289928cc5SHong Zhang   if (f != stdin) fclose(f);
28389928cc5SHong Zhang   return 0;
28489928cc5SHong Zhang }
28589928cc5SHong Zhang 
mm_write_banner(FILE * f,MM_typecode matcode)28689928cc5SHong Zhang int mm_write_banner(FILE *f, MM_typecode matcode)
28789928cc5SHong Zhang {
28889928cc5SHong Zhang   char *str = mm_typecode_to_str(matcode);
28989928cc5SHong Zhang   int   ret_code;
29089928cc5SHong Zhang 
29189928cc5SHong Zhang   ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
29289928cc5SHong Zhang   if (ret_code < 0) return MM_COULD_NOT_WRITE_FILE;
29389928cc5SHong Zhang   else return 0;
29489928cc5SHong Zhang }
29589928cc5SHong Zhang 
mm_write_mtx_crd(char fname[],int M,int N,int nz,int ia[],int ja[],double val[],MM_typecode matcode)29689928cc5SHong Zhang int mm_write_mtx_crd(char fname[], int M, int N, int nz, int ia[], int ja[], double val[], MM_typecode matcode)
29789928cc5SHong Zhang {
29889928cc5SHong Zhang   FILE *f;
29989928cc5SHong Zhang   int   i;
30089928cc5SHong Zhang 
30189928cc5SHong Zhang   if (strcmp(fname, "stdout") == 0) f = stdout;
30289928cc5SHong Zhang   else if ((f = fopen(fname, "w")) == NULL) return MM_COULD_NOT_WRITE_FILE;
30389928cc5SHong Zhang 
30489928cc5SHong Zhang   /* print banner followed by typecode */
30589928cc5SHong Zhang   fprintf(f, "%s ", MatrixMarketBanner);
30689928cc5SHong Zhang   fprintf(f, "%s\n", mm_typecode_to_str(matcode));
30789928cc5SHong Zhang 
30889928cc5SHong Zhang   /* print matrix sizes and nonzeros */
30989928cc5SHong Zhang   fprintf(f, "%d %d %d\n", M, N, nz);
31089928cc5SHong Zhang 
31189928cc5SHong Zhang   /* print values */
31289928cc5SHong Zhang   if (mm_is_pattern(matcode))
31389928cc5SHong Zhang     for (i = 0; i < nz; i++) fprintf(f, "%d %d\n", ia[i], ja[i]);
31489928cc5SHong Zhang   else if (mm_is_real(matcode))
31589928cc5SHong Zhang     for (i = 0; i < nz; i++) fprintf(f, "%d %d %20.16g\n", ia[i], ja[i], val[i]);
31689928cc5SHong Zhang   else if (mm_is_complex(matcode))
31789928cc5SHong Zhang     for (i = 0; i < nz; i++) fprintf(f, "%d %d %20.16g %20.16g\n", ia[i], ja[i], val[2 * i], val[2 * i + 1]);
31889928cc5SHong Zhang   else {
31989928cc5SHong Zhang     if (f != stdout) fclose(f);
32089928cc5SHong Zhang     return MM_UNSUPPORTED_TYPE;
32189928cc5SHong Zhang   }
32289928cc5SHong Zhang 
32389928cc5SHong Zhang   if (f != stdout) fclose(f);
32489928cc5SHong Zhang 
32589928cc5SHong Zhang   return 0;
32689928cc5SHong Zhang }
32789928cc5SHong Zhang 
mm_typecode_to_str(MM_typecode matcode)32889928cc5SHong Zhang char *mm_typecode_to_str(MM_typecode matcode)
32989928cc5SHong Zhang {
33089928cc5SHong Zhang   const char *types[4];
33189928cc5SHong Zhang 
33289928cc5SHong Zhang   /* check for MTX type */
33389928cc5SHong Zhang   if (mm_is_matrix(matcode)) types[0] = MM_MTX_STR;
33489928cc5SHong Zhang   else return NULL;
33589928cc5SHong Zhang 
33689928cc5SHong Zhang   /* check for CRD or ARR matrix */
33789928cc5SHong Zhang   if (mm_is_sparse(matcode)) types[1] = MM_SPARSE_STR;
33889928cc5SHong Zhang   else if (mm_is_dense(matcode)) types[1] = MM_DENSE_STR;
33989928cc5SHong Zhang   else return NULL;
34089928cc5SHong Zhang 
34189928cc5SHong Zhang   /* check for element data type */
34289928cc5SHong Zhang   if (mm_is_real(matcode)) types[2] = MM_REAL_STR;
34389928cc5SHong Zhang   else if (mm_is_complex(matcode)) types[2] = MM_COMPLEX_STR;
34489928cc5SHong Zhang   else if (mm_is_pattern(matcode)) types[2] = MM_PATTERN_STR;
34589928cc5SHong Zhang   else if (mm_is_integer(matcode)) types[2] = MM_INT_STR;
34689928cc5SHong Zhang   else return NULL;
34789928cc5SHong Zhang 
34889928cc5SHong Zhang   /* check for symmetry type */
34989928cc5SHong Zhang   if (mm_is_general(matcode)) types[3] = MM_GENERAL_STR;
35089928cc5SHong Zhang   else if (mm_is_symmetric(matcode)) types[3] = MM_SYMM_STR;
35189928cc5SHong Zhang   else if (mm_is_hermitian(matcode)) types[3] = MM_HERM_STR;
35289928cc5SHong Zhang   else if (mm_is_skew(matcode)) types[3] = MM_SKEW_STR;
35389928cc5SHong Zhang   else return NULL;
35489928cc5SHong Zhang 
35589928cc5SHong Zhang   mm_buffer[0] = 0;
356a364092eSJacob Faibussowitsch   snprintf(mm_buffer, sizeof(mm_buffer) / sizeof(mm_buffer[0]), "%s %s %s %s", types[0], types[1], types[2], types[3]);
35789928cc5SHong Zhang   return mm_buffer;
35889928cc5SHong Zhang }
359