00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00038 namespace
00039 {
00040 void trim(char * buffer, long max_size)
00041 {
00042
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
00053 long stop = start;
00054 for (long i=stop; i<max_size; ++i)
00055 {
00056 if (buffer[i] == 0)
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;
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 }
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
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
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
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
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
00237 ++cur_col;
00238 cur_row = 0;
00239 }
00240 }
00241 else
00242 {
00243 long row;
00244 long col;
00245 double value;
00246
00247
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
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 }
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 }
00414 }
00415
00416 #endif