Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2001-2009 Vivien Mallet 00002 // 00003 // This file is part of the linear-algebra library Seldon, 00004 // http://seldon.sourceforge.net/. 00005 // 00006 // Seldon is free software; you can redistribute it and/or modify it under the 00007 // terms of the GNU Lesser General Public License as published by the Free 00008 // Software Foundation; either version 2.1 of the License, or (at your option) 00009 // any later version. 00010 // 00011 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY 00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00013 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00014 // more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with Seldon. If not, see http://www.gnu.org/licenses/. 00018 00019 00020 #ifndef SELDON_FILE_MATRIX_SPARSE_IOMATRIXMARKET_CXX 00021 00022 00023 #include "IOMatrixMarket.hxx" 00024 #include <iomanip> 00025 00026 namespace Seldon 00027 { 00028 00029 00031 00044 template <class Prop, class Allocator> 00045 void ReadHarwellBoeing(string filename, 00046 Matrix<float, Prop, ColSparse, Allocator>& A) 00047 { 00048 ReadHarwellBoeing(filename, "real", "general", A); 00049 } 00050 00051 00053 template <class Prop, class Allocator> 00054 void ReadHarwellBoeing(string filename, 00055 Matrix<double, Prop, ColSparse, Allocator>& A) 00056 { 00057 ReadHarwellBoeing(filename, "real", "general", A); 00058 } 00059 00060 00062 00080 template <class T, class Prop, class Storage, class Allocator> 00081 void ReadHarwellBoeing(string filename, 00082 string value_type, string matrix_type, 00083 Matrix<T, Prop, Storage, Allocator> & A) 00084 { 00085 int i, j, k; 00086 string line, element; 00087 00088 // Dimensions of the output matrix. 00089 int Nrow, Ncol; 00090 int Nnonzero; 00091 00092 ifstream input_stream(filename.c_str()); 00093 00094 #ifdef SELDON_CHECK_IO 00095 // Checks if the stream is ready. 00096 if (!input_stream.good()) 00097 throw IOError("ReadHarwellBoeing(string filename, " 00098 "Matrix& A, string value_type, string matrix_type)", 00099 "Unable to read file \"" + filename + "\"."); 00100 #endif 00101 00102 /*** Parsing headers ***/ 00103 00104 // First line. 00105 string title, name; 00106 getline(input_stream, line); 00107 title = line.substr(0, 72); 00108 name = line.substr(72, 8); 00109 00110 // Second line. 00111 int Nline_ptr, Nline_ind, Nline_val, Nline_rhs; 00112 input_stream >> i >> Nline_ptr >> Nline_ind >> Nline_val >> Nline_rhs; 00113 00114 // Third line. 00115 string type; 00116 int Nelemental; 00117 input_stream >> type >> Nrow >> Ncol >> Nnonzero >> Nelemental; 00118 00119 if (type.size() != 3) 00120 throw WrongArgument("ReadHarwellBoeing(string filename, " 00121 "Matrix& A, string value_type, string matrix_type)", 00122 "File \"" + filename + "\" contains a matrix of " 00123 "type \"" + type + "\", which is not a valid type. " 00124 "The type must contain exactly three characters."); 00125 00126 if (type.substr(0, 1) != "R" && type.substr(0, 1) != "C" 00127 && type.substr(0, 1) != "P") 00128 throw WrongArgument("ReadHarwellBoeing(string filename, " 00129 "Matrix& A, string value_type, string matrix_type)", 00130 "File \"" + filename + "\" contains a matrix of " 00131 "type \"" + type + "\", which is not a valid type. " 00132 "The first character of that type must be 'R', 'C' " 00133 "(not supported anyway) or 'P'."); 00134 00135 if (type.substr(0, 1) == "C") 00136 throw WrongArgument("ReadHarwellBoeing(string filename, " 00137 "Matrix& A, string value_type, string matrix_type)", 00138 "File \"" + filename + "\" contains a " 00139 "complex-valued matrix, which is not supported."); 00140 00141 if (type.substr(0, 1) == "R" && value_type != "real") 00142 throw WrongArgument("ReadHarwellBoeing(string filename, " 00143 "Matrix& A, string value_type, string matrix_type)", 00144 "File \"" + filename + "\" contains a real-valued " 00145 "matrix, while the input matrix 'A' is not " 00146 "declared as such."); 00147 00148 if (type.substr(1, 1) == "H") 00149 throw WrongArgument("ReadHarwellBoeing(string filename, " 00150 "Matrix& A, string value_type, string matrix_type)", 00151 "File \"" + filename + "\" contains a Hermitian " 00152 "matrix, which is not supported."); 00153 00154 if (type.substr(1, 1) == "Z") 00155 throw WrongArgument("ReadHarwellBoeing(string filename, " 00156 "Matrix& A, string value_type, string matrix_type)", 00157 "File \"" + filename + "\" contains a skew " 00158 "symmetric matrix, which is not supported."); 00159 00160 if (type.substr(1, 1) == "S") 00161 throw WrongArgument("ReadHarwellBoeing(string filename, " 00162 "Matrix& A, string value_type, string matrix_type)", 00163 "File \"" + filename + "\" contains a " 00164 "symmetric matrix, which is not supported."); 00165 00166 if (Nelemental != 0 || type.substr(2, 1) == "E") 00167 throw WrongArgument("ReadHarwellBoeing(string filename, " 00168 "Matrix& A, string value_type, string matrix_type)", 00169 "File \"" + filename + "\" contains an elemental " 00170 "matrix, which is not supported."); 00171 00172 getline(input_stream, line); 00173 00174 // Fourth line. 00175 getline(input_stream, line); 00176 int line_width_ptr, element_width_ptr, line_width_ind, element_width_ind; 00177 element = line.substr(0, 16); 00178 sscanf(element.c_str(), "(%dI%d)", &line_width_ptr, &element_width_ptr); 00179 element = line.substr(16, 16); 00180 sscanf(element.c_str(), "(%dI%d)", &line_width_ind, &element_width_ind); 00181 int line_width_val = 0; 00182 int element_width_val = 0; 00183 if (type.substr(0, 1) != "P") 00184 { 00185 element = line.substr(32, 16); 00186 00187 // Splits the format to retrieve the useful widths. This part is 00188 // tricky because no parsing (in C++) of Fortran format was found. 00189 vector<int> vect; 00190 string delimiter = " (ABEFGILOPZ*.)"; 00191 string tmp_str; 00192 int tmp_int; 00193 string::size_type index_beg = element.find_first_not_of(delimiter); 00194 string::size_type index_end; 00195 while (index_beg != string::npos) 00196 { 00197 index_end = element.find_first_of(delimiter, index_beg); 00198 tmp_str = element.substr(index_beg, 00199 index_end == string::npos ? 00200 string::npos : (index_end-index_beg)); 00201 istringstream(tmp_str) >> tmp_int; 00202 vect.push_back(tmp_int); 00203 index_beg = element.find_first_not_of(delimiter, index_end); 00204 } 00205 00206 if (vect.size() < 3) 00207 throw WrongArgument("ReadHarwellBoeing(string filename, Matrix& A, " 00208 "string value_type, string matrix_type)", 00209 "File \"" + filename + "\" contains values " 00210 "written in format \"" + element + "\", which " 00211 "could not be parsed."); 00212 00213 line_width_val = vect[vect.size() - 3]; 00214 element_width_val = vect[vect.size() - 2]; 00215 } 00216 00217 // Fifth header line, if any: ignored. RHS are not read. 00218 if (Nline_rhs != 0) 00219 getline(input_stream, line); 00220 00221 /*** Allocations ***/ 00222 00223 // Content of output matrix A. 00224 int* A_ptr; 00225 int* A_ind; 00226 T* A_data; 00227 00228 #ifdef SELDON_CHECK_MEMORY 00229 try 00230 { 00231 #endif 00232 00233 A_ptr = reinterpret_cast<int*>(calloc(Ncol + 1, sizeof(int))); 00234 00235 #ifdef SELDON_CHECK_MEMORY 00236 } 00237 catch (...) 00238 { 00239 A_ptr = NULL; 00240 } 00241 00242 if (A_ptr == NULL) 00243 throw NoMemory("ReadHarwellBoeing(string filename, " 00244 "Matrix& A, string value_type, string matrix_type)", 00245 "Unable to allocate memory for an array of " 00246 + to_str(Ncol + 1) + " integers."); 00247 #endif 00248 00249 #ifdef SELDON_CHECK_MEMORY 00250 try 00251 { 00252 #endif 00253 00254 // Reallocates 'A_ind' and 'A_data' in order to append the 00255 // elements of the i-th row of C. 00256 A_ind = reinterpret_cast<int*>(calloc(Nnonzero, sizeof(int))); 00257 A_data = reinterpret_cast<T*> 00258 (A.GetAllocator().allocate(Nnonzero)); 00259 00260 #ifdef SELDON_CHECK_MEMORY 00261 } 00262 catch (...) 00263 { 00264 A_ind = NULL; 00265 A_data = NULL; 00266 } 00267 00268 if (A_ind == NULL || A_data == NULL) 00269 throw NoMemory("ReadHarwellBoeing(string filename, " 00270 "Matrix& A, string value_type, string matrix_type)", 00271 "Unable to allocate memory for an array of " 00272 + to_str(Nnonzero) + " integers " 00273 "and for an array of " 00274 + to_str(sizeof(T) * Nnonzero) + " bytes."); 00275 #endif 00276 00277 /*** Reads the structure ***/ 00278 00279 int index = 0; 00280 for (i = 0; i < Nline_ptr; i++) 00281 { 00282 getline(input_stream, line); 00283 k = 0; 00284 for (j = 0; j < line_width_ptr; j++) 00285 { 00286 istringstream(line.substr(k, element_width_ptr)) >> A_ptr[index]; 00287 // The indexes are 1-based, so this corrects it: 00288 A_ptr[index]--; 00289 index++; 00290 if (index == Ncol + 1) 00291 // So as not to read more elements than actually available on 00292 // the line. 00293 break; 00294 k += element_width_ptr; 00295 } 00296 if (index == Ncol + 1) 00297 break; 00298 } 00299 00300 index = 0; 00301 for (i = 0; i < Nline_ind; i++) 00302 { 00303 getline(input_stream, line); 00304 k = 0; 00305 for (j = 0; j < line_width_ind; j++) 00306 { 00307 istringstream(line.substr(k, element_width_ind)) >> A_ind[index]; 00308 // The indexes are 1-based, so this corrects it: 00309 A_ind[index]--; 00310 index++; 00311 if (index == Nnonzero) 00312 // So as not to read more elements than actually available on 00313 // the line. 00314 break; 00315 k += element_width_ind; 00316 } 00317 if (index == Nnonzero) 00318 break; 00319 } 00320 00321 /*** Reads the values ***/ 00322 00323 if (type.substr(0, 1) == "P") 00324 for (i = 0; i < Nnonzero; i++) 00325 A_data[i] = T(1); 00326 else 00327 { 00328 index = 0; 00329 for (i = 0; i < Nline_val; i++) 00330 { 00331 getline(input_stream, line); 00332 k = 0; 00333 for (j = 0; j < line_width_val; j++) 00334 { 00335 istringstream(line.substr(k, element_width_val)) 00336 >> A_data[index]; 00337 index++; 00338 if (index == Nnonzero) 00339 // So as not to read more elements than actually available 00340 // on the line. 00341 break; 00342 k += element_width_val; 00343 } 00344 if (index == Nnonzero) 00345 break; 00346 } 00347 } 00348 00349 #ifdef SELDON_CHECK_IO 00350 // Checks if the stream is still in good shape. 00351 if (!input_stream.good()) 00352 throw IOError("ReadHarwellBoeing(string filename, " 00353 "Matrix& A, string value_type, string matrix_type)", 00354 "Unable to read all values in file \"" 00355 + filename + "\"."); 00356 #endif 00357 00358 input_stream.close(); 00359 00360 A.SetData(Nrow, Ncol, Nnonzero, A_data, A_ptr, A_ind); 00361 } 00362 00363 00364 template<class T> 00365 void PrintComplexValuesHarwell(int nnz, const Vector<complex<T> >& Val, 00366 ofstream& file_out) 00367 { 00368 for (int i = 0; i < 2*nnz; i += 3) 00369 { 00370 for (int j = i; j < min(i+3, 2*nnz); j++) 00371 { 00372 if (j%2 == 0) 00373 file_out << setw(23) << real(Val(j/2)); 00374 else 00375 file_out << setw(23) << imag(Val(j/2)); 00376 } 00377 00378 file_out << '\n'; 00379 } 00380 } 00381 00382 00383 template<class T> 00384 void PrintComplexValuesHarwell(int nnz, const Vector<T>& Val, 00385 ofstream& file_out) 00386 { 00387 for (int i = 0; i < nnz; i += 3) 00388 { 00389 for (int j = i; j < min(i+3, nnz); j++) 00390 file_out << setw(23) << Val(j); 00391 00392 file_out << '\n'; 00393 } 00394 } 00395 00396 00397 template<class T, class Prop, class Storage, class Allocator> 00398 void WriteHarwellBoeing(const Matrix<T, Prop, Storage, Allocator>& A, 00399 const string& file_name, bool complex) 00400 { 00401 // converting to CSR 00402 IVect Ptr, Ind; 00403 Vector<T> Val; 00404 General sym; 00405 ConvertToCSC(A, sym, Ptr, Ind, Val); 00406 00407 // number of columns and non-zero entries 00408 int nnz = Val.GetM(); 00409 int m = A.GetM(); 00410 int n = A.GetN(); 00411 00412 // First line 00413 ofstream file_out(file_name.data()); 00414 00415 string title("Seldon"); 00416 string key("S0000008"); 00417 file_out.setf(ios::left); 00418 file_out << setw(72) << title; 00419 file_out << setw(8) << key; 00420 file_out << endl; 00421 00422 // Compute column pointer format 00423 int ptr_len = int(ceil( log10(0.1 + nnz + 1) )) + 1; 00424 int ptr_nperline = min(80 / ptr_len, n+1); 00425 int ptrcrd = n / ptr_nperline + 1; 00426 string ptrfmt = string("(") + to_str(ptr_nperline) 00427 + "I" + to_str(ptr_len) + ")"; 00428 00429 // Compute row index format 00430 int ind_len = int(ceil( log10(0.1 + n + 1) )) + 1; 00431 int ind_nperline = min(80 / ind_len, nnz); 00432 int indcrd = (nnz-1) / ind_nperline + 1; 00433 string indfmt = string("(") + to_str(ind_nperline) 00434 + 'I' + to_str(ind_len) + ')'; 00435 00436 // compute value format 00437 string valfmt("(3D23.15)"); 00438 int valcrd = (nnz-1) / 3 + 1; 00439 if (complex) 00440 valcrd = (2*nnz-1) / 3 + 1; 00441 00442 int rhscrd = 0; 00443 int totcrd = ptrcrd + indcrd + valcrd + rhscrd; 00444 00445 // Second line 00446 file_out << setw(14) << totcrd; 00447 file_out << setw(14) << ptrcrd; 00448 file_out << setw(14) << indcrd; 00449 file_out << setw(14) << valcrd; 00450 file_out << setw(14) << rhscrd; 00451 file_out << endl; 00452 00453 // Third line 00454 int neltvl = 0; 00455 char mxtype[4]; 00456 if (complex) 00457 mxtype[0] = 'C'; 00458 else 00459 mxtype[0] = 'R'; 00460 00461 if (m == n) 00462 mxtype[1] = 'U'; 00463 else 00464 mxtype[1] = 'R'; 00465 00466 mxtype[2] = 'A'; 00467 mxtype[3] = '\0'; 00468 00469 file_out << mxtype << " "; 00470 file_out << setw(14) << m; 00471 file_out << setw(14) << n; 00472 file_out << setw(14) << nnz; 00473 file_out << setw(14) << neltvl; 00474 file_out << endl; 00475 00476 // Fourth line 00477 file_out << setw(16) << ptrfmt; 00478 file_out << setw(16) << indfmt; 00479 file_out << setw(20) << valfmt; 00480 file_out << setw(20) << valfmt; 00481 file_out << endl; 00482 00483 // printing ptr values 00484 file_out.setf(ios::left); 00485 for (int i = 0; i <= n; i += ptr_nperline) 00486 { 00487 for (int j = i; j < min(i+ptr_nperline, n+1); j++) 00488 file_out << setw(ptr_len) << Ptr(j)+1; 00489 00490 file_out << '\n'; 00491 } 00492 00493 // printing ind values 00494 for (int i = 0; i < nnz; i += ind_nperline) 00495 { 00496 for (int j = i; j < min(i+ind_nperline, nnz); j++) 00497 file_out << setw(ind_len) << Ind(j)+1; 00498 00499 file_out << '\n'; 00500 } 00501 00502 // printing values 00503 file_out.precision(15); 00504 file_out.setf(ios::scientific); 00505 PrintComplexValuesHarwell(nnz, Val, file_out); 00506 00507 file_out.close(); 00508 } 00509 00510 00512 template<class T, class Prop, class Storage, class Allocator> 00513 void WriteHarwellBoeing(const Matrix<T, Prop, Storage, Allocator>& A, 00514 const string& file_name) 00515 { 00516 WriteHarwellBoeing(A, file_name, false); 00517 } 00518 00519 00521 template<class T, class Prop, class Storage, class Allocator> 00522 void WriteHarwellBoeing(const Matrix<complex<T>, 00523 Prop, Storage, Allocator>& A, 00524 const string& file_name) 00525 { 00526 WriteHarwellBoeing(A, file_name, true); 00527 } 00528 00529 } 00530 00531 00532 #define SELDON_FILE_MATRIX_SPARSE_IOMATRIXMARKET_CXX 00533 #endif