ColPack
Utilities/mmio.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines