ViennaCL - The Vienna Computing Library: viennacl/io/matrix_market.hpp Source File

ViennaCL - The Vienna Computing Library 1.7.1 Free open-source GPU-accelerated linear algebra and solver library. |

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matrix_market.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_IO_MATRIX_MARKET_HPP
2 #define VIENNACL_IO_MATRIX_MARKET_HPP
3
4 /* =========================================================================
5 Copyright (c) 2010-2016, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8 Portions of this software are copyright by UChicago Argonne, LLC.
9
10 -----------------
11 ViennaCL - The Vienna Computing Library
12 -----------------
13
14 Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15
16 (A list of authors and contributors can be found in the manual)
17
18 License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20
21
26 #include <algorithm>
27 #include <string>
28 #include <iostream>
29 #include <fstream>
30 #include <sstream>
31 #include <vector>
32 #include <map>
33 #include <cctype>
34 #include "viennacl/tools/adapter.hpp"
35 #include "viennacl/traits/size.hpp"
36 #include "viennacl/traits/fill.hpp"
37
38 namespace viennacl
39 {
40 namespace io
41 {
42 //helper
43 namespace detail
44 {
45 inline void trim(char * buffer, long max_size)
46 {
47 //trim at beginning of string
48 long start = 0;
49 for (long i=0; i<max_size; ++i)
50 {
51 if (buffer[i] == ' ')
52 ++start;
53 else
54 break;
55 }
56
57 //trim at end of string
58 long stop = start;
59 for (long i=stop; i<max_size; ++i)
60 {
61 if (buffer[i] == 0) //end of string
62 break;
63
64 if (buffer[i] != ' ')
65 stop = i;
66 }
67
68 for (long i=0; i<=stop - start; ++i)
69 {
70 buffer[i] = buffer[start + i];
71 }
72
73 if (buffer[0] != ' ')
74 buffer[stop - start + 1] = 0; //terminate string
75 else
76 buffer[0] = 0;
77 }
78
79 inline std::string tolower(std::string & s)
80 {
81 std::transform(s.begin(), s.end(), s.begin(), static_cast < int(*)(int) > (std::tolower));
82 return s;
83 }
84
85
86
87 } //namespace
88
90
101 template<typename MatrixT>
102 long read_matrix_market_file_impl(MatrixT & mat,
103 const char * file,
104 long index_base)
105 {
106 typedef typename viennacl::result_of::cpu_value_type<typename viennacl::result_of::value_type<MatrixT>::type>::type ScalarT;
107
108 //std::cout << "Reading matrix market file" << std::endl;
109 char buffer[1025];
110 std::ifstream reader(file);
111 std::string token;
112 long linenum = 0;
113 bool symmetric = false;
114 bool dense_format = false;
115 bool is_header = true;
116 bool pattern_matrix = false;
117 //bool is_complex = false;
118 long cur_row = 0;
119 long cur_col = 0;
120 long valid_entries = 0;
121 long nnz = 0;
122
123
124 if (!reader){
125 std::cerr << "ViennaCL: Matrix Market Reader: Cannot open file " << file << std::endl;
126 return EXIT_FAILURE;
127 }
128
129 while (reader.good())
130 {
131 // get a non-empty line
132 do
133 {
134 reader.getline(buffer, 1024);
135 ++linenum;
136 detail::trim(buffer, 1024);
137 }
138 while (reader.good() && buffer[0] == 0);
139
140 if (buffer[0] == '%')
141 {
142 if (buffer[1] == '%')
143 {
144 //parse header:
145 std::stringstream line(std::string(buffer + 2));
146 line >> token;
147 if (detail::tolower(token) != "matrixmarket")
148 {
149 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'MatrixMarket', got '" << token << "'" << std::endl;
150 return 0;
151 }
152
153 line >> token;
154 if (detail::tolower(token) != "matrix")
155 {
156 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'matrix', got '" << token << "'" << std::endl;
157 return 0;
158 }
159
160 line >> token;
161 if (detail::tolower(token) != "coordinate")
162 {
163 if (detail::tolower(token) == "array")
164 {
165 dense_format = true;
166 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": 'array' type is not supported yet!" << std::endl;
167 return 0;
168 }
169 else
170 {
171 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'array' or 'coordinate', got '" << token << "'" << std::endl;
172 return 0;
173 }
174 }
175
176 line >> token;
177 if (detail::tolower(token) == "pattern")
178 {
179 pattern_matrix = true;
180 }
181 else if (detail::tolower(token) == "complex")
182 {
183 //is_complex = true;
184 }
185 else if (detail::tolower(token) != "real")
186 {
187 std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only real valued floating point arithmetic or pattern type matrices." << std::endl;
188 return 0;
189 }
190
191 line >> token;
192 if (detail::tolower(token) == "general"){ }
193 else if (detail::tolower(token) == "symmetric"){ symmetric = true; }
194 else
195 {
196 std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only general or symmetric matrices." << std::endl;
197 return 0;
198 }
199
200 }
201 }
202 else
203 {
204 std::stringstream line(std::stringstream::in | std::stringstream::out);
205 line << std::string(buffer);
206
207 if (is_header)
208 {
209 //read header line
210 vcl_size_t rows;
211 vcl_size_t cols;
212
213 if (line.good())
214 line >> rows;
215 else
216 {
217 std::cerr << "Error in file " << file << ": Could not get matrix dimensions (rows) in line " << linenum << std::endl;
218 return 0;
219 }
220
221 if (line.good())
222 line >> cols;
223 else
224 {
225 std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
226 return 0;
227 }
228 if (!dense_format)
229 {
230 if (line.good())
231 line >> nnz;
232 else
233 {
234 std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
235 return 0;
236 }
237 }
238
239 if (rows > 0 && cols > 0)
240 viennacl::traits::resize(mat, rows, cols);
241
242 is_header = false;
243 }
244 else
245 {
246 //read data
247 if (dense_format)
248 {
249 ScalarT value;
250 line >> value;
251 viennacl::traits::fill(mat, static_cast<vcl_size_t>(cur_row), static_cast<vcl_size_t>(cur_col), value);
252
253 if (++cur_row == static_cast<long>(viennacl::traits::size1(mat)))
254 {
255 //next column
256 ++cur_col;
257 cur_row = 0;
258 }
259 }
260 else //sparse format
261 {
262 long row;
263 long col;
264 ScalarT value = ScalarT(1);
265
266 //parse data:
267 if (line.good())
268 line >> row;
269 else
270 {
271 std::cerr << "Error in file " << file << ": Parse error for matrix row entry in line " << linenum << std::endl;
272 return 0;
273 }
274
275 if (line.good())
276 line >> col;
277 else
278 {
279 std::cerr << "Error in file " << file << ": Parse error for matrix col entry in line " << linenum << std::endl;
280 return 0;
281 }
282
283 //take index_base base into account:
284 row -= index_base;
285 col -= index_base;
286
287 if (!pattern_matrix) // value for pattern matrix is implicitly 1, so we only need to read data for 'normal' matrices
288 {
289 if (line.good())
290 {
291 line >> value;
292 }
293 else
294 {
295 std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
296 return 0;
297 }
298 }
299
300 if (row >= static_cast<long>(viennacl::traits::size1(mat)) || row < 0)
301 {
302 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;
303 return 0;
304 }
305
306 if (col >= static_cast<long>(viennacl::traits::size2(mat)) || col < 0)
307 {
308 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;
309 return 0;
310 }
311
312 viennacl::traits::fill(mat, static_cast<vcl_size_t>(row), static_cast<vcl_size_t>(col), value); //basically equivalent to mat(row, col) = value;
313 if (symmetric)
314 viennacl::traits::fill(mat, static_cast<vcl_size_t>(col), static_cast<vcl_size_t>(row), value); //basically equivalent to mat(col, row) = value;
315
316 if (++valid_entries == nnz)
317 break;
318
319 } //else dense_format
320 }
321 }
322 }
323
324 //std::cout << linenum << " lines read." << std::endl;
325 reader.close();
326 return linenum;
327 }
328
329
338 template<typename MatrixT>
339 long read_matrix_market_file(MatrixT & mat,
340 const char * file,
341 long index_base = 1)
342 {
343 return read_matrix_market_file_impl(mat, file, index_base);
344 }
345
346 template<typename MatrixT>
347 long read_matrix_market_file(MatrixT & mat,
348 const std::string & file,
349 long index_base = 1)
350 {
351 return read_matrix_market_file_impl(mat, file.c_str(), index_base);
352 }
353
354 template<typename ScalarT>
355 long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarT> > & mat,
356 const char * file,
357 long index_base = 1)
358 {
359 viennacl::tools::sparse_matrix_adapter<ScalarT> adapted_matrix(mat);
360 return read_matrix_market_file_impl(adapted_matrix, file, index_base);
361 }
362
363 template<typename ScalarT>
364 long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarT> > & mat,
365 const std::string & file,
366 long index_base = 1)
367 {
368 viennacl::tools::sparse_matrix_adapter<ScalarT> adapted_matrix(mat);
369 return read_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
370 }
371
372
374 template<typename MatrixT>
375 void write_matrix_market_file_impl(MatrixT const & mat, const char * file, long index_base)
376 {
377 std::ofstream writer(file);
378
379 long num_entries = 0;
380 for (typename MatrixT::const_iterator1 row_it = mat.begin1();
381 row_it != mat.end1();
382 ++row_it)
383 for (typename MatrixT::const_iterator2 col_it = row_it.begin();
384 col_it != row_it.end();
385 ++col_it)
386 ++num_entries;
387
388 writer << "%%MatrixMarket matrix coordinate real general" << std::endl;
389 writer << mat.size1() << " " << mat.size2() << " " << num_entries << std::endl;
390
391 for (typename MatrixT::const_iterator1 row_it = mat.begin1();
392 row_it != mat.end1();
393 ++row_it)
394 for (typename MatrixT::const_iterator2 col_it = row_it.begin();
395 col_it != row_it.end();
396 ++col_it)
397 writer << col_it.index1() + index_base << " " << col_it.index2() + index_base << " " << *col_it << std::endl;
398
399 writer.close();
400 }
401
402 template<typename ScalarT>
403 void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarT> > const & mat,
404 const char * file,
405 long index_base = 1)
406 {
407 viennacl::tools::const_sparse_matrix_adapter<ScalarT> adapted_matrix(mat);
408 return write_matrix_market_file_impl(adapted_matrix, file, index_base);
409 }
410
411 template<typename ScalarT>
412 void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarT> > const & mat,
413 const std::string & file,
414 long index_base = 1)
415 {
416 viennacl::tools::const_sparse_matrix_adapter<ScalarT> adapted_matrix(mat);
417 return write_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
418 }
419
428 template<typename MatrixT>
429 void write_matrix_market_file(MatrixT const & mat,
430 const std::string & file,
431 long index_base = 1)
432 {
433 write_matrix_market_file_impl(mat, file.c_str(), index_base);
434 }
435
436
437 } //namespace io
438 } //namespace viennacl
439
440 #endif
viennacl::traits::fill
void fill(MatrixType &matrix, vcl_size_t row_index, vcl_size_t col_index, NumericT value)
Generic filler routine for setting an entry of a matrix to a particular value.
Definition: fill.hpp:46
viennacl::io::detail::trim
void trim(char *buffer, long max_size)
Definition: matrix_market.hpp:45
adapter.hpp
Adapter classes for sparse matrices made of the STL type std::vector >
size.hpp
Generic size and resize functionality for different vector and matrix types.
viennacl::traits::size1
vcl_size_t size1(MatrixType const &mat)
Generic routine for obtaining the number of rows of a matrix (ViennaCL, uBLAS, etc.)
Definition: size.hpp:163
viennacl::io::write_matrix_market_file_impl
void write_matrix_market_file_impl(MatrixT const &mat, const char *file, long index_base)
Definition: matrix_market.hpp:375
viennacl::traits::size2
result_of::size_type< MatrixType >::type size2(MatrixType const &mat)
Generic routine for obtaining the number of columns of a matrix (ViennaCL, uBLAS, etc...
Definition: size.hpp:201
viennacl::io::write_matrix_market_file
void write_matrix_market_file(std::vector< std::map< unsigned int, ScalarT > > const &mat, const char *file, long index_base=1)
Definition: matrix_market.hpp:403
viennacl::io::detail::tolower
std::string tolower(std::string &s)
Definition: matrix_market.hpp:79
viennacl::traits::resize
void resize(MatrixType &matrix, vcl_size_t rows, vcl_size_t cols)
Generic resize routine for resizing a matrix (ViennaCL, uBLAS, etc.) to a new size/dimension.
Definition: size.hpp:63
viennacl::traits::start
result_of::size_type< T >::type start(T const &obj)
Definition: start.hpp:44
fill.hpp
Generic fill functionality for different matrix types.
viennacl::tools::const_sparse_matrix_adapter
Adapts a constant sparse matrix type made up from std::vector > to basic ub...
Definition: adapter.hpp:183
viennacl::vcl_size_t
std::size_t vcl_size_t
Definition: forwards.h:75
viennacl::io::read_matrix_market_file_impl
long read_matrix_market_file_impl(MatrixT &mat, const char *file, long index_base)
Reads a sparse or dense matrix from a file (MatrixMarket format)
Definition: matrix_market.hpp:102
viennacl::row
vector_expression< const matrix_base< NumericT, F >, const unsigned int, op_row > row(const matrix_base< NumericT, F > &A, unsigned int i)
Definition: matrix.hpp:910
viennacl::result_of::cpu_value_type
Helper meta function for retrieving the main RAM-based value type. Particularly important to obtain T...
Definition: result_of.hpp:269
viennacl::tools::sparse_matrix_adapter
Adapts a non-const sparse matrix type made up from std::vector > to basic u...
Definition: adapter.hpp:357
viennacl::io::read_matrix_market_file
long read_matrix_market_file(MatrixT &mat, const char *file, long index_base=1)
Reads a sparse matrix from a file (MatrixMarket format)
Definition: matrix_market.hpp:339