# include # include # include # include # include # include "mm_io.h" /******************************************************************************/ int mm_is_valid ( MM_typecode matcode ) /******************************************************************************/ /* Purpose: MM_IS_VALID checks whether the MM header information is valid. Modified: 31 October 2008 Parameters: Input, MM_typecode MATCODE, the header information. Output, int MM_IS_VALID, is TRUE if the matrix code is valid. */ { if ( !mm_is_matrix ( matcode ) ) { return 0; } if ( mm_is_dense ( matcode ) && mm_is_pattern ( matcode ) ) { return 0; } if ( mm_is_real ( matcode ) && mm_is_hermitian ( matcode ) ) { return 0; } if ( mm_is_pattern ( matcode ) && ( mm_is_hermitian ( matcode ) || mm_is_skew ( matcode ) ) ) { return 0; } return 1; } /******************************************************************************/ int mm_read_banner ( FILE *f, MM_typecode *matcode ) /******************************************************************************/ /* Purpose: MM_READ_BANNER reads the header line of an MM file. Modified: 31 October 2008 Parameters: Input, FILE *F, a pointer to the input file. Output, MM_typecode *MATCODE, the header information. */ { char line[MM_MAX_LINE_LENGTH]; char banner[MM_MAX_TOKEN_LENGTH]; char mtx[MM_MAX_TOKEN_LENGTH]; char crd[MM_MAX_TOKEN_LENGTH]; char data_type[MM_MAX_TOKEN_LENGTH]; char storage_scheme[MM_MAX_TOKEN_LENGTH]; char *p; mm_clear_typecode ( matcode ); if ( fgets ( line, MM_MAX_LINE_LENGTH, f ) == NULL ) { return MM_PREMATURE_EOF; } if ( sscanf ( line, "%s %s %s %s %s", banner, mtx, crd, data_type, storage_scheme ) != 5 ) { return MM_PREMATURE_EOF; } for (p=mtx; *p!='\0'; *p=tolower(*p),p++); /* convert to lower case */ for (p=crd; *p!='\0'; *p=tolower(*p),p++); for (p=data_type; *p!='\0'; *p=tolower(*p),p++); for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++); /* check for banner */ if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0) return MM_NO_HEADER; /* first field should be "mtx" */ if (strcmp(mtx, MM_MTX_STR) != 0) return MM_UNSUPPORTED_TYPE; mm_set_matrix(matcode); /* second field describes whether this is a sparse matrix (in coordinate storgae) or a dense array */ if (strcmp(crd, MM_SPARSE_STR) == 0) mm_set_sparse(matcode); else if (strcmp(crd, MM_DENSE_STR) == 0) mm_set_dense(matcode); else return MM_UNSUPPORTED_TYPE; /* third field */ if (strcmp(data_type, MM_REAL_STR) == 0) { mm_set_real(matcode); } else if (strcmp(data_type, MM_COMPLEX_STR) == 0) { mm_set_complex(matcode); } else if (strcmp(data_type, MM_PATTERN_STR) == 0) { mm_set_pattern(matcode); } else if (strcmp(data_type, MM_INT_STR) == 0) { mm_set_integer(matcode); } else { return MM_UNSUPPORTED_TYPE; } /* fourth field */ if (strcmp(storage_scheme, MM_GENERAL_STR) == 0) mm_set_general(matcode); else if (strcmp(storage_scheme, MM_SYMM_STR) == 0) mm_set_symmetric(matcode); else if (strcmp(storage_scheme, MM_HERM_STR) == 0) mm_set_hermitian(matcode); else if (strcmp(storage_scheme, MM_SKEW_STR) == 0) mm_set_skew(matcode); else return MM_UNSUPPORTED_TYPE; return 0; } /******************************************************************************/ int mm_read_mtx_array_size ( FILE *f, int *M, int *N ) /******************************************************************************/ /* Purpose: MM_READ_MTX_ARRAY_SIZE reads the size line of an MM array file. Modified: 03 November 2008 Parameters: Input, FILE *F, a pointer to the input file. Output, int *M, the number of rows, as read from the file. Output, int *N, the number of columns, as read from the file. Output, MM_READ_MTX_ARRAY_SIZE, an error flag. 0, no error. */ { char line[MM_MAX_LINE_LENGTH]; int num_items_read; /* set return null parameter values, in case we exit with errors */ *M = 0; *N = 0; /* now continue scanning until you reach the end-of-comments */ do { if ( fgets ( line, MM_MAX_LINE_LENGTH, f ) == NULL ) { return MM_PREMATURE_EOF; } } while ( line[0] == '%' ); /* line[] is either blank or has M,N, nz */ if ( sscanf ( line, "%d %d", M, N ) == 2 ) { return 0; } else { do { num_items_read = fscanf ( f, "%d %d", M, N ); if ( num_items_read == EOF ) { return MM_PREMATURE_EOF; } } while ( num_items_read != 2 ); } return 0; } /******************************************************************************/ int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J, double **val, MM_typecode *matcode) /******************************************************************************/ /* Purpose: MM_READ_MTX_CRD reads the values in an MM coordinate file. Discussion: This function allocates the storage for the arrays. mm_read_mtx_crd() fills M, N, nz, array of values, and return type code, e.g. 'MCRS' if matrix is complex, values[] is of size 2*nz, (nz pairs of real/imaginary values) Modified: 31 October 2008 Parameters: */ { int ret_code; FILE *f; if (strcmp(fname, "stdin") == 0) f=stdin; else if ((f = fopen(fname, "r")) == NULL) return MM_COULD_NOT_READ_FILE; if ((ret_code = mm_read_banner(f, matcode)) != 0) return ret_code; if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) && mm_is_matrix(*matcode))) return MM_UNSUPPORTED_TYPE; if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0) return ret_code; *I = (int *) malloc(*nz * sizeof(int)); *J = (int *) malloc(*nz * sizeof(int)); *val = NULL; if (mm_is_complex(*matcode)) { *val = (double *) malloc(*nz * 2 * sizeof(double)); ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode); if (ret_code != 0) return ret_code; } else if (mm_is_real(*matcode)) { *val = (double *) malloc(*nz * sizeof(double)); ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode); if (ret_code != 0) return ret_code; } else if (mm_is_pattern(*matcode)) { ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, *matcode); if (ret_code != 0) return ret_code; } if (f != stdin) fclose(f); return 0; } /******************************************************************************/ int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[], double val[], MM_typecode matcode) /******************************************************************************/ /* Purpose: MM_READ_MTX_CRD_DATA reads the values in an MM coordinate file. Discussion: This function assumes the array storage has already been allocated. Modified: 31 October 2008 Parameters: Input, FILE *F, a pointer to the input file. */ { int i; if (mm_is_complex(matcode)) { for (i=0; i