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 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 5089928cc5SHong Zhang /* reseve 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 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 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 10289928cc5SHong Zhang for (p = mtx; *p != '\0'; *p = tolower(*p), p++) 10389928cc5SHong Zhang ; /* convert to lower case */ 10489928cc5SHong Zhang for (p = crd; *p != '\0'; *p = tolower(*p), p++) 10589928cc5SHong Zhang ; 10689928cc5SHong Zhang for (p = data_type; *p != '\0'; *p = tolower(*p), p++) 10789928cc5SHong Zhang ; 10889928cc5SHong Zhang for (p = storage_scheme; *p != '\0'; *p = tolower(*p), p++) 10989928cc5SHong Zhang ; 11089928cc5SHong Zhang 11189928cc5SHong Zhang /* check for banner */ 11289928cc5SHong Zhang if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0) return MM_NO_HEADER; 11389928cc5SHong Zhang 11489928cc5SHong Zhang /* first field should be "mtx" */ 11589928cc5SHong Zhang if (strcmp(mtx, MM_MTX_STR) != 0) return MM_UNSUPPORTED_TYPE; 11689928cc5SHong Zhang mm_set_matrix(matcode); 11789928cc5SHong Zhang 11889928cc5SHong Zhang /* second field describes whether this is a sparse matrix (in coordinate 11989928cc5SHong Zhang storgae) or a dense array */ 12089928cc5SHong Zhang 12189928cc5SHong Zhang if (strcmp(crd, MM_SPARSE_STR) == 0) mm_set_sparse(matcode); 12289928cc5SHong Zhang else if (strcmp(crd, MM_DENSE_STR) == 0) mm_set_dense(matcode); 12389928cc5SHong Zhang else return MM_UNSUPPORTED_TYPE; 12489928cc5SHong Zhang 12589928cc5SHong Zhang /* third field */ 12689928cc5SHong Zhang 12789928cc5SHong Zhang if (strcmp(data_type, MM_REAL_STR) == 0) mm_set_real(matcode); 12889928cc5SHong Zhang else if (strcmp(data_type, MM_COMPLEX_STR) == 0) mm_set_complex(matcode); 12989928cc5SHong Zhang else if (strcmp(data_type, MM_PATTERN_STR) == 0) mm_set_pattern(matcode); 13089928cc5SHong Zhang else if (strcmp(data_type, MM_INT_STR) == 0) mm_set_integer(matcode); 13189928cc5SHong Zhang else return MM_UNSUPPORTED_TYPE; 13289928cc5SHong Zhang 13389928cc5SHong Zhang /* fourth field */ 13489928cc5SHong Zhang 13589928cc5SHong Zhang if (strcmp(storage_scheme, MM_GENERAL_STR) == 0) mm_set_general(matcode); 13689928cc5SHong Zhang else if (strcmp(storage_scheme, MM_SYMM_STR) == 0) mm_set_symmetric(matcode); 13789928cc5SHong Zhang else if (strcmp(storage_scheme, MM_HERM_STR) == 0) mm_set_hermitian(matcode); 13889928cc5SHong Zhang else if (strcmp(storage_scheme, MM_SKEW_STR) == 0) mm_set_skew(matcode); 13989928cc5SHong Zhang else return MM_UNSUPPORTED_TYPE; 14089928cc5SHong Zhang 14189928cc5SHong Zhang return 0; 14289928cc5SHong Zhang } 14389928cc5SHong Zhang 14489928cc5SHong Zhang int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz) 14589928cc5SHong Zhang { 14689928cc5SHong Zhang if (fprintf(f, "%d %d %d\n", M, N, nz) < 0) return MM_COULD_NOT_WRITE_FILE; 14789928cc5SHong Zhang else return 0; 14889928cc5SHong Zhang } 14989928cc5SHong Zhang 15089928cc5SHong Zhang int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz) 15189928cc5SHong Zhang { 15289928cc5SHong Zhang char line[MM_MAX_LINE_LENGTH]; 15389928cc5SHong Zhang int num_items_read; 15489928cc5SHong Zhang 15589928cc5SHong Zhang /* set return null parameter values, in case we exit with errors */ 15689928cc5SHong Zhang *M = *N = *nz = 0; 15789928cc5SHong Zhang 15889928cc5SHong Zhang /* now continue scanning until you reach the end-of-comments */ 15989928cc5SHong Zhang do { 16089928cc5SHong Zhang if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF; 16189928cc5SHong Zhang } while (line[0] == '%'); 16289928cc5SHong Zhang 16389928cc5SHong Zhang /* line[] is either blank or has M,N, nz */ 16489928cc5SHong Zhang if (sscanf(line, "%d %d %d", M, N, nz) == 3) return 0; 16589928cc5SHong Zhang 16689928cc5SHong Zhang else do { 16789928cc5SHong Zhang num_items_read = fscanf(f, "%d %d %d", M, N, nz); 16889928cc5SHong Zhang if (num_items_read == EOF) return MM_PREMATURE_EOF; 16989928cc5SHong Zhang } while (num_items_read != 3); 17089928cc5SHong Zhang 17189928cc5SHong Zhang return 0; 17289928cc5SHong Zhang } 17389928cc5SHong Zhang 17489928cc5SHong Zhang int mm_read_mtx_array_size(FILE *f, int *M, int *N) 17589928cc5SHong Zhang { 17689928cc5SHong Zhang char line[MM_MAX_LINE_LENGTH]; 17789928cc5SHong Zhang int num_items_read; 17889928cc5SHong Zhang /* set return null parameter values, in case we exit with errors */ 17989928cc5SHong Zhang *M = *N = 0; 18089928cc5SHong Zhang 18189928cc5SHong Zhang /* now continue scanning until you reach the end-of-comments */ 18289928cc5SHong Zhang do { 18389928cc5SHong Zhang if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) return MM_PREMATURE_EOF; 18489928cc5SHong Zhang } while (line[0] == '%'); 18589928cc5SHong Zhang 18689928cc5SHong Zhang /* line[] is either blank or has M,N, nz */ 18789928cc5SHong Zhang if (sscanf(line, "%d %d", M, N) == 2) return 0; 18889928cc5SHong Zhang 18989928cc5SHong Zhang else /* we have a blank line */ do { 19089928cc5SHong Zhang num_items_read = fscanf(f, "%d %d", M, N); 19189928cc5SHong Zhang if (num_items_read == EOF) return MM_PREMATURE_EOF; 19289928cc5SHong Zhang } while (num_items_read != 2); 19389928cc5SHong Zhang 19489928cc5SHong Zhang return 0; 19589928cc5SHong Zhang } 19689928cc5SHong Zhang 19789928cc5SHong Zhang int mm_write_mtx_array_size(FILE *f, int M, int N) 19889928cc5SHong Zhang { 19989928cc5SHong Zhang if (fprintf(f, "%d %d\n", M, N) < 0) return MM_COULD_NOT_WRITE_FILE; 20089928cc5SHong Zhang else return 0; 20189928cc5SHong Zhang } 20289928cc5SHong Zhang 20389928cc5SHong Zhang /*-------------------------------------------------------------------------*/ 20489928cc5SHong Zhang 20589928cc5SHong Zhang /******************************************************************/ 20689928cc5SHong Zhang /* use when ia[], ja[], and val[] are already allocated */ 20789928cc5SHong Zhang /******************************************************************/ 20889928cc5SHong Zhang 20989928cc5SHong Zhang int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int ia[], int ja[], double val[], MM_typecode matcode) 21089928cc5SHong Zhang { 21189928cc5SHong Zhang int i; 21289928cc5SHong Zhang if (mm_is_complex(matcode)) { 21389928cc5SHong Zhang for (i = 0; i < nz; i++) 21489928cc5SHong Zhang if (fscanf(f, "%d %d %lg %lg", &ia[i], &ja[i], &val[2 * i], &val[2 * i + 1]) != 4) return MM_PREMATURE_EOF; 21589928cc5SHong Zhang } else if (mm_is_real(matcode)) { 21689928cc5SHong Zhang for (i = 0; i < nz; i++) { 21789928cc5SHong Zhang if (fscanf(f, "%d %d %lg\n", &ia[i], &ja[i], &val[i]) != 3) return MM_PREMATURE_EOF; 21889928cc5SHong Zhang } 21989928cc5SHong Zhang } 22089928cc5SHong Zhang 22189928cc5SHong Zhang else if (mm_is_pattern(matcode)) { 22289928cc5SHong Zhang for (i = 0; i < nz; i++) 22389928cc5SHong Zhang if (fscanf(f, "%d %d", &ia[i], &ja[i]) != 2) return MM_PREMATURE_EOF; 22489928cc5SHong Zhang } else return MM_UNSUPPORTED_TYPE; 22589928cc5SHong Zhang 22689928cc5SHong Zhang return 0; 22789928cc5SHong Zhang } 22889928cc5SHong Zhang 22989928cc5SHong Zhang int mm_read_mtx_crd_entry(FILE *f, int *ia, int *ja, double *real, double *imag, MM_typecode matcode) 23089928cc5SHong Zhang { 23189928cc5SHong Zhang if (mm_is_complex(matcode)) { 23289928cc5SHong Zhang if (fscanf(f, "%d %d %lg %lg", ia, ja, real, imag) != 4) return MM_PREMATURE_EOF; 23389928cc5SHong Zhang } else if (mm_is_real(matcode)) { 23489928cc5SHong Zhang if (fscanf(f, "%d %d %lg\n", ia, ja, real) != 3) return MM_PREMATURE_EOF; 23589928cc5SHong Zhang 23689928cc5SHong Zhang } 23789928cc5SHong Zhang 23889928cc5SHong Zhang else if (mm_is_pattern(matcode)) { 23989928cc5SHong Zhang if (fscanf(f, "%d %d", ia, ja) != 2) return MM_PREMATURE_EOF; 24089928cc5SHong Zhang } else return MM_UNSUPPORTED_TYPE; 24189928cc5SHong Zhang 24289928cc5SHong Zhang return 0; 24389928cc5SHong Zhang } 24489928cc5SHong Zhang 24589928cc5SHong Zhang /************************************************************************ 24689928cc5SHong Zhang mm_read_mtx_crd() fills M, N, nz, array of values, and return 24789928cc5SHong Zhang type code, e.g. 'MCRS' 24889928cc5SHong Zhang 24989928cc5SHong Zhang if matrix is complex, values[] is of size 2*nz, 25089928cc5SHong Zhang (nz pairs of real/imaginary values) 25189928cc5SHong Zhang ************************************************************************/ 25289928cc5SHong Zhang 25389928cc5SHong Zhang int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **ia, int **ja, double **val, MM_typecode *matcode) 25489928cc5SHong Zhang { 25589928cc5SHong Zhang int ret_code; 25689928cc5SHong Zhang FILE *f; 25789928cc5SHong Zhang 25889928cc5SHong Zhang if (strcmp(fname, "stdin") == 0) f = stdin; 25989928cc5SHong Zhang else if ((f = fopen(fname, "r")) == NULL) return MM_COULD_NOT_READ_FILE; 26089928cc5SHong Zhang 26189928cc5SHong Zhang if ((ret_code = mm_read_banner(f, matcode)) != 0) return ret_code; 26289928cc5SHong Zhang 26389928cc5SHong Zhang if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) && mm_is_matrix(*matcode))) return MM_UNSUPPORTED_TYPE; 26489928cc5SHong Zhang 26589928cc5SHong Zhang if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0) return ret_code; 26689928cc5SHong Zhang 26789928cc5SHong Zhang *ia = (int *)malloc(*nz * sizeof(int)); 26889928cc5SHong Zhang *ja = (int *)malloc(*nz * sizeof(int)); 26989928cc5SHong Zhang *val = NULL; 27089928cc5SHong Zhang 27189928cc5SHong Zhang if (mm_is_complex(*matcode)) { 27289928cc5SHong Zhang *val = (double *)malloc(*nz * 2 * 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 } else if (mm_is_real(*matcode)) { 27689928cc5SHong Zhang *val = (double *)malloc(*nz * sizeof(double)); 27789928cc5SHong Zhang ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *ia, *ja, *val, *matcode); 27889928cc5SHong Zhang if (ret_code != 0) return ret_code; 27989928cc5SHong Zhang } 28089928cc5SHong Zhang 28189928cc5SHong Zhang else if (mm_is_pattern(*matcode)) { 28289928cc5SHong Zhang ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *ia, *ja, *val, *matcode); 28389928cc5SHong Zhang if (ret_code != 0) return ret_code; 28489928cc5SHong Zhang } 28589928cc5SHong Zhang 28689928cc5SHong Zhang if (f != stdin) fclose(f); 28789928cc5SHong Zhang return 0; 28889928cc5SHong Zhang } 28989928cc5SHong Zhang 29089928cc5SHong Zhang int mm_write_banner(FILE *f, MM_typecode matcode) 29189928cc5SHong Zhang { 29289928cc5SHong Zhang char *str = mm_typecode_to_str(matcode); 29389928cc5SHong Zhang int ret_code; 29489928cc5SHong Zhang 29589928cc5SHong Zhang ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str); 29689928cc5SHong Zhang if (ret_code < 0) return MM_COULD_NOT_WRITE_FILE; 29789928cc5SHong Zhang else return 0; 29889928cc5SHong Zhang } 29989928cc5SHong Zhang 30089928cc5SHong Zhang int mm_write_mtx_crd(char fname[], int M, int N, int nz, int ia[], int ja[], double val[], MM_typecode matcode) 30189928cc5SHong Zhang { 30289928cc5SHong Zhang FILE *f; 30389928cc5SHong Zhang int i; 30489928cc5SHong Zhang 30589928cc5SHong Zhang if (strcmp(fname, "stdout") == 0) f = stdout; 30689928cc5SHong Zhang else if ((f = fopen(fname, "w")) == NULL) return MM_COULD_NOT_WRITE_FILE; 30789928cc5SHong Zhang 30889928cc5SHong Zhang /* print banner followed by typecode */ 30989928cc5SHong Zhang fprintf(f, "%s ", MatrixMarketBanner); 31089928cc5SHong Zhang fprintf(f, "%s\n", mm_typecode_to_str(matcode)); 31189928cc5SHong Zhang 31289928cc5SHong Zhang /* print matrix sizes and nonzeros */ 31389928cc5SHong Zhang fprintf(f, "%d %d %d\n", M, N, nz); 31489928cc5SHong Zhang 31589928cc5SHong Zhang /* print values */ 31689928cc5SHong Zhang if (mm_is_pattern(matcode)) 31789928cc5SHong Zhang for (i = 0; i < nz; i++) fprintf(f, "%d %d\n", ia[i], ja[i]); 31889928cc5SHong Zhang else if (mm_is_real(matcode)) 31989928cc5SHong Zhang for (i = 0; i < nz; i++) fprintf(f, "%d %d %20.16g\n", ia[i], ja[i], val[i]); 32089928cc5SHong Zhang else if (mm_is_complex(matcode)) 32189928cc5SHong 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]); 32289928cc5SHong Zhang else { 32389928cc5SHong Zhang if (f != stdout) fclose(f); 32489928cc5SHong Zhang return MM_UNSUPPORTED_TYPE; 32589928cc5SHong Zhang } 32689928cc5SHong Zhang 32789928cc5SHong Zhang if (f != stdout) fclose(f); 32889928cc5SHong Zhang 32989928cc5SHong Zhang return 0; 33089928cc5SHong Zhang } 33189928cc5SHong Zhang 33289928cc5SHong Zhang char *mm_typecode_to_str(MM_typecode matcode) 33389928cc5SHong Zhang { 33489928cc5SHong Zhang const char *types[4]; 33589928cc5SHong Zhang 33689928cc5SHong Zhang /* check for MTX type */ 33789928cc5SHong Zhang if (mm_is_matrix(matcode)) types[0] = MM_MTX_STR; 33889928cc5SHong Zhang else return NULL; 33989928cc5SHong Zhang 34089928cc5SHong Zhang /* check for CRD or ARR matrix */ 34189928cc5SHong Zhang if (mm_is_sparse(matcode)) types[1] = MM_SPARSE_STR; 34289928cc5SHong Zhang else if (mm_is_dense(matcode)) types[1] = MM_DENSE_STR; 34389928cc5SHong Zhang else return NULL; 34489928cc5SHong Zhang 34589928cc5SHong Zhang /* check for element data type */ 34689928cc5SHong Zhang if (mm_is_real(matcode)) types[2] = MM_REAL_STR; 34789928cc5SHong Zhang else if (mm_is_complex(matcode)) types[2] = MM_COMPLEX_STR; 34889928cc5SHong Zhang else if (mm_is_pattern(matcode)) types[2] = MM_PATTERN_STR; 34989928cc5SHong Zhang else if (mm_is_integer(matcode)) types[2] = MM_INT_STR; 35089928cc5SHong Zhang else return NULL; 35189928cc5SHong Zhang 35289928cc5SHong Zhang /* check for symmetry type */ 35389928cc5SHong Zhang if (mm_is_general(matcode)) types[3] = MM_GENERAL_STR; 35489928cc5SHong Zhang else if (mm_is_symmetric(matcode)) types[3] = MM_SYMM_STR; 35589928cc5SHong Zhang else if (mm_is_hermitian(matcode)) types[3] = MM_HERM_STR; 35689928cc5SHong Zhang else if (mm_is_skew(matcode)) types[3] = MM_SKEW_STR; 35789928cc5SHong Zhang else return NULL; 35889928cc5SHong Zhang 35989928cc5SHong Zhang mm_buffer[0] = 0; 360*a364092eSJacob Faibussowitsch snprintf(mm_buffer, sizeof(mm_buffer) / sizeof(mm_buffer[0]), "%s %s %s %s", types[0], types[1], types[2], types[3]); 36189928cc5SHong Zhang return mm_buffer; 36289928cc5SHong Zhang } 363