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>
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 {
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 {
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 {
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 {
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 {
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
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
void trim(char *buffer, long max_size)
Adapter classes for sparse matrices made of the STL type std::vector >
Generic size and resize functionality for different vector and matrix types.
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
void write_matrix_market_file_impl(MatrixT const &mat, const char *file, long index_base)
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
void write_matrix_market_file(std::vector< std::map< unsigned int, ScalarT > > const &mat, const char *file, long index_base=1)
std::string tolower(std::string &s)
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
result_of::size_type< T >::type start(T const &obj)
Definition: start.hpp:44
Generic fill functionality for different matrix types.
Adapts a constant sparse matrix type made up from std::vector > to basic ub...
Definition: adapter.hpp:183
std::size_t vcl_size_t
Definition: forwards.h:75
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)
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
Helper meta function for retrieving the main RAM-based value type. Particularly important to obtain T...
Definition: result_of.hpp:269
Adapts a non-const sparse matrix type made up from std::vector > to basic u...
Definition: adapter.hpp:357
long read_matrix_market_file(MatrixT &mat, const char *file, long index_base=1)
Reads a sparse matrix from a file (MatrixMarket format)