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