ViennaCL - The Vienna Computing Library  1.2.0
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-2011, Institute for Microelectronics,
6  Institute for Analysis and Scientific Computing,
7  TU Wien.
8 
9  -----------------
10  ViennaCL - The Vienna Computing Library
11  -----------------
12 
13  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
14 
15  (A list of authors and contributors can be found in the PDF manual)
16 
17  License: MIT (X11), see file LICENSE in the base directory
18 ============================================================================= */
19 
20 
25 #include <algorithm>
26 #include <string>
27 #include <iostream>
28 #include <fstream>
29 #include <sstream>
30 #include <vector>
31 #include <map>
32 #include <cctype>
34 #include "viennacl/traits/size.hpp"
35 #include "viennacl/traits/fill.hpp"
36 
37 namespace viennacl
38 {
39  namespace io
40  {
41  //helper
42  namespace
43  {
44  void trim(char * buffer, long max_size)
45  {
46  //trim at beginning of string
47  long start = 0;
48  for (long i=0; i<max_size; ++i)
49  {
50  if (buffer[i] == ' ')
51  ++start;
52  else
53  break;
54  }
55 
56  //trim at end of string
57  long stop = start;
58  for (long i=stop; i<max_size; ++i)
59  {
60  if (buffer[i] == 0) //end of string
61  break;
62 
63  if (buffer[i] != ' ')
64  stop = i;
65  }
66 
67  for (long i=0; i<=stop - start; ++i)
68  {
69  buffer[i] = buffer[start + i];
70  }
71 
72  if (buffer[0] != ' ')
73  buffer[stop - start + 1] = 0; //terminate string
74  else
75  buffer[0] = 0;
76  }
77 
78  std::string tolower(std::string & s)
79  {
80  std::transform(s.begin(), s.end(), s.begin(), static_cast < int(*)(int) > (std::tolower));
81  return s;
82  }
83 
84 
85 
86  } //namespace
87 
89 
98  template <typename MatrixType>
99  long read_matrix_market_file_impl(MatrixType & mat,
100  const char * file,
101  long index_base)
102  {
103  std::cout << "Reading matrix market file" << std::endl;
104  char buffer[1025];
105  std::ifstream reader(file);
106  std::string token;
107  long linenum = 0;
108  bool symmetric = false;
109  bool dense_format = false;
110  bool is_header = true;
111  long cur_row = 0;
112  long cur_col = 0;
113  long valid_entries = 0;
114  long nnz = 0;
115 
116 
117  if (!reader){
118  std::cerr << "ViennaCL: Matrix Market Reader: Cannot open file " << file << std::endl;
119  return 0;
120  }
121 
122  while (reader.good())
123  {
124  // get a non-empty line
125  do
126  {
127  reader.getline(buffer, 1024);
128  ++linenum;
129  trim(buffer, 1024);
130  }
131  while (reader.good() && buffer[0] == 0);
132 
133  if (buffer[0] == '%')
134  {
135  if (buffer[1] == '%')
136  {
137  //parse header:
138  std::stringstream line(std::string(buffer + 2));
139  line >> token;
140  if (tolower(token) != "matrixmarket")
141  {
142  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'MatrixMarket', got '" << token << "'" << std::endl;
143  return 0;
144  }
145 
146  line >> token;
147  if (tolower(token) != "matrix")
148  {
149  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'matrix', got '" << token << "'" << std::endl;
150  return 0;
151  }
152 
153  line >> token;
154  if (tolower(token) != "coordinate")
155  {
156  if (tolower(token) == "array")
157  {
158  dense_format = true;
159  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": 'array' type is not supported yet!" << std::endl;
160  return 0;
161  }
162  else
163  {
164  std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'array' or 'coordinate', got '" << token << "'" << std::endl;
165  return 0;
166  }
167  }
168 
169  line >> token;
170  if (tolower(token) != "real")
171  {
172  std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only real valued floating point arithmetic." << std::endl;
173  return 0;
174  }
175 
176  line >> token;
177  if (tolower(token) == "general"){ }
178  else if (tolower(token) == "symmetric"){ symmetric = true; }
179  else
180  {
181  std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only general or symmetric matrices." << std::endl;
182  return 0;
183  }
184 
185  }
186  }
187  else
188  {
189  std::stringstream line(std::stringstream::in | std::stringstream::out);
190  line << std::string(buffer);
191 
192  if (is_header)
193  {
194  //read header line
195  long rows;
196  long cols;
197 
198  if (line.good())
199  line >> rows;
200  else
201  {
202  std::cerr << "Error in file " << file << ": Could not get matrix dimensions (rows) in line " << linenum << std::endl;
203  return 0;
204  }
205 
206  if (line.good())
207  line >> cols;
208  else
209  {
210  std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
211  return 0;
212  }
213  if (!dense_format)
214  {
215  if (line.good())
216  line >> nnz;
217  else
218  {
219  std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
220  return 0;
221  }
222  }
223 
224  if (rows > 0 && cols > 0)
225  viennacl::traits::resize(mat, rows, cols);
226 
227  is_header = false;
228  }
229  else
230  {
231  //read data
232  if (dense_format)
233  {
234  double value;
235  line >> value;
236  viennacl::traits::fill(mat, cur_row, cur_col, value);
237 
238  if (++cur_row == static_cast<long>(viennacl::traits::size1(mat)))
239  {
240  //next column
241  ++cur_col;
242  cur_row = 0;
243  }
244  }
245  else //sparse format
246  {
247  long row;
248  long col;
249  double value;
250 
251  //parse data:
252  if (line.good())
253  line >> row;
254  else
255  {
256  std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
257  return 0;
258  }
259 
260  if (line.good())
261  line >> col;
262  else
263  {
264  std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
265  return 0;
266  }
267 
268  //take index_base base into account:
269  row -= index_base;
270  col -= index_base;
271 
272  if (line.good())
273  line >> value;
274  else
275  {
276  std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
277  return 0;
278  }
279 
280  if (row >= static_cast<long>(viennacl::traits::size1(mat)) || row < 0)
281  {
282  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;
283  return 0;
284  }
285 
286  if (col >= static_cast<long>(viennacl::traits::size2(mat)) || col < 0)
287  {
288  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;
289  return 0;
290  }
291 
292  viennacl::traits::fill(mat, row, col, value); //basically equivalent to mat(row, col) = value;
293  if (symmetric)
294  viennacl::traits::fill(mat, col, row, value); //basically equivalent to mat(col, row) = value;
295 
296  if (++valid_entries == nnz)
297  break;
298 
299  } //else dense_format
300  }
301  }
302  }
303 
304  std::cout << linenum << " lines read." << std::endl;
305  reader.close();
306  return linenum;
307  }
308 
309 
318  template <typename MatrixType>
319  long read_matrix_market_file(MatrixType & mat,
320  const char * file,
321  long index_base = 1)
322  {
323  return read_matrix_market_file_impl(mat, file, index_base);
324  }
325 
326  template <typename MatrixType>
327  long read_matrix_market_file(MatrixType & mat,
328  const std::string & file,
329  long index_base = 1)
330  {
331  return read_matrix_market_file_impl(mat, file.c_str(), index_base);
332  }
333 
334  template <typename ScalarType>
335  long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat,
336  const char * file,
337  long index_base = 1)
338  {
340  return read_matrix_market_file_impl(adapted_matrix, file, index_base);
341  }
342 
343  template <typename ScalarType>
344  long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat,
345  const std::string & file,
346  long index_base = 1)
347  {
349  return read_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
350  }
351 
352 
354  template <typename MatrixType>
355  void write_matrix_market_file_impl(MatrixType const & mat, const char * file, long index_base)
356  {
357  std::ofstream writer(file);
358 
359  long num_entries = 0;
360  for (typename MatrixType::const_iterator1 row_it = mat.begin1();
361  row_it != mat.end1();
362  ++row_it)
363  for (typename MatrixType::const_iterator2 col_it = row_it.begin();
364  col_it != row_it.end();
365  ++col_it)
366  ++num_entries;
367 
368  writer << "%%MatrixMarket matrix coordinate real general" << std::endl;
369  writer << mat.size1() << " " << mat.size2() << " " << num_entries << std::endl;
370 
371  for (typename MatrixType::const_iterator1 row_it = mat.begin1();
372  row_it != mat.end1();
373  ++row_it)
374  for (typename MatrixType::const_iterator2 col_it = row_it.begin();
375  col_it != row_it.end();
376  ++col_it)
377  writer << col_it.index1() + index_base << " " << col_it.index2() + index_base << " " << *col_it << std::endl;
378 
379  writer.close();
380  }
381 
382  template <typename ScalarType>
383  void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat,
384  const char * file,
385  long index_base = 1)
386  {
388  return write_matrix_market_file_impl(adapted_matrix, file, index_base);
389  }
390 
391  template <typename ScalarType>
392  void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat,
393  const std::string & file,
394  long index_base = 1)
395  {
397  return write_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
398  }
399 
408  template <typename MatrixType>
409  void write_matrix_market_file(MatrixType const & mat,
410  const std::string & file,
411  long index_base = 1)
412  {
413  write_matrix_market_file_impl(mat, file.c_str(), index_base);
414  }
415 
416 
417  } //namespace io
418 } //namespace viennacl
419 
420 #endif