|
ViennaCL - The Vienna Computing Library
1.1.2
|
00001 /* ======================================================================= 00002 Copyright (c) 2010, Institute for Microelectronics, TU Vienna. 00003 http://www.iue.tuwien.ac.at 00004 ----------------- 00005 ViennaCL - The Vienna Computing Library 00006 ----------------- 00007 00008 authors: Karl Rupp rupp@iue.tuwien.ac.at 00009 Florian Rudolf flo.rudy+viennacl@gmail.com 00010 Josef Weinbub weinbub@iue.tuwien.ac.at 00011 00012 license: MIT (X11), see file LICENSE in the ViennaCL base directory 00013 ======================================================================= */ 00014 00015 00016 #ifndef _VIENNACL_MATRIX_MARKET_HPP_ 00017 #define _VIENNACL_MATRIX_MARKET_HPP_ 00018 00023 #include <algorithm> 00024 #include <string> 00025 #include <iostream> 00026 #include <fstream> 00027 #include <sstream> 00028 #include <vector> 00029 #include <map> 00030 #include <cctype> 00031 #include "viennacl/tools/adapter.hpp" 00032 00033 namespace viennacl 00034 { 00035 namespace io 00036 { 00037 //helper 00038 namespace 00039 { 00040 void trim(char * buffer, long max_size) 00041 { 00042 //trim at beginning of string 00043 long start = 0; 00044 for (long i=0; i<max_size; ++i) 00045 { 00046 if (buffer[i] == ' ') 00047 ++start; 00048 else 00049 break; 00050 } 00051 00052 //trim at end of string 00053 long stop = start; 00054 for (long i=stop; i<max_size; ++i) 00055 { 00056 if (buffer[i] == 0) //end of string 00057 break; 00058 00059 if (buffer[i] != ' ') 00060 stop = i; 00061 } 00062 00063 for (long i=0; i<=stop - start; ++i) 00064 { 00065 buffer[i] = buffer[start + i]; 00066 } 00067 00068 if (buffer[0] != ' ') 00069 buffer[stop - start + 1] = 0; //terminate string 00070 else 00071 buffer[0] = 0; 00072 } 00073 00074 std::string tolower(std::string & s) 00075 { 00076 std::transform(s.begin(), s.end(), s.begin(), static_cast < int(*)(int) > (std::tolower)); 00077 return s; 00078 } 00079 00080 00081 00082 } //namespace 00083 00085 00094 template <typename MatrixType> 00095 long read_matrix_market_file_impl(MatrixType & mat, 00096 const char * file, 00097 long index_base) 00098 { 00099 std::cout << "Reading matrix market file" << std::endl; 00100 char buffer[1025]; 00101 std::ifstream reader(file); 00102 std::string token; 00103 long linenum = 0; 00104 bool symmetric = false; 00105 bool dense_format = false; 00106 bool is_header = true; 00107 long cur_row = 0; 00108 long cur_col = 0; 00109 long valid_entries = 0; 00110 long nnz = 0; 00111 00112 00113 if (!reader){ 00114 std::cerr << "ViennaCL: Matrix Market Reader: Cannot open file " << file << std::endl; 00115 return 0; 00116 } 00117 00118 while (reader.good()) 00119 { 00120 // get a non-empty line 00121 do 00122 { 00123 reader.getline(buffer, 1024); 00124 ++linenum; 00125 trim(buffer, 1024); 00126 } 00127 while (reader.good() && buffer[0] == 0); 00128 00129 if (buffer[0] == '%') 00130 { 00131 if (buffer[1] == '%') 00132 { 00133 //parse header: 00134 std::stringstream line(std::string(buffer + 2)); 00135 line >> token; 00136 if (tolower(token) != "matrixmarket") 00137 { 00138 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'MatrixMarket', got '" << token << "'" << std::endl; 00139 return 0; 00140 } 00141 00142 line >> token; 00143 if (tolower(token) != "matrix") 00144 { 00145 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'matrix', got '" << token << "'" << std::endl; 00146 return 0; 00147 } 00148 00149 line >> token; 00150 if (tolower(token) != "coordinate") 00151 { 00152 if (tolower(token) == "array") 00153 { 00154 dense_format = true; 00155 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": 'array' type is not supported yet!" << std::endl; 00156 return 0; 00157 } 00158 else 00159 { 00160 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'array' or 'coordinate', got '" << token << "'" << std::endl; 00161 return 0; 00162 } 00163 } 00164 00165 line >> token; 00166 if (tolower(token) != "real") 00167 { 00168 std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only real valued floating point arithmetic." << std::endl; 00169 return 0; 00170 } 00171 00172 line >> token; 00173 if (tolower(token) == "general"){ } 00174 else if (tolower(token) == "symmetric"){ symmetric = true; } 00175 else 00176 { 00177 std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only general or symmetric matrices." << std::endl; 00178 return 0; 00179 } 00180 00181 } 00182 } 00183 else 00184 { 00185 std::stringstream line(std::stringstream::in | std::stringstream::out); 00186 line << std::string(buffer); 00187 00188 if (is_header) 00189 { 00190 //read header line 00191 long rows; 00192 long cols; 00193 00194 if (line.good()) 00195 line >> rows; 00196 else 00197 { 00198 std::cerr << "Error in file " << file << ": Could not get matrix dimensions (rows) in line " << linenum << std::endl; 00199 return 0; 00200 } 00201 00202 if (line.good()) 00203 line >> cols; 00204 else 00205 { 00206 std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl; 00207 return 0; 00208 } 00209 if (!dense_format) 00210 { 00211 if (line.good()) 00212 line >> nnz; 00213 else 00214 { 00215 std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl; 00216 return 0; 00217 } 00218 } 00219 00220 if (rows > 0 && cols > 0) 00221 mat.resize(rows, cols, false); 00222 00223 is_header = false; 00224 } 00225 else 00226 { 00227 //read data 00228 if (dense_format) 00229 { 00230 double value; 00231 line >> value; 00232 mat(cur_row, cur_col) = value; 00233 00234 if (++cur_row == static_cast<long>(mat.size1())) 00235 { 00236 //next column 00237 ++cur_col; 00238 cur_row = 0; 00239 } 00240 } 00241 else //sparse format 00242 { 00243 long row; 00244 long col; 00245 double value; 00246 00247 //parse data: 00248 if (line.good()) 00249 line >> row; 00250 else 00251 { 00252 std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl; 00253 return 0; 00254 } 00255 00256 if (line.good()) 00257 line >> col; 00258 else 00259 { 00260 std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl; 00261 return 0; 00262 } 00263 00264 //take index_base base into account: 00265 row -= index_base; 00266 col -= index_base; 00267 00268 if (line.good()) 00269 line >> value; 00270 else 00271 { 00272 std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl; 00273 return 0; 00274 } 00275 00276 if (row >= static_cast<long>(mat.size1()) || row < 0) 00277 { 00278 std::cerr << "Error in file " << file << " at line " << linenum << ": Row index out of bounds: " << row << " (matrix dim: " << mat.size1() << " x " << mat.size2() << ")" << std::endl; 00279 return 0; 00280 } 00281 00282 if (col >= static_cast<long>(mat.size2()) || col < 0) 00283 { 00284 std::cerr << "Error in file " << file << " at line " << linenum << ": Column index out of bounds: " << col << " (matrix dim: " << mat.size1() << " x " << mat.size2() << ")" << std::endl; 00285 return 0; 00286 } 00287 00288 mat(row, col) = value; 00289 if (symmetric) 00290 mat(col, row) = value; 00291 00292 if (++valid_entries == nnz) 00293 break; 00294 00295 } //else dense_format 00296 } 00297 } 00298 } 00299 00300 std::cout << linenum << " lines read." << std::endl; 00301 reader.close(); 00302 return linenum; 00303 } 00304 00305 00314 template <typename MatrixType> 00315 long read_matrix_market_file(MatrixType & mat, 00316 const char * file, 00317 long index_base = 1) 00318 { 00319 return read_matrix_market_file_impl(mat, file, index_base); 00320 } 00321 00322 template <typename MatrixType> 00323 long read_matrix_market_file(MatrixType & mat, 00324 const std::string & file, 00325 long index_base = 1) 00326 { 00327 return read_matrix_market_file_impl(mat, file.c_str(), index_base); 00328 } 00329 00330 template <typename ScalarType> 00331 long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat, 00332 const char * file, 00333 long index_base = 1) 00334 { 00335 viennacl::tools::sparse_matrix_adapter<ScalarType> adapted_matrix(mat); 00336 return read_matrix_market_file_impl(adapted_matrix, file, index_base); 00337 } 00338 00339 template <typename ScalarType> 00340 long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat, 00341 const std::string & file, 00342 long index_base = 1) 00343 { 00344 viennacl::tools::sparse_matrix_adapter<ScalarType> adapted_matrix(mat); 00345 return read_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base); 00346 } 00347 00348 00350 template <typename MatrixType> 00351 void write_matrix_market_file_impl(MatrixType const & mat, const char * file, long index_base) 00352 { 00353 std::ofstream writer(file); 00354 00355 long num_entries = 0; 00356 for (typename MatrixType::const_iterator1 row_it = mat.begin1(); 00357 row_it != mat.end1(); 00358 ++row_it) 00359 for (typename MatrixType::const_iterator2 col_it = row_it.begin(); 00360 col_it != row_it.end(); 00361 ++col_it) 00362 ++num_entries; 00363 00364 writer << "%%MatrixMarket matrix coordinate real general" << std::endl; 00365 writer << mat.size1() << " " << mat.size2() << " " << num_entries << std::endl; 00366 00367 for (typename MatrixType::const_iterator1 row_it = mat.begin1(); 00368 row_it != mat.end1(); 00369 ++row_it) 00370 for (typename MatrixType::const_iterator2 col_it = row_it.begin(); 00371 col_it != row_it.end(); 00372 ++col_it) 00373 writer << col_it.index1() + index_base << " " << col_it.index2() + index_base << " " << *col_it << std::endl; 00374 00375 writer.close(); 00376 } 00377 00378 template <typename ScalarType> 00379 void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat, 00380 const char * file, 00381 long index_base = 1) 00382 { 00383 viennacl::tools::const_sparse_matrix_adapter<ScalarType> adapted_matrix(mat); 00384 return write_matrix_market_file_impl(adapted_matrix, file, index_base); 00385 } 00386 00387 template <typename ScalarType> 00388 void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat, 00389 const std::string & file, 00390 long index_base = 1) 00391 { 00392 viennacl::tools::const_sparse_matrix_adapter<ScalarType> adapted_matrix(mat); 00393 return write_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base); 00394 } 00395 00404 template <typename MatrixType> 00405 void write_matrix_market_file(MatrixType const & mat, 00406 const std::string & file, 00407 long index_base = 1) 00408 { 00409 write_matrix_market_file_impl(mat, file.c_str(), index_base); 00410 } 00411 00412 00413 } //namespace io 00414 } //namespace viennacl 00415 00416 #endif
1.7.6.1