ViennaCL - The Vienna Computing Library  1.5.1
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-2014, 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 PDF 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 
99  template <typename MatrixType>
100  long read_matrix_market_file_impl(MatrixType & mat,
101  const char * file,
102  long index_base)
103  {
105 
106  //std::cout << "Reading matrix market file" << std::endl;
107  char buffer[1025];
108  std::ifstream reader(file);
109  std::string token;
110  long linenum = 0;
111  bool symmetric = false;
112  bool dense_format = false;
113  bool is_header = true;
114  long cur_row = 0;
115  long cur_col = 0;
116  long valid_entries = 0;
117  long nnz = 0;
118 
119 
120  if (!reader){
121  std::cerr << "ViennaCL: Matrix Market Reader: Cannot open file " << file << std::endl;
122  return EXIT_FAILURE;
123  }
124 
125  while (reader.good())
126  {
127  // get a non-empty line
128  do
129  {
130  reader.getline(buffer, 1024);
131  ++linenum;
132  detail::trim(buffer, 1024);
133  }
134  while (reader.good() && buffer[0] == 0);
135 
136  if (buffer[0] == '%')
137  {
138  if (buffer[1] == '%')
139  {
140  //parse header:
141  std::stringstream line(std::string(buffer + 2));
142  line >> token;
143  if (detail::tolower(token) != "matrixmarket")
144  {
145  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'MatrixMarket', got '" << token << "'" << std::endl;
146  return 0;
147  }
148 
149  line >> token;
150  if (detail::tolower(token) != "matrix")
151  {
152  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'matrix', got '" << token << "'" << std::endl;
153  return 0;
154  }
155 
156  line >> token;
157  if (detail::tolower(token) != "coordinate")
158  {
159  if (detail::tolower(token) == "array")
160  {
161  dense_format = true;
162  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": 'array' type is not supported yet!" << std::endl;
163  return 0;
164  }
165  else
166  {
167  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'array' or 'coordinate', got '" << token << "'" << std::endl;
168  return 0;
169  }
170  }
171 
172  line >> token;
173  if (detail::tolower(token) != "real")
174  {
175  std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only real valued floating point arithmetic." << std::endl;
176  return 0;
177  }
178 
179  line >> token;
180  if (detail::tolower(token) == "general"){ }
181  else if (detail::tolower(token) == "symmetric"){ symmetric = true; }
182  else
183  {
184  std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only general or symmetric matrices." << std::endl;
185  return 0;
186  }
187 
188  }
189  }
190  else
191  {
192  std::stringstream line(std::stringstream::in | std::stringstream::out);
193  line << std::string(buffer);
194 
195  if (is_header)
196  {
197  //read header line
198  long rows;
199  long cols;
200 
201  if (line.good())
202  line >> rows;
203  else
204  {
205  std::cerr << "Error in file " << file << ": Could not get matrix dimensions (rows) in line " << linenum << std::endl;
206  return 0;
207  }
208 
209  if (line.good())
210  line >> cols;
211  else
212  {
213  std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
214  return 0;
215  }
216  if (!dense_format)
217  {
218  if (line.good())
219  line >> nnz;
220  else
221  {
222  std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
223  return 0;
224  }
225  }
226 
227  if (rows > 0 && cols > 0)
228  viennacl::traits::resize(mat, rows, cols);
229 
230  is_header = false;
231  }
232  else
233  {
234  //read data
235  if (dense_format)
236  {
237  ScalarType value;
238  line >> value;
239  viennacl::traits::fill(mat, cur_row, cur_col, value);
240 
241  if (++cur_row == static_cast<long>(viennacl::traits::size1(mat)))
242  {
243  //next column
244  ++cur_col;
245  cur_row = 0;
246  }
247  }
248  else //sparse format
249  {
250  long row;
251  long col;
252  ScalarType value;
253 
254  //parse data:
255  if (line.good())
256  line >> row;
257  else
258  {
259  std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
260  return 0;
261  }
262 
263  if (line.good())
264  line >> col;
265  else
266  {
267  std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
268  return 0;
269  }
270 
271  //take index_base base into account:
272  row -= index_base;
273  col -= index_base;
274 
275  if (line.good())
276  line >> value;
277  else
278  {
279  std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
280  return 0;
281  }
282 
283  if (row >= static_cast<long>(viennacl::traits::size1(mat)) || row < 0)
284  {
285  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;
286  return 0;
287  }
288 
289  if (col >= static_cast<long>(viennacl::traits::size2(mat)) || col < 0)
290  {
291  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;
292  return 0;
293  }
294 
295  viennacl::traits::fill(mat, row, col, value); //basically equivalent to mat(row, col) = value;
296  if (symmetric)
297  viennacl::traits::fill(mat, col, row, value); //basically equivalent to mat(col, row) = value;
298 
299  if (++valid_entries == nnz)
300  break;
301 
302  } //else dense_format
303  }
304  }
305  }
306 
307  //std::cout << linenum << " lines read." << std::endl;
308  reader.close();
309  return linenum;
310  }
311 
312 
321  template <typename MatrixType>
322  long read_matrix_market_file(MatrixType & mat,
323  const char * file,
324  long index_base = 1)
325  {
326  return read_matrix_market_file_impl(mat, file, index_base);
327  }
328 
329  template <typename MatrixType>
330  long read_matrix_market_file(MatrixType & mat,
331  const std::string & file,
332  long index_base = 1)
333  {
334  return read_matrix_market_file_impl(mat, file.c_str(), index_base);
335  }
336 
337  template <typename ScalarType>
338  long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat,
339  const char * file,
340  long index_base = 1)
341  {
343  return read_matrix_market_file_impl(adapted_matrix, file, index_base);
344  }
345 
346  template <typename ScalarType>
347  long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat,
348  const std::string & file,
349  long index_base = 1)
350  {
352  return read_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
353  }
354 
355 
357  template <typename MatrixType>
358  void write_matrix_market_file_impl(MatrixType const & mat, const char * file, long index_base)
359  {
360  std::ofstream writer(file);
361 
362  long num_entries = 0;
363  for (typename MatrixType::const_iterator1 row_it = mat.begin1();
364  row_it != mat.end1();
365  ++row_it)
366  for (typename MatrixType::const_iterator2 col_it = row_it.begin();
367  col_it != row_it.end();
368  ++col_it)
369  ++num_entries;
370 
371  writer << "%%MatrixMarket matrix coordinate real general" << std::endl;
372  writer << mat.size1() << " " << mat.size2() << " " << num_entries << std::endl;
373 
374  for (typename MatrixType::const_iterator1 row_it = mat.begin1();
375  row_it != mat.end1();
376  ++row_it)
377  for (typename MatrixType::const_iterator2 col_it = row_it.begin();
378  col_it != row_it.end();
379  ++col_it)
380  writer << col_it.index1() + index_base << " " << col_it.index2() + index_base << " " << *col_it << std::endl;
381 
382  writer.close();
383  }
384 
385  template <typename ScalarType>
386  void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat,
387  const char * file,
388  long index_base = 1)
389  {
391  return write_matrix_market_file_impl(adapted_matrix, file, index_base);
392  }
393 
394  template <typename ScalarType>
395  void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat,
396  const std::string & file,
397  long index_base = 1)
398  {
400  return write_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
401  }
402 
411  template <typename MatrixType>
412  void write_matrix_market_file(MatrixType const & mat,
413  const std::string & file,
414  long index_base = 1)
415  {
416  write_matrix_market_file_impl(mat, file.c_str(), index_base);
417  }
418 
419 
420  } //namespace io
421 } //namespace viennacl
422 
423 #endif
void trim(char *buffer, long max_size)
Definition: matrix_market.hpp:45
long read_matrix_market_file_impl(MatrixType &mat, const char *file, long index_base)
Reads a sparse or dense matrix from a file (MatrixMarket format)
Definition: matrix_market.hpp:100
Adapter classes for sparse matrices made of the STL type std::vector<std::map<SizeType, SCALARTYPE> >
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:216
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:245
std::string tolower(std::string &s)
Definition: matrix_market.hpp:79
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:59
result_of::size_type< T >::type start(T const &obj)
Definition: start.hpp:43
long read_matrix_market_file(MatrixType &mat, const char *file, long index_base=1)
Reads a sparse matrix from a file (MatrixMarket format)
Definition: matrix_market.hpp:322
Generic fill functionality for different matrix types.
Adapts a constant sparse matrix type made up from std::vector<std::map<SizeType, SCALARTYPE> > to bas...
Definition: adapter.hpp:176
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
void fill(MatrixType &matrix, vcl_size_t row_index, vcl_size_t col_index, SCALARTYPE value)
Generic filler routine for setting an entry of a matrix to a particular value.
Definition: fill.hpp:47
void write_matrix_market_file(std::vector< std::map< unsigned int, ScalarType > > const &mat, const char *file, long index_base=1)
Definition: matrix_market.hpp:386
Helper meta function for retrieving the main RAM-based value type. Particularly important to obtain T...
Definition: result_of.hpp:274
Adapts a non-const sparse matrix type made up from std::vector<std::map<SizeType, SCALARTYPE> > to ba...
Definition: adapter.hpp:345
void write_matrix_market_file_impl(MatrixType const &mat, const char *file, long index_base)
Definition: matrix_market.hpp:358