ColPack
|
00001 /* 00002 * Matrix Market I/O library for ANSI C 00003 * 00004 * See http://math.nist.gov/MatrixMarket for details. 00005 * 00006 * 00007 */ 00008 00009 00010 #include <stdio.h> 00011 #include <string.h> 00012 #include <stdlib.h> 00013 #include <ctype.h> 00014 00015 #include "mmio.h" 00016 00017 int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, 00018 double **val_, int **I_, int **J_) 00019 { 00020 FILE *f; 00021 MM_typecode matcode; 00022 int M, N, nz; 00023 int i; 00024 double *val; 00025 int *I, *J; 00026 00027 if ((f = fopen(fname, "r")) == NULL) 00028 return -1; 00029 00030 00031 if (mm_read_banner(f, &matcode) != 0) 00032 { 00033 printf("mm_read_unsymetric: Could not process Matrix Market banner "); 00034 printf(" in file [%s]\n", fname); 00035 return -1; 00036 } 00037 00038 00039 00040 if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) && 00041 mm_is_sparse(matcode))) 00042 { 00043 fprintf(stderr, "Sorry, this application does not support "); 00044 fprintf(stderr, "Market Market type: [%s]\n", 00045 mm_typecode_to_str(matcode)); 00046 return -1; 00047 } 00048 00049 /* find out size of sparse matrix: M, N, nz .... */ 00050 00051 if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0) 00052 { 00053 fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n"); 00054 return -1; 00055 } 00056 00057 *M_ = M; 00058 *N_ = N; 00059 *nz_ = nz; 00060 00061 /* reseve memory for matrices */ 00062 00063 I = (int *) malloc(nz * sizeof(int)); 00064 J = (int *) malloc(nz * sizeof(int)); 00065 val = (double *) malloc(nz * sizeof(double)); 00066 00067 *val_ = val; 00068 *I_ = I; 00069 *J_ = J; 00070 00071 /* NOTE: when reading in doubles, ANSI C requires the use of the "l" */ 00072 /* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */ 00073 /* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */ 00074 00075 for (i=0; i<nz; i++) 00076 { 00077 fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]); 00078 I[i]--; /* adjust from 1-based to 0-based */ 00079 J[i]--; 00080 } 00081 fclose(f); 00082 00083 return 0; 00084 } 00085 00086 int mm_is_valid(MM_typecode matcode) 00087 { 00088 if (!mm_is_matrix(matcode)) return 0; 00089 if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0; 00090 if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0; 00091 if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) || 00092 mm_is_skew(matcode))) return 0; 00093 return 1; 00094 } 00095 00096 int mm_read_banner(FILE *f, MM_typecode *matcode) 00097 { 00098 char line[MM_MAX_LINE_LENGTH]; 00099 char banner[MM_MAX_TOKEN_LENGTH]; 00100 char mtx[MM_MAX_TOKEN_LENGTH]; 00101 char crd[MM_MAX_TOKEN_LENGTH]; 00102 char data_type[MM_MAX_TOKEN_LENGTH]; 00103 char storage_scheme[MM_MAX_TOKEN_LENGTH]; 00104 char *p; 00105 00106 00107 mm_clear_typecode(matcode); 00108 00109 if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) 00110 return MM_PREMATURE_EOF; 00111 00112 if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type, 00113 storage_scheme) != 5) 00114 return MM_PREMATURE_EOF; 00115 00116 for (p=mtx; *p!='\0'; *p=tolower(*p),p++); /* convert to lower case */ 00117 for (p=crd; *p!='\0'; *p=tolower(*p),p++); 00118 for (p=data_type; *p!='\0'; *p=tolower(*p),p++); 00119 for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++); 00120 00121 /* check for banner */ 00122 if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0) 00123 return MM_NO_HEADER; 00124 00125 /* first field should be "mtx" */ 00126 if (strcmp(mtx, MM_MTX_STR) != 0) 00127 return MM_UNSUPPORTED_TYPE; 00128 mm_set_matrix(matcode); 00129 00130 00131 /* second field describes whether this is a sparse matrix (in coordinate 00132 storgae) or a dense array */ 00133 00134 00135 if (strcmp(crd, MM_SPARSE_STR) == 0) 00136 mm_set_sparse(matcode); 00137 else 00138 if (strcmp(crd, MM_DENSE_STR) == 0) 00139 mm_set_dense(matcode); 00140 else 00141 return MM_UNSUPPORTED_TYPE; 00142 00143 00144 /* third field */ 00145 00146 if (strcmp(data_type, MM_REAL_STR) == 0) 00147 mm_set_real(matcode); 00148 else 00149 if (strcmp(data_type, MM_COMPLEX_STR) == 0) 00150 mm_set_complex(matcode); 00151 else 00152 if (strcmp(data_type, MM_PATTERN_STR) == 0) 00153 mm_set_pattern(matcode); 00154 else 00155 if (strcmp(data_type, MM_INT_STR) == 0) 00156 mm_set_integer(matcode); 00157 else 00158 return MM_UNSUPPORTED_TYPE; 00159 00160 00161 /* fourth field */ 00162 00163 if (strcmp(storage_scheme, MM_GENERAL_STR) == 0) 00164 mm_set_general(matcode); 00165 else 00166 if (strcmp(storage_scheme, MM_SYMM_STR) == 0) 00167 mm_set_symmetric(matcode); 00168 else 00169 if (strcmp(storage_scheme, MM_HERM_STR) == 0) 00170 mm_set_hermitian(matcode); 00171 else 00172 if (strcmp(storage_scheme, MM_SKEW_STR) == 0) 00173 mm_set_skew(matcode); 00174 else 00175 return MM_UNSUPPORTED_TYPE; 00176 00177 00178 return 0; 00179 } 00180 00181 int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz) 00182 { 00183 if (fprintf(f, "%d %d %d\n", M, N, nz) != 3) 00184 return MM_COULD_NOT_WRITE_FILE; 00185 else 00186 return 0; 00187 } 00188 00189 int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz ) 00190 { 00191 char line[MM_MAX_LINE_LENGTH]; 00192 int num_items_read; 00193 00194 /* set return null parameter values, in case we exit with errors */ 00195 *M = *N = *nz = 0; 00196 00197 /* now continue scanning until you reach the end-of-comments */ 00198 do 00199 { 00200 if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL) 00201 return MM_PREMATURE_EOF; 00202 }while (line[0] == '%'); 00203 00204 /* line[] is either blank or has M,N, nz */ 00205 if (sscanf(line, "%d %d %d", M, N, nz) == 3) 00206 return 0; 00207 00208 else 00209 do 00210 { 00211 num_items_read = fscanf(f, "%d %d %d", M, N, nz); 00212 if (num_items_read == EOF) return MM_PREMATURE_EOF; 00213 } 00214 while (num_items_read != 3); 00215 00216 return 0; 00217 } 00218 00219 00220 int mm_read_mtx_array_size(FILE *f, int *M, int *N) 00221 { 00222 char line[MM_MAX_LINE_LENGTH]; 00223 int num_items_read; 00224 /* set return null parameter values, in case we exit with errors */ 00225 *M = *N = 0; 00226 00227 /* now continue scanning until you reach the end-of-comments */ 00228 do 00229 { 00230 if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL) 00231 return MM_PREMATURE_EOF; 00232 }while (line[0] == '%'); 00233 00234 /* line[] is either blank or has M,N, nz */ 00235 if (sscanf(line, "%d %d", M, N) == 2) 00236 return 0; 00237 00238 else /* we have a blank line */ 00239 do 00240 { 00241 num_items_read = fscanf(f, "%d %d", M, N); 00242 if (num_items_read == EOF) return MM_PREMATURE_EOF; 00243 } 00244 while (num_items_read != 2); 00245 00246 return 0; 00247 } 00248 00249 int mm_write_mtx_array_size(FILE *f, int M, int N) 00250 { 00251 if (fprintf(f, "%d %d\n", M, N) != 2) 00252 return MM_COULD_NOT_WRITE_FILE; 00253 else 00254 return 0; 00255 } 00256 00257 00258 00259 /*-------------------------------------------------------------------------*/ 00260 00261 /******************************************************************/ 00262 /* use when I[], J[], and val[]J, and val[] are already allocated */ 00263 /******************************************************************/ 00264 00265 int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[], 00266 double val[], MM_typecode matcode) 00267 { 00268 int i; 00269 if (mm_is_complex(matcode)) 00270 { 00271 for (i=0; i<nz; i++) 00272 if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2*i], &val[2*i+1]) 00273 != 4) return MM_PREMATURE_EOF; 00274 } 00275 else if (mm_is_real(matcode)) 00276 { 00277 for (i=0; i<nz; i++) 00278 { 00279 if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]) 00280 != 3) return MM_PREMATURE_EOF; 00281 00282 } 00283 } 00284 00285 else if (mm_is_pattern(matcode)) 00286 { 00287 for (i=0; i<nz; i++) 00288 if (fscanf(f, "%d %d", &I[i], &J[i]) 00289 != 2) return MM_PREMATURE_EOF; 00290 } 00291 else 00292 return MM_UNSUPPORTED_TYPE; 00293 00294 return 0; 00295 00296 } 00297 00298 int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, 00299 double *real, double *imag, MM_typecode matcode) 00300 { 00301 if (mm_is_complex(matcode)) 00302 { 00303 if (fscanf(f, "%d %d %lg %lg", I, J, real, imag) 00304 != 4) return MM_PREMATURE_EOF; 00305 } 00306 else if (mm_is_real(matcode)) 00307 { 00308 if (fscanf(f, "%d %d %lg\n", I, J, real) 00309 != 3) return MM_PREMATURE_EOF; 00310 00311 } 00312 00313 else if (mm_is_pattern(matcode)) 00314 { 00315 if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF; 00316 } 00317 else 00318 return MM_UNSUPPORTED_TYPE; 00319 00320 return 0; 00321 00322 } 00323 00324 00325 /************************************************************************ 00326 mm_read_mtx_crd() fills M, N, nz, array of values, and return 00327 type code, e.g. 'MCRS' 00328 00329 if matrix is complex, values[] is of size 2*nz, 00330 (nz pairs of real/imaginary values) 00331 ************************************************************************/ 00332 00333 int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J, 00334 double **val, MM_typecode *matcode) 00335 { 00336 int ret_code; 00337 FILE *f; 00338 00339 if (strcmp(fname, "stdin") == 0) f=stdin; 00340 else 00341 if ((f = fopen(fname, "r")) == NULL) 00342 return MM_COULD_NOT_READ_FILE; 00343 00344 00345 if ((ret_code = mm_read_banner(f, matcode)) != 0) 00346 return ret_code; 00347 00348 if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) && 00349 mm_is_matrix(*matcode))) 00350 return MM_UNSUPPORTED_TYPE; 00351 00352 if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0) 00353 return ret_code; 00354 00355 00356 *I = (int *) malloc(*nz * sizeof(int)); 00357 *J = (int *) malloc(*nz * sizeof(int)); 00358 *val = NULL; 00359 00360 if (mm_is_complex(*matcode)) 00361 { 00362 *val = (double *) malloc(*nz * 2 * sizeof(double)); 00363 ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, 00364 *matcode); 00365 if (ret_code != 0) return ret_code; 00366 } 00367 else if (mm_is_real(*matcode)) 00368 { 00369 *val = (double *) malloc(*nz * sizeof(double)); 00370 ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, 00371 *matcode); 00372 if (ret_code != 0) return ret_code; 00373 } 00374 00375 else if (mm_is_pattern(*matcode)) 00376 { 00377 ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, 00378 *matcode); 00379 if (ret_code != 0) return ret_code; 00380 } 00381 00382 if (f != stdin) fclose(f); 00383 return 0; 00384 } 00385 00386 int mm_write_banner(FILE *f, MM_typecode matcode) 00387 { 00388 char *str = mm_typecode_to_str(matcode); 00389 int ret_code; 00390 00391 ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str); 00392 free(str); 00393 if (ret_code !=2 ) 00394 return MM_COULD_NOT_WRITE_FILE; 00395 else 00396 return 0; 00397 } 00398 00399 int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[], 00400 double val[], MM_typecode matcode) 00401 { 00402 FILE *f; 00403 int i; 00404 00405 if (strcmp(fname, "stdout") == 0) 00406 f = stdout; 00407 else 00408 if ((f = fopen(fname, "w")) == NULL) 00409 return MM_COULD_NOT_WRITE_FILE; 00410 00411 /* print banner followed by typecode */ 00412 fprintf(f, "%s ", MatrixMarketBanner); 00413 fprintf(f, "%s\n", mm_typecode_to_str(matcode)); 00414 00415 /* print matrix sizes and nonzeros */ 00416 fprintf(f, "%d %d %d\n", M, N, nz); 00417 00418 /* print values */ 00419 if (mm_is_pattern(matcode)) 00420 for (i=0; i<nz; i++) 00421 fprintf(f, "%d %d\n", I[i], J[i]); 00422 else 00423 if (mm_is_real(matcode)) 00424 for (i=0; i<nz; i++) 00425 fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]); 00426 else 00427 if (mm_is_complex(matcode)) 00428 for (i=0; i<nz; i++) 00429 fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i], 00430 val[2*i+1]); 00431 else 00432 { 00433 if (f != stdout) fclose(f); 00434 return MM_UNSUPPORTED_TYPE; 00435 } 00436 00437 if (f !=stdout) fclose(f); 00438 00439 return 0; 00440 } 00441 00442 00448 char *mm_strdup(const char *s) 00449 { 00450 int len = strlen(s); 00451 char *s2 = (char *) malloc((len+1)*sizeof(char)); 00452 return strcpy(s2, s); 00453 } 00454 00455 char *mm_typecode_to_str(MM_typecode matcode) 00456 { 00457 char buffer[MM_MAX_LINE_LENGTH]; 00458 char *types[4]; 00459 char *mm_strdup(const char *); 00460 int error =0; 00461 00462 /* check for MTX type */ 00463 if (mm_is_matrix(matcode)) 00464 types[0] = MM_MTX_STR; 00465 else 00466 error=1; 00467 00468 /* check for CRD or ARR matrix */ 00469 if (mm_is_sparse(matcode)) 00470 types[1] = MM_SPARSE_STR; 00471 else 00472 if (mm_is_dense(matcode)) 00473 types[1] = MM_DENSE_STR; 00474 else 00475 return NULL; 00476 00477 /* check for element data type */ 00478 if (mm_is_real(matcode)) 00479 types[2] = MM_REAL_STR; 00480 else 00481 if (mm_is_complex(matcode)) 00482 types[2] = MM_COMPLEX_STR; 00483 else 00484 if (mm_is_pattern(matcode)) 00485 types[2] = MM_PATTERN_STR; 00486 else 00487 if (mm_is_integer(matcode)) 00488 types[2] = MM_INT_STR; 00489 else 00490 return NULL; 00491 00492 00493 /* check for symmetry type */ 00494 if (mm_is_general(matcode)) 00495 types[3] = MM_GENERAL_STR; 00496 else 00497 if (mm_is_symmetric(matcode)) 00498 types[3] = MM_SYMM_STR; 00499 else 00500 if (mm_is_hermitian(matcode)) 00501 types[3] = MM_HERM_STR; 00502 else 00503 if (mm_is_skew(matcode)) 00504 types[3] = MM_SKEW_STR; 00505 else 00506 return NULL; 00507 00508 sprintf(buffer,"%s %s %s %s", types[0], types[1], types[2], types[3]); 00509 return mm_strdup(buffer); 00510 00511 }