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