|
EpetraExt
Development
|
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
1.7.6.1