EpetraExt  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
EpetraExt_mmio.cpp
Go to the documentation of this file.
00001 /*
00002 //@HEADER
00003 // ***********************************************************************
00004 //
00005 //     EpetraExt: Epetra Extended - Linear Algebra Services Package
00006 //                 Copyright (2011) Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 //@HEADER
00042 */
00043 
00044 /*
00045 *   Matrix Market I/O library for ANSI C
00046 *
00047 *   See http://math.nist.gov/MatrixMarket for details.
00048 *
00049 *
00050 */
00051 
00052 /* JW - This is essentially a C file that was "converted" to C++, but still
00053    contains C function calls.  Since it is independent of the rest of
00054    the package, we will not include the central ConfigDefs file, but
00055    will rather #include the C headers that we need.  This should fix the
00056    build problem on sass2889.
00057 #include <Epetra_ConfigDefs.h> */
00058 #include <string.h>
00059 #include <stdio.h>
00060 #include <ctype.h>
00061 #include "Teuchos_Assert.hpp"
00062 #include "EpetraExt_mmio.h"
00063 
00064 using namespace EpetraExt;
00065 namespace EpetraExt {
00066 int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
00067                 double **val_, int **I_, int **J_)
00068 {
00069     FILE *f;
00070     MM_typecode matcode;
00071     int M, N, nz;
00072     int i;
00073     double *val;
00074     int *I, *J;
00075 
00076     if ((f = fopen(fname, "r")) == NULL)
00077             return -1;
00078 
00079 
00080     if (mm_read_banner(f, &matcode) != 0)
00081     {
00082         printf("mm_read_unsymetric: Could not process Matrix Market banner ");
00083         printf(" in file [%s]\n", fname);
00084         return -1;
00085     }
00086 
00087 
00088 
00089     if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) &&
00090             mm_is_sparse(matcode)))
00091     {
00092       char buffer[MM_MAX_LINE_LENGTH];
00093       mm_typecode_to_str(matcode, buffer);
00094       fprintf(stderr, "Sorry, this application does not support ");
00095       fprintf(stderr, "Market Market type: [%s]\n",buffer);
00096         return -1;
00097     }
00098 
00099     /* find out size of sparse matrix: M, N, nz .... */
00100 
00101     if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0)
00102     {
00103         fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n");
00104         return -1;
00105     }
00106 
00107     *M_ = M;
00108     *N_ = N;
00109     *nz_ = nz;
00110 
00111     /* reseve memory for matrices */
00112 
00113     //I = (int *) malloc(nz * sizeof(int));
00114     //J = (int *) malloc(nz * sizeof(int));
00115     //val = (double *) malloc(nz * sizeof(double));
00116 
00117     I = new int[nz];
00118     J = new int[nz];
00119     val = new double[nz];
00120 
00121     *val_ = val;
00122     *I_ = I;
00123     *J_ = J;
00124 
00125     /* NOTE: when reading in doubles, ANSI C requires the use of the "l"  */
00126     /*   specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
00127     /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */
00128 
00129     for (i=0; i<nz; i++)
00130     {
00131         TEUCHOS_ASSERT(fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]) != EOF);
00132         I[i]--;  /* adjust from 1-based to 0-based */
00133         J[i]--;
00134     }
00135     fclose(f);
00136 
00137     return 0;
00138 }
00139 
00140 int mm_is_valid(MM_typecode matcode)
00141 {
00142     if (!mm_is_matrix(matcode)) return 0;
00143     if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;
00144     if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;
00145     if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||
00146                 mm_is_skew(matcode))) return 0;
00147     return 1;
00148 }
00149 
00150 int mm_read_banner(FILE *f, MM_typecode *matcode)
00151 {
00152     char line[MM_MAX_LINE_LENGTH];
00153     char banner[MM_MAX_TOKEN_LENGTH];
00154     char mtx[MM_MAX_TOKEN_LENGTH];
00155     char crd[MM_MAX_TOKEN_LENGTH];
00156     char data_type[MM_MAX_TOKEN_LENGTH];
00157     char storage_scheme[MM_MAX_TOKEN_LENGTH];
00158     char *p;
00159 
00160 
00161     mm_clear_typecode(matcode);
00162 
00163     if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
00164         return MM_PREMATURE_EOF;
00165 
00166     if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type,
00167         storage_scheme) != 5)
00168         return MM_PREMATURE_EOF;
00169 
00170     for (p=mtx; *p!='\0'; *p=tolower(*p),p++);  /* convert to lower case */
00171     for (p=crd; *p!='\0'; *p=tolower(*p),p++);
00172     for (p=data_type; *p!='\0'; *p=tolower(*p),p++);
00173     for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++);
00174 
00175     /* check for banner */
00176     if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)
00177         return MM_NO_HEADER;
00178 
00179     /* first field should be "mtx" */
00180     if (strcmp(mtx, MM_MTX_STR) != 0)
00181         return  MM_UNSUPPORTED_TYPE;
00182     mm_set_matrix(matcode);
00183 
00184 
00185     /* second field describes whether this is a sparse matrix (in coordinate
00186             storgae) or a dense array */
00187 
00188 
00189     if (strcmp(crd, MM_SPARSE_STR) == 0)
00190         mm_set_sparse(matcode);
00191     else
00192     if (strcmp(crd, MM_DENSE_STR) == 0)
00193             mm_set_dense(matcode);
00194     else
00195         return MM_UNSUPPORTED_TYPE;
00196 
00197 
00198     /* third field */
00199 
00200     if (strcmp(data_type, MM_REAL_STR) == 0)
00201         mm_set_real(matcode);
00202     else
00203     if (strcmp(data_type, MM_COMPLEX_STR) == 0)
00204         mm_set_complex(matcode);
00205     else
00206     if (strcmp(data_type, MM_PATTERN_STR) == 0)
00207         mm_set_pattern(matcode);
00208     else
00209     if (strcmp(data_type, MM_INT_STR) == 0)
00210         mm_set_integer(matcode);
00211     else
00212         return MM_UNSUPPORTED_TYPE;
00213 
00214 
00215     /* fourth field */
00216 
00217     if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)
00218         mm_set_general(matcode);
00219     else
00220     if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
00221         mm_set_symmetric(matcode);
00222     else
00223     if (strcmp(storage_scheme, MM_HERM_STR) == 0)
00224         mm_set_hermitian(matcode);
00225     else
00226     if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
00227         mm_set_skew(matcode);
00228     else
00229         return MM_UNSUPPORTED_TYPE;
00230 
00231 
00232     return 0;
00233 }
00234 
00235 int mm_write_mtx_crd_size(FILE *f, long long M, long long N, long long nz)
00236 {
00237   fprintf(f, "%lld %lld %lld\n", M, N, nz);
00238   return 0;
00239 }
00240 
00241 int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz )
00242 {
00243     char line[MM_MAX_LINE_LENGTH];
00244     int num_items_read;
00245 
00246     /* set return null parameter values, in case we exit with errors */
00247     *M = *N = *nz = 0;
00248 
00249     /* now continue scanning until you reach the end-of-comments */
00250     do
00251     {
00252         if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
00253             return MM_PREMATURE_EOF;
00254     }while (line[0] == '%');
00255 
00256     /* line[] is either blank or has M,N, nz */
00257     if (sscanf(line, "%d %d %d", M, N, nz) == 3)
00258         return 0;
00259 
00260     else
00261     do
00262     {
00263         num_items_read = fscanf(f, "%d %d %d", M, N, nz);
00264         if (num_items_read == EOF) return MM_PREMATURE_EOF;
00265     }
00266     while (num_items_read != 3);
00267 
00268     return 0;
00269 }
00270 
00271 int mm_read_mtx_crd_size(FILE *f, long long *M, long long *N, long long *nz )
00272 {
00273     char line[MM_MAX_LINE_LENGTH];
00274     int num_items_read;
00275 
00276     /* set return null parameter values, in case we exit with errors */
00277     *M = *N = *nz = 0;
00278 
00279     /* now continue scanning until you reach the end-of-comments */
00280     do
00281     {
00282         if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
00283             return MM_PREMATURE_EOF;
00284     }while (line[0] == '%');
00285 
00286     /* line[] is either blank or has M,N, nz */
00287     if (sscanf(line, "%lld %lld %lld", M, N, nz) == 3)
00288         return 0;
00289 
00290     else
00291     do
00292     {
00293         num_items_read = fscanf(f, "%lld %lld %lld", M, N, nz);
00294         if (num_items_read == EOF) return MM_PREMATURE_EOF;
00295     }
00296     while (num_items_read != 3);
00297 
00298     return 0;
00299 }
00300 
00301 int mm_read_mtx_array_size(FILE *f, int *M, int *N)
00302 {
00303     char line[MM_MAX_LINE_LENGTH];
00304     int num_items_read;
00305     /* set return null parameter values, in case we exit with errors */
00306     *M = *N = 0;
00307 
00308     /* now continue scanning until you reach the end-of-comments */
00309     do
00310     {
00311         if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
00312             return MM_PREMATURE_EOF;
00313     }while (line[0] == '%');
00314 
00315     /* line[] is either blank or has M,N, nz */
00316     if (sscanf(line, "%d %d", M, N) == 2)
00317         return 0;
00318 
00319     else /* we have a blank line */
00320     do
00321     {
00322         num_items_read = fscanf(f, "%d %d", M, N);
00323         if (num_items_read == EOF) return MM_PREMATURE_EOF;
00324     }
00325     while (num_items_read != 2);
00326 
00327     return 0;
00328 }
00329 
00330 int mm_write_mtx_array_size(FILE *f, long long M, long long N)
00331 {
00332     fprintf(f, "%lld %lld\n", M, N);
00333     return 0;
00334 }
00335 
00336 
00337 
00338 /*-------------------------------------------------------------------------*/
00339 
00340 /******************************************************************/
00341 /* use when I[], J[], and val[]J, and val[] are already allocated */
00342 /******************************************************************/
00343 
00344 int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
00345         double val[], MM_typecode matcode)
00346 {
00347     int i;
00348     if (mm_is_complex(matcode))
00349     {
00350         for (i=0; i<nz; i++)
00351             if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2*i], &val[2*i+1])
00352                 != 4) return MM_PREMATURE_EOF;
00353     }
00354     else if (mm_is_real(matcode))
00355     {
00356         for (i=0; i<nz; i++)
00357         {
00358             if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
00359                 != 3) return MM_PREMATURE_EOF;
00360 
00361         }
00362     }
00363 
00364     else if (mm_is_pattern(matcode))
00365     {
00366         for (i=0; i<nz; i++)
00367             if (fscanf(f, "%d %d", &I[i], &J[i])
00368                 != 2) return MM_PREMATURE_EOF;
00369     }
00370     else
00371         return MM_UNSUPPORTED_TYPE;
00372 
00373     return 0;
00374 
00375 }
00376 
00377 int mm_read_mtx_crd_entry(FILE *f, int *I, int *J,
00378         double *real, double *imag, MM_typecode matcode)
00379 {
00380     if (mm_is_complex(matcode))
00381     {
00382             if (fscanf(f, "%d %d %lg %lg", I, J, real, imag)
00383                 != 4) return MM_PREMATURE_EOF;
00384     }
00385     else if (mm_is_real(matcode))
00386     {
00387             if (fscanf(f, "%d %d %lg\n", I, J, real)
00388                 != 3) return MM_PREMATURE_EOF;
00389 
00390     }
00391 
00392     else if (mm_is_pattern(matcode))
00393     {
00394             if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF;
00395     }
00396     else
00397         return MM_UNSUPPORTED_TYPE;
00398 
00399     return 0;
00400 
00401 }
00402 
00403 int mm_read_mtx_crd_entry(FILE *f, long long *I, long long *J,
00404         double *real, double *imag, MM_typecode matcode)
00405 {
00406     if (mm_is_complex(matcode))
00407     {
00408             if (fscanf(f, "%lld %lld %lg %lg", I, J, real, imag)
00409                 != 4) return MM_PREMATURE_EOF;
00410     }
00411     else if (mm_is_real(matcode))
00412     {
00413             if (fscanf(f, "%lld %lld %lg\n", I, J, real)
00414                 != 3) return MM_PREMATURE_EOF;
00415 
00416     }
00417 
00418     else if (mm_is_pattern(matcode))
00419     {
00420             if (fscanf(f, "%lld %lld", I, J) != 2) return MM_PREMATURE_EOF;
00421     }
00422     else
00423         return MM_UNSUPPORTED_TYPE;
00424 
00425     return 0;
00426 
00427 }
00428 
00429 /************************************************************************
00430     mm_read_mtx_crd()  fills M, N, nz, array of values, and return
00431                         type code, e.g. 'MCRS'
00432 
00433                         if matrix is complex, values[] is of size 2*nz,
00434                             (nz pairs of real/imaginary values)
00435 ************************************************************************/
00436 
00437 int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,
00438         double **val, MM_typecode *matcode)
00439 {
00440     int ret_code;
00441     FILE *f;
00442 
00443     if (strcmp(fname, "stdin") == 0) f=stdin;
00444     else
00445     if ((f = fopen(fname, "r")) == NULL)
00446         return MM_COULD_NOT_READ_FILE;
00447 
00448 
00449     if ((ret_code = mm_read_banner(f, matcode)) != 0)
00450         return ret_code;
00451 
00452     if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&
00453             mm_is_matrix(*matcode)))
00454         return MM_UNSUPPORTED_TYPE;
00455 
00456     if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)
00457         return ret_code;
00458 
00459 
00460     //*I = (int *)  malloc(*nz * sizeof(int));
00461     //*J = (int *)  malloc(*nz * sizeof(int));
00462     //*val = NULL;
00463 
00464     *I = new int[*nz];
00465     *J = new int[*nz];
00466     *val = 0;
00467 
00468     if (mm_is_complex(*matcode))
00469     {
00470         //*val = (double *) malloc(*nz * 2 * sizeof(double));
00471         *val = new double[2*(*nz)];
00472         ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
00473                 *matcode);
00474         if (ret_code != 0) return ret_code;
00475     }
00476     else if (mm_is_real(*matcode))
00477     {
00478         //*val = (double *) malloc(*nz * sizeof(double));
00479         *val = new double[*nz];
00480         ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
00481                 *matcode);
00482         if (ret_code != 0) return ret_code;
00483     }
00484 
00485     else if (mm_is_pattern(*matcode))
00486     {
00487         ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
00488                 *matcode);
00489         if (ret_code != 0) return ret_code;
00490     }
00491 
00492     if (f != stdin) fclose(f);
00493     return 0;
00494 }
00495 
00496 int mm_write_banner(FILE *f, MM_typecode matcode)
00497 {
00498   char buffer[MM_MAX_LINE_LENGTH];
00499 
00500   mm_typecode_to_str(matcode, buffer);
00501   int ret_code;
00502 
00503   ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, buffer);
00504   //free(str);
00505   //delete [] str;
00506     return 0;
00507 }
00508 
00509 int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
00510         double val[], MM_typecode matcode)
00511 {
00512     FILE *f;
00513     int i;
00514 
00515     if (strcmp(fname, "stdout") == 0)
00516         f = stdout;
00517     else
00518     if ((f = fopen(fname, "w")) == NULL)
00519         return MM_COULD_NOT_WRITE_FILE;
00520 
00521     /* print banner followed by typecode */
00522     char buffer[MM_MAX_LINE_LENGTH];
00523     mm_typecode_to_str(matcode, buffer);
00524     fprintf(f, "%s ", MatrixMarketBanner);
00525     fprintf(f, "%s\n", buffer);
00526 
00527     /* print matrix sizes and nonzeros */
00528     fprintf(f, "%d %d %d\n", M, N, nz);
00529 
00530     /* print values */
00531     if (mm_is_pattern(matcode))
00532         for (i=0; i<nz; i++)
00533             fprintf(f, "%d %d\n", I[i], J[i]);
00534     else
00535     if (mm_is_real(matcode))
00536         for (i=0; i<nz; i++)
00537             fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
00538     else
00539     if (mm_is_complex(matcode))
00540         for (i=0; i<nz; i++)
00541             fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i],
00542                         val[2*i+1]);
00543     else
00544     {
00545         if (f != stdout) fclose(f);
00546         return MM_UNSUPPORTED_TYPE;
00547     }
00548 
00549     if (f !=stdout) fclose(f);
00550 
00551     return 0;
00552 }
00553 
00554 
00555  void mm_typecode_to_str(MM_typecode matcode, char * buffer)
00556 {
00557     char type0[20];
00558     char type1[20];
00559     char type2[20];
00560     char type3[20];
00561     int error =0;
00562 
00563     /* check for MTX type */
00564     if (mm_is_matrix(matcode))
00565         strcpy(type0, MM_MTX_STR);
00566     else
00567         error=1;
00568 
00569     /* check for CRD or ARR matrix */
00570     if (mm_is_sparse(matcode))
00571         strcpy(type1, MM_SPARSE_STR);
00572     else
00573     if (mm_is_dense(matcode))
00574         strcpy(type1, MM_DENSE_STR);
00575     else
00576         return;
00577 
00578     /* check for element data type */
00579     if (mm_is_real(matcode))
00580         strcpy(type2, MM_REAL_STR);
00581     else
00582     if (mm_is_complex(matcode))
00583         strcpy(type2, MM_COMPLEX_STR);
00584     else
00585     if (mm_is_pattern(matcode))
00586         strcpy(type2, MM_PATTERN_STR);
00587     else
00588     if (mm_is_integer(matcode))
00589         strcpy(type2, MM_INT_STR);
00590     else
00591         return;
00592 
00593     /* check for symmetry type */
00594     if (mm_is_general(matcode))
00595         strcpy(type3, MM_GENERAL_STR);
00596     else
00597     if (mm_is_symmetric(matcode))
00598         strcpy(type3, MM_SYMM_STR);
00599     else
00600     if (mm_is_hermitian(matcode))
00601         strcpy(type3, MM_HERM_STR);
00602     else
00603     if (mm_is_skew(matcode))
00604         strcpy(type3, MM_SKEW_STR);
00605     else
00606         return;
00607 
00608     sprintf(buffer,"%s %s %s %s", type0, type1, type2, type3);
00609     return;
00610 }
00611 } // namespace EpetraExt
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines