IOMatrixMarket.cxx
1 // Copyright (C) 2001-2011 Vivien Mallet
2 // Copyright (C) 2001-2011 Marc DuruflĂ©
3 //
4 // This file is part of the linear-algebra library Seldon,
5 // http://seldon.sourceforge.net/.
6 //
7 // Seldon is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your option)
10 // any later version.
11 //
12 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with Seldon. If not, see http://www.gnu.org/licenses/.
19 
20 
21 #ifndef SELDON_FILE_MATRIX_SPARSE_IOMATRIXMARKET_CXX
22 
23 
24 #include "IOMatrixMarket.hxx"
25 #include <iomanip>
26 
27 /*
28  Functions defined in this file:
29  (storage RowSparse, ColSparse, RowSymSparse, ColSymSparse,
30  ArrayRowSparse, ArrayColSparse, ArrayRowSymSparse, ArrayColSymSparse
31  and equivalent complex storages if SeldonComplexMatrix.hxx is included)
32 
33  A is read in Harwell-Boeing format (.rua, .rsa, .rra, .cua, .cra or .csa)
34  ReadHarwellBoeing(file_name, A)
35 
36  A is written in Harwell-Boeing format
37  WriteHarwellBoeing(A, file_name)
38 
39  A is read in Matrix-Market format (.mtx)
40  ReadMatrixMarket(file_name, A)
41 
42  A is written in Matrix-Market format (.mtx)
43  WriteMatrixMarket(A, file_name)
44 
45  Internal functions (do not use directly) :
46  ReadComplexValuesHarwell
47  PrintComplexValuesHarwell
48 
49 */
50 
51 namespace Seldon
52 {
53 
54 
56  // ReadCoordinateMatrix //
58 
59 
61  template<class T>
62  void ReadComplexValue(istream& FileStream, T& entry)
63  {
64  FileStream >> entry;
65  }
66 
67 
69  template<class T>
70  void ReadComplexValue(istream& FileStream, complex<T>& entry)
71  {
72  T a, b;
73  FileStream >> a >> b;
74  entry = complex<T>(a, b);
75  }
76 
77 
79  template<class T>
80  void WriteComplexValue(ostream& FileStream, const T& entry)
81  {
82  FileStream << entry;
83  }
84 
85 
87  template<class T>
88  void WriteComplexValue(ostream& FileStream, const complex<T>& entry)
89  {
90  FileStream << real(entry) << " " << imag(entry);
91  }
92 
93 
95 
103  template<class Tint, class AllocInt, class T, class Allocator>
104  void ReadCoordinateMatrix(istream& FileStream,
108  bool cplx)
109  {
110 #ifdef SELDON_CHECK_IO
111  // Checks if the stream is ready.
112  if (!FileStream.good())
113  throw IOError("ReadCoordinateMatrix", "Stream is not ready.");
114 #endif
115 
116  T entry; int row = 0, col = 0;
117  long nb_elt = 0;
118  SetComplexZero(entry);
119 
120  while (!FileStream.eof())
121  {
122  // new entry is read (1-index)
123  FileStream >> row >> col;
124  if (cplx)
125  ReadComplexValue(FileStream, entry);
126  else
127  FileStream >> entry;
128 
129  if (FileStream.fail())
130  break;
131  else
132  {
133 #ifdef SELDON_CHECK_IO
134  if (row < 1)
135  throw IOError(string("ReadCoordinateMatrix"),
136  string("Error : Row number should be greater ")
137  + "than 0 but is equal to " + to_str(row));
138 
139  if (col < 1)
140  throw IOError(string("ReadCoordinateMatrix"),
141  string("Error : Column number should be greater")
142  + " than 0 but is equal to " + to_str(col));
143 #endif
144 
145  nb_elt++;
146 
147  // inserting new element
148  if (nb_elt > values.GetM())
149  {
150  values.Resize(2*nb_elt);
151  row_numbers.Resize(2*nb_elt);
152  col_numbers.Resize(2*nb_elt);
153  }
154 
155  values(nb_elt-1) = entry;
156  row_numbers(nb_elt-1) = row;
157  col_numbers(nb_elt-1) = col;
158  }
159  }
160 
161  if (nb_elt > 0)
162  {
163  row_numbers.Resize(nb_elt);
164  col_numbers.Resize(nb_elt);
165  values.Resize(nb_elt);
166  }
167  }
168 
169 
171 
182  template<class Matrix1, class T>
183  void ReadCoordinateMatrix(Matrix1& A, istream& FileStream, T& zero,
184  int index, long nnz, bool cplx)
185  {
186  // previous elements are removed
187  A.Clear();
188 
189  Vector<int> row_numbers, col_numbers;
190  Vector<T> values;
191  if (nnz >= 0)
192  {
193  values.Reallocate(nnz);
194  row_numbers.Reallocate(nnz);
195  col_numbers.Reallocate(nnz);
196  values.Fill(0);
197  row_numbers.Zero();
198  col_numbers.Zero();
199  }
200 
201  ReadCoordinateMatrix(FileStream, row_numbers, col_numbers, values, cplx);
202 
203  if (row_numbers.GetM() > 0)
204  ConvertMatrix_from_Coordinates(row_numbers, col_numbers, values,
205  A, index);
206  }
207 
208 
210 
218  template<class Tint, class AllocInt, class T, class Allocator>
219  void WriteCoordinateMatrix(ostream& FileStream,
220  const Vector<Tint, VectFull, AllocInt>& row_numbers,
221  const Vector<Tint, VectFull, AllocInt>& col_numbers,
222  const Vector<T, VectFull, Allocator>& values,
223  bool cplx)
224  {
225  if (cplx)
226  {
227  for (int i = 0; i < row_numbers.GetM(); i++)
228  {
229  FileStream << row_numbers(i) << " " << col_numbers(i) << " ";
230  WriteComplexValue(FileStream, values(i));
231  FileStream << '\n';
232  }
233  }
234  else
235  {
236  for (int i = 0; i < row_numbers.GetM(); i++)
237  FileStream << row_numbers(i) << " " << col_numbers(i)
238  << " " << values(i) << '\n';
239  }
240  }
241 
242 
244 
252  template<class T0, class Prop0, class Storage0, class Alloc0, class T>
253  void WriteCoordinateMatrix(const Matrix<T0, Prop0, Storage0, Alloc0>& A,
254  ostream& FileStream, T& zero,
255  int index, bool cplx)
256  {
257  // conversion to coordinate format (if symmetric part, lower and upper part
258  // are recovered)
259  Vector<int> IndRow, IndCol;
260  Vector<T> Value;
261  ConvertMatrix_to_Coordinates(A, IndRow, IndCol,
262  Value, index, true);
263 
264  WriteCoordinateMatrix(FileStream, IndRow, IndCol, Value, cplx);
265 
266  // if last element is not present, 0 is printed
267  long N = IndRow.GetM()-1;
268  if (N >= 0)
269  {
270  int m = A.GetM()-1, n = A.GetN()-1;
271  SetComplexZero(zero);
272  if ( (IndRow(N) != m+index) || (IndCol(N) != n+index))
273  {
274  if (A(m, n) == zero)
275  {
276  FileStream << m+index << " " << n+index << " ";
277  if (cplx)
278  WriteComplexValue(FileStream, zero);
279  else
280  FileStream << zero;
281 
282  FileStream << '\n';
283  }
284  }
285  }
286  }
287 
288 
290 
302  template <class T, class Prop, class Allocator>
303  void ReadHarwellBoeing(string filename,
305  {
306  ReadHarwellBoeing(filename, "real", "general", A);
307  }
308 
309 
312  template <class T, class Prop, class Allocator>
313  void ReadHarwellBoeing(string filename,
314  Matrix<complex<T>, Prop, ColSparse, Allocator>& A)
315  {
316  ReadHarwellBoeing(filename, "complex", "general", A);
317  }
318 
319 
322  template <class T, class Prop, class Allocator>
323  void ReadHarwellBoeing(string filename,
325  {
326  ReadHarwellBoeing(filename, "real", "symmetric", A);
327  }
328 
329 
332  template <class T, class Prop, class Allocator>
333  void ReadHarwellBoeing(string filename,
334  Matrix<complex<T>, Prop, RowSymSparse, Allocator>& A)
335  {
336  ReadHarwellBoeing(filename, "complex", "symmetric", A);
337  }
338 
339 
342  template <class T, class T2, class Storage, class Allocator>
343  void ReadHarwellBoeing(string filename, const T2& val,
345  {
347  ReadHarwellBoeing(filename, "real", "symmetric", B);
348  Copy(B, A);
349  }
350 
351 
354  template <class T, class T2, class Storage, class Allocator>
355  void ReadHarwellBoeing(string filename, const T2& val,
357  {
359  ReadHarwellBoeing(filename, "real", "general", B);
360  Copy(B, A);
361  }
362 
363 
366  template <class T, class T2, class Storage, class Allocator>
367  void ReadHarwellBoeing(string filename, const complex<T2>& val,
369  {
371  ReadHarwellBoeing(filename, "complex", "symmetric", B);
372  Copy(B, A);
373  }
374 
375 
378  template <class T, class T2, class Storage, class Allocator>
379  void ReadHarwellBoeing(string filename, const complex<T2>& val,
381  {
383  ReadHarwellBoeing(filename, "complex", "general", B);
384  Copy(B, A);
385  }
386 
387 
390  template <class T, class Prop, class Storage, class Allocator>
391  void ReadHarwellBoeing(string filename,
393  {
395  ReadHarwellBoeing(filename, val, A);
396  }
397 
398 
399  template<class T>
400  void ReadComplexValuesHarwell(long Nnonzero, int Nline_val, int line_width_val,
401  int element_width_val,
402  istream& input_stream, T* A_data)
403  {
404  string line, value;
405  string::size_type pos;
406  long index = 0;
407  for (int i = 0; i < Nline_val; i++)
408  {
409  getline(input_stream, line);
410  int k = 0;
411  for (int j = 0; j < line_width_val; j++)
412  {
413  value = line.substr(k, element_width_val);
414  pos = value.find('D');
415  if (pos != string::npos)
416  value[pos] = 'E';
417 
418  istringstream flux(value);
419  flux >> A_data[index];
420  index++;
421  if (index == Nnonzero)
422  // So as not to read more elements than actually available
423  // on the line.
424  break;
425  k += element_width_val;
426  }
427  if (index == Nnonzero)
428  break;
429  }
430  }
431 
432 
433  template<class T>
434  void ReadComplexValuesHarwell(long Nnonzero, int Nline_val, int line_width_val,
435  int element_width_val,
436  istream& input_stream, complex<T>* A_data)
437  {
438  string line, value;
439  string::size_type pos;
440  long index = 0, nb = 0; T a, b(0);
441  for (int i = 0; i < Nline_val; i++)
442  {
443  getline(input_stream, line);
444  int k = 0;
445  for (int j = 0; j < line_width_val; j++)
446  {
447  a = b;
448  value = line.substr(k, element_width_val);
449  pos = value.find('D');
450  if (pos != string::npos)
451  value[pos] = 'E';
452 
453  istringstream flux(value);
454  flux >> b;
455  if (index%2 == 1)
456  {
457  A_data[nb] = complex<T>(a, b);
458  nb++;
459  }
460 
461  index++;
462  if (index == 2*Nnonzero)
463  // So as not to read more elements than actually available
464  // on the line.
465  break;
466  k += element_width_val;
467  }
468  if (index == 2*Nnonzero)
469  break;
470  }
471  }
472 
473 
475 
492  template <class T, class Prop, class Storage, class Allocator>
493  void ReadHarwellBoeing(string filename,
494  string value_type, string matrix_type,
496  {
497  int i, j, k;
498  string line, element;
499 
500  // Dimensions of the output matrix.
501  int Nrow, Ncol;
502  long Nnonzero;
503 
504  ifstream input_stream(filename.c_str());
505 
506 #ifdef SELDON_CHECK_IO
507  // Checks if the stream is ready.
508  if (!input_stream.good())
509  throw IOError("ReadHarwellBoeing(string filename, "
510  "Matrix& A, string value_type, string matrix_type)",
511  "Unable to read file \"" + filename + "\".");
512 #endif
513 
514  /*** Parsing headers ***/
515 
516  // First line.
517  string title, name;
518  getline(input_stream, line);
519  title = line.substr(0, 72);
520  name = line.substr(72, 8);
521 
522  // Second line.
523  int Nline_ptr, Nline_ind, Nline_val, Nline_rhs;
524  input_stream >> i >> Nline_ptr >> Nline_ind >> Nline_val >> Nline_rhs;
525 
526  // Third line.
527  string type;
528  int Nelemental;
529  input_stream >> type >> Nrow >> Ncol >> Nnonzero >> Nelemental;
530 
531 #ifdef SELDON_CHECK_IO
532  // Checks if the stream is still in good shape.
533  if (!input_stream.good())
534  throw IOError("ReadHarwellBoeing(string filename, "
535  "Matrix& A, string value_type, string matrix_type)",
536  "Unable to read integers in file \""
537  + filename + "\".");
538 #endif
539 
540  if (type.size() != 3)
541  throw WrongArgument("ReadHarwellBoeing(string filename, "
542  "Matrix& A, string value_type, string matrix_type)",
543  "File \"" + filename + "\" contains a matrix of "
544  "type \"" + type + "\", which is not a valid type. "
545  "The type must contain exactly three characters.");
546 
547  if (type.substr(0, 1) != "R" && type.substr(0, 1) != "C"
548  && type.substr(0, 1) != "P")
549  throw WrongArgument("ReadHarwellBoeing(string filename, "
550  "Matrix& A, string value_type, string matrix_type)",
551  "File \"" + filename + "\" contains a matrix of "
552  "type \"" + type + "\", which is not a valid type. "
553  "The first character of that type must be 'R', 'C' "
554  "(not supported anyway) or 'P'.");
555 
556  if (type.substr(0, 1) == "R" && value_type != "real")
557  throw WrongArgument("ReadHarwellBoeing(string filename, "
558  "Matrix& A, string value_type, string matrix_type)",
559  "File \"" + filename + "\" contains a real-valued "
560  "matrix, while the input matrix 'A' is not "
561  "declared as such.");
562 
563  if (type.substr(0, 1) == "C" && value_type != "complex")
564  throw WrongArgument("ReadHarwellBoeing(string filename, "
565  "Matrix& A, string value_type, string matrix_type)",
566  "File \"" + filename + "\" contains a complex-valued "
567  "matrix, while the input matrix 'A' is not "
568  "declared as such.");
569 
570  if (type.substr(1, 1) == "H")
571  throw WrongArgument("ReadHarwellBoeing(string filename, "
572  "Matrix& A, string value_type, string matrix_type)",
573  "File \"" + filename + "\" contains a Hermitian "
574  "matrix, which is not supported.");
575 
576  if (type.substr(1, 1) == "Z")
577  throw WrongArgument("ReadHarwellBoeing(string filename, "
578  "Matrix& A, string value_type, string matrix_type)",
579  "File \"" + filename + "\" contains a skew "
580  "symmetric matrix, which is not supported.");
581 
582  if (type.substr(2, 1) == "E")
583  throw WrongArgument("ReadHarwellBoeing(string filename, "
584  "Matrix& A, string value_type, string matrix_type)",
585  "File \"" + filename + "\" contains an elemental "
586  "matrix, which is not supported.");
587 
588  getline(input_stream, line);
589 
590  // Fourth line.
591  getline(input_stream, line);
592  int line_width_ptr(0), element_width_ptr(0);
593  int line_width_ind(0), element_width_ind(0);
594  string::size_type pos1 = line.find('(', 0);
595  string::size_type pos2 = line.find('I', 0);
596  if ((pos2 < 16) && (pos1 < pos2))
597  line_width_ptr = to_num<int>(line.substr(pos1+1, pos2-pos1-1));
598 
599  pos1 = pos2;
600  pos2 = line.find(')', 0);
601  if ((pos2 < 16) && (pos1 < pos2))
602  element_width_ptr = to_num<int>(line.substr(pos1+1, pos2-pos1-1));
603 
604  pos1 = line.find('(', 16);
605  pos2 = line.find('I', 16);
606  if ((pos2 < 32) && (pos1 < pos2))
607  line_width_ind = to_num<int>(line.substr(pos1+1, pos2-pos1-1));
608 
609  pos1 = pos2;
610  pos2 = line.find(')', 16);
611  if ((pos2 < 32) && (pos1 < pos2))
612  element_width_ind = to_num<int>(line.substr(pos1+1, pos2-pos1-1));
613 
614  int line_width_val = 0;
615  int element_width_val = 0;
616  if (type.substr(0, 1) != "P")
617  {
618  element = line.substr(32, 20);
619 
620  // Splits the format to retrieve the useful widths. This part is
621  // tricky because no parsing (in C++) of Fortran format was found.
622  Vector<int> vect;
623  string delimiter = " (ABDEFGILOPZ*.)";
624  string tmp_str;
625  int tmp_int;
626  string::size_type index_beg = element.find_first_not_of(delimiter);
627  string::size_type index_end;
628  while (index_beg != string::npos)
629  {
630  index_end = element.find_first_of(delimiter, index_beg);
631  tmp_str = element.substr(index_beg,
632  index_end == string::npos ?
633  string::npos : (index_end-index_beg));
634  istringstream(tmp_str) >> tmp_int;
635  vect.PushBack(tmp_int);
636  index_beg = element.find_first_not_of(delimiter, index_end);
637  }
638 
639  if (vect.GetM() < 3)
640  throw WrongArgument("ReadHarwellBoeing(string filename, Matrix& A, "
641  "string value_type, string matrix_type)",
642  "File \"" + filename + "\" contains values "
643  "written in format \"" + element + "\", which "
644  "could not be parsed.");
645 
646  line_width_val = vect(vect.GetM() - 3);
647  element_width_val = vect(vect.GetM() - 2);
648  }
649 
650  if ((line_width_ptr == 0) || (element_width_ptr == 0) ||
651  (line_width_ind == 0) || (element_width_ind == 0) ||
652  (line_width_val == 0) || (element_width_val == 0) )
653  throw WrongArgument("ReadHarwellBoeing(string filename, Matrix& A, "
654  "string value_type, string matrix_type)",
655  "Failed to read formats in file"+filename);
656 
657  // Fifth header line, if any: ignored. RHS are not read.
658  if (Nline_rhs != 0)
659  getline(input_stream, line);
660 
661  /*** Allocations ***/
662 
663  typedef typename SeldonDefaultAllocator<VectFull, int>::allocator
664  AllocatorInt;
665 
666  typedef typename SeldonDefaultAllocator<VectFull, long>::allocator
667  AllocatorLong;
668 
669  // Content of output matrix A.
670  long* A_ptr;
671  int* A_ind;
672  T* A_data;
673 
674 #ifdef SELDON_CHECK_MEMORY
675  try
676  {
677 #endif
678 
679  A_ptr = reinterpret_cast<long*>(AllocatorLong::
680  allocate(Ncol + 1));
681 
682 #ifdef SELDON_CHECK_MEMORY
683  }
684  catch (...)
685  {
686  A_ptr = NULL;
687  }
688 
689  if (A_ptr == NULL)
690  throw NoMemory("ReadHarwellBoeing(string filename, "
691  "Matrix& A, string value_type, string matrix_type)",
692  "Unable to allocate memory for an array of "
693  + to_str(Ncol + 1) + " integers.");
694 #endif
695 
696 #ifdef SELDON_CHECK_MEMORY
697  try
698  {
699 #endif
700 
701  // Reallocates 'A_ind' and 'A_data' in order to append the
702  // elements of the i-th row of C.
703  A_ind = reinterpret_cast<int*>(AllocatorInt::allocate(Nnonzero));
704  A_data = reinterpret_cast<T*>
705  (Allocator::allocate(Nnonzero));
706 
707 #ifdef SELDON_CHECK_MEMORY
708  }
709  catch (...)
710  {
711  A_ind = NULL;
712  A_data = NULL;
713  }
714 
715  if (A_ind == NULL || A_data == NULL)
716  throw NoMemory("ReadHarwellBoeing(string filename, "
717  "Matrix& A, string value_type, string matrix_type)",
718  "Unable to allocate memory for an array of "
719  + to_str(Nnonzero) + " integers "
720  "and for an array of "
721  + to_str(sizeof(T) * Nnonzero) + " bytes.");
722 #endif
723 
724  /*** Reads the structure ***/
725 
726  long index = 0;
727  for (i = 0; i < Nline_ptr; i++)
728  {
729  getline(input_stream, line);
730  k = 0;
731  for (j = 0; j < line_width_ptr; j++)
732  {
733  istringstream(line.substr(k, element_width_ptr)) >> A_ptr[index];
734 
735  // The indexes are 1-based, so this corrects it:
736  A_ptr[index]--;
737  index++;
738  if (index == Ncol + 1)
739  // So as not to read more elements than actually available on
740  // the line.
741  break;
742  k += element_width_ptr;
743  }
744  if (index == Ncol + 1)
745  break;
746  }
747 
748  index = 0;
749  for (i = 0; i < Nline_ind; i++)
750  {
751  getline(input_stream, line);
752  k = 0;
753  for (j = 0; j < line_width_ind; j++)
754  {
755  istringstream(line.substr(k, element_width_ind)) >> A_ind[index];
756  // The indexes are 1-based, so this corrects it:
757  A_ind[index]--;
758  index++;
759  if (index == Nnonzero)
760  // So as not to read more elements than actually available on
761  // the line.
762  break;
763  k += element_width_ind;
764  }
765  if (index == Nnonzero)
766  break;
767  }
768 
769  /*** Reads the values ***/
770 
771  if (type.substr(0, 1) == "P")
772  for (long i0 = 0; i0 < Nnonzero; i0++)
773  A_data[i0] = T(1);
774  else
775  {
776  index = 0;
777  ReadComplexValuesHarwell(Nnonzero, Nline_val, line_width_val,
778  element_width_val, input_stream, A_data);
779  }
780 
781 #ifdef SELDON_CHECK_IO
782  // Checks if the stream is still in good shape.
783  if (!input_stream.good())
784  throw IOError("ReadHarwellBoeing(string filename, "
785  "Matrix& A, string value_type, string matrix_type)",
786  "Unable to read all values in file \""
787  + filename + "\".");
788 #endif
789 
790  input_stream.close();
791 
792  A.SetData(Nrow, Ncol, Nnonzero, A_data, A_ptr, A_ind);
793  }
794 
795 
796  template<class T>
797  void PrintComplexValuesHarwell(long nnz, const Vector<complex<T> >& Val,
798  ofstream& file_out)
799  {
800  for (long i = 0; i < 2*nnz; i += 3)
801  {
802  for (long j = i; j < min(i+3, 2*nnz); j++)
803  {
804  if (j%2 == 0)
805  file_out << setw(23) << std::real(Val(j/2));
806  else
807  file_out << setw(23) << std::imag(Val(j/2));
808  }
809 
810  file_out << '\n';
811  }
812  }
813 
814 
815  template<class T>
816  void PrintComplexValuesHarwell(long nnz, const Vector<T>& Val,
817  ofstream& file_out)
818  {
819  for (long i = 0; i < nnz; i += 3)
820  {
821  for (long j = i; j < min(i+3, nnz); j++)
822  file_out << setw(23) << Val(j);
823 
824  file_out << '\n';
825  }
826  }
827 
828 
830  template<class T, class Prop, class Storage, class Allocator>
831  void WriteHarwellBoeing(const Matrix<T, Prop, Storage, Allocator>& A,
832  const string& file_name)
833  {
835  typedef typename ClassComplexType<T>::Treal Treal;
836  bool complex = ( sizeof(Tcplx)/sizeof(Treal) == 2);
837 
838  // converting to CSC
839  Vector<long> Ptr; Vector<int> Ind;
840  Vector<Tcplx> Val;
841  Prop sym;
842  if (IsSymmetricMatrix(A))
843  ConvertToCSR(A, sym, Ptr, Ind, Val);
844  else
845  ConvertToCSC(A, sym, Ptr, Ind, Val);
846 
847  // number of columns and non-zero entries
848  long nnz = Val.GetM();
849  int m = A.GetM();
850  int n = A.GetN();
851 
852  // First line
853  ofstream file_out(file_name.data());
854 
855 #ifdef SELDON_CHECK_IO
856  // Checks if the stream is ready.
857  if (!file_out.good())
858  throw IOError("WriteHarwellBoeing(const Matrix& A, string filename)",
859  "Unable to open file \"" + file_name + "\".");
860 #endif
861 
862  string title("Seldon");
863  string key("S0000008");
864  file_out.setf(ios::left);
865  file_out << setw(72) << title;
866  file_out << setw(8) << key;
867  file_out << endl;
868 
869  // Compute column pointer format
870  int ptr_len = int(ceil( log10(0.1 + nnz + 1) )) + 1;
871  int ptr_nperline = min(80 / ptr_len, n+1);
872  int ptrcrd = n / ptr_nperline + 1;
873  string ptrfmt = string("(") + to_str(ptr_nperline)
874  + "I" + to_str(ptr_len) + ")";
875 
876  // Compute row index format
877  int ind_len = int(ceil( log10(0.1 + n + 1) )) + 1;
878  int ind_nperline = min(80 / ind_len, int(nnz));
879  int indcrd = (nnz-1) / ind_nperline + 1;
880  string indfmt = string("(") + to_str(ind_nperline)
881  + 'I' + to_str(ind_len) + ')';
882 
883  // compute value format
884  string valfmt("(3D23.15)");
885  int valcrd = (nnz-1) / 3 + 1;
886  if (complex)
887  valcrd = (2*nnz-1) / 3 + 1;
888 
889  int rhscrd = 0;
890  int totcrd = ptrcrd + indcrd + valcrd + rhscrd;
891 
892  // Second line
893  file_out << setw(14) << totcrd;
894  file_out << setw(14) << ptrcrd;
895  file_out << setw(14) << indcrd;
896  file_out << setw(14) << valcrd;
897  file_out << setw(14) << rhscrd;
898  file_out << endl;
899 
900  // Third line
901  int neltvl = 0;
902  char mxtype[4];
903  if (complex)
904  mxtype[0] = 'C';
905  else
906  mxtype[0] = 'R';
907 
908  if (m == n)
909  {
910  if (IsSymmetricMatrix(A))
911  mxtype[1] = 'S';
912  else
913  mxtype[1] = 'U';
914  }
915  else
916  mxtype[1] = 'R';
917 
918  mxtype[2] = 'A';
919  mxtype[3] = '\0';
920 
921  file_out << mxtype << " ";
922  file_out << setw(14) << m;
923  file_out << setw(14) << n;
924  file_out << setw(14) << nnz;
925  file_out << setw(14) << neltvl;
926  file_out << endl;
927 
928  // Fourth line
929  file_out << setw(16) << ptrfmt;
930  file_out << setw(16) << indfmt;
931  file_out << setw(20) << valfmt;
932  file_out << setw(20) << valfmt;
933  file_out << endl;
934 
935  // printing ptr values
936  file_out.setf(ios::left);
937  for (int i = 0; i <= n; i += ptr_nperline)
938  {
939  for (int j = i; j < min(i+ptr_nperline, n+1); j++)
940  file_out << setw(ptr_len) << Ptr(j)+1;
941 
942  file_out << '\n';
943  }
944 
945  // printing ind values
946  for (long i = 0; i < nnz; i += ind_nperline)
947  {
948  for (long j = i; j < min(i+ind_nperline, nnz); j++)
949  file_out << setw(ind_len) << Ind(j)+1;
950 
951  file_out << '\n';
952  }
953 
954  // printing values
955  file_out.precision(15);
956  file_out.setf(ios::scientific);
957  PrintComplexValuesHarwell(nnz, Val, file_out);
958 
959  file_out.close();
960  }
961 
962 
964  template <class T, class Prop, class Storage, class Allocator>
965  void ReadMatrixMarket(string filename,
967  {
969  typedef typename ClassComplexType<T>::Treal Treal;
970  bool complex = ( sizeof(Tcplx)/sizeof(Treal) == 2);
971  bool symmetric = IsSymmetricMatrix(A);
972 
973  ifstream input_stream(filename.c_str());
974 
975 #ifdef SELDON_CHECK_IO
976  // Checks if the stream is ready.
977  if (!input_stream.good())
978  throw IOError("ReadMatrixMarket(string filename, Matrix& A)",
979  "Unable to read file \"" + filename + "\".");
980 #endif
981 
982  // first line
983  string line, word1, word2, storage_type, value_type, matrix_type;
984  getline(input_stream, line);
985 
986  istringstream header(line);
987  header >> word1 >> word2 >> storage_type >> value_type >> matrix_type;
988 
989  if (storage_type != "coordinate")
990  throw WrongArgument("ReadMatrixMarket(string filename, Matrix& A)",
991  "The storage should be coordinate in the file");
992 
993  if ( complex && (value_type != "complex") )
994  throw WrongArgument("ReadMatrixMarket(string filename, Matrix& A)",
995  "The matrix should contain complex values");
996 
997  if ( !complex && (value_type != "real") )
998  throw WrongArgument("ReadMatrixMarket(string filename, Matrix& A)",
999  "The matrix should contain real values");
1000 
1001  if ( symmetric && (matrix_type != "symmetric") )
1002  throw WrongArgument("ReadMatrixMarket(string filename, Matrix& A)",
1003  "Problem of symmetry");
1004 
1005  if ( !symmetric && (matrix_type != "general") )
1006  throw WrongArgument("ReadMatrixMarket(string filename, Matrix& A)",
1007  "Problem of symmetry");
1008 
1009  // skipping commentaries
1010  bool comment_line = true;
1011  while (comment_line)
1012  {
1013  getline(input_stream, line);
1014  if ( (line.size() > 0) && (line[0] != '%'))
1015  comment_line = false;
1016 
1017  if (input_stream.eof())
1018  comment_line = false;
1019  }
1020 
1021  // then reading m, n, nnz
1022  int m = 0, n = 0; long nnz = 0;
1023  istringstream size_stream(line);
1024  size_stream >> m >> n >> nnz;
1025 
1026  // then reading i, j, val
1027  Vector<int> row(nnz), col(nnz);
1028  Vector<Tcplx> val(nnz);
1029  ReadCoordinateMatrix(input_stream, row, col, val, complex);
1030 
1031  // closing stream
1032  input_stream.close();
1033 
1034  // for symmetric matrices, row and col are swapped
1035  // because Matrix Market is storing lower part whereas Seldon
1036  // stores upper part of the matrix
1037  A.Reallocate(m, n);
1038  if (symmetric)
1039  ConvertMatrix_from_Coordinates(col, row, val, A, 1);
1040  else
1041  ConvertMatrix_from_Coordinates(row, col, val, A, 1);
1042  }
1043 
1044 
1046  template<class T, class Prop, class Storage, class Allocator>
1047  void WriteMatrixMarket(const Matrix<T, Prop, Storage, Allocator>& A,
1048  const string& file_name)
1049  {
1050  typedef typename Matrix<T, Prop, Storage, Allocator>::entry_type Tcplx;
1051  typedef typename ClassComplexType<T>::Treal Treal;
1052  bool complex = ( sizeof(Tcplx)/sizeof(Treal) == 2);
1053  bool symmetric = IsSymmetricMatrix(A);
1054 
1055  ofstream file_out(file_name.data());
1056  file_out.precision(15);
1057  file_out.setf(ios::scientific);
1058 
1059 #ifdef SELDON_CHECK_IO
1060  // Checks if the stream is ready.
1061  if (!file_out.good())
1062  throw IOError("WriteHarwellBoeing(const Matrix& A, string filename)",
1063  "Unable to open file \"" + file_name + "\".");
1064 #endif
1065 
1066  file_out << "%%MatrixMarket matrix coordinate ";
1067  if (complex)
1068  file_out << "complex ";
1069  else
1070  file_out << "real ";
1071 
1072  if (symmetric)
1073  file_out << "symmetric\n";
1074  else
1075  file_out << "general\n";
1076 
1077  // conversion to coordinate format (with 1-index)
1078  Vector<int> row, col;
1079  Vector<Tcplx> val;
1080  ConvertMatrix_to_Coordinates(A, row, col, val, 1, false);
1081 
1082  file_out << A.GetM() << " " << A.GetN() << " " << val.GetM() << '\n';
1083 
1084  if (symmetric)
1085  {
1086  // storing lower part for symmetric matrices
1087  int itmp;
1088  for (long i = 0; i < row.GetM(); i++)
1089  {
1090  if (row(i) < col(i))
1091  {
1092  itmp = row(i);
1093  row(i) = col(i);
1094  col(i) = itmp;
1095  }
1096  }
1097  }
1098 
1099  WriteCoordinateMatrix(file_out, row, col, val, complex);
1100 
1101  file_out.close();
1102  }
1103 
1104 }
1105 
1106 
1107 #define SELDON_FILE_MATRIX_SPARSE_IOMATRIXMARKET_CXX
1108 #endif
Seldon::WriteComplexValue
void WriteComplexValue(ostream &FileStream, const T &entry)
reads a real or complex value in a file
Definition: IOMatrixMarket.cxx:80
Seldon::ColSparse
Definition: Storage.hxx:79
Seldon::to_str
std::string to_str(const T &input)
Converts most types to string.
Definition: CommonInline.cxx:137
Seldon::Vector_Base::GetM
long GetM() const
Returns the number of elements.
Definition: VectorInline.cxx:131
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::IsSymmetricMatrix
bool IsSymmetricMatrix(const Matrix< T, Prop, Storage, Allocator > &A)
returns true if the matrix is symmetric
Definition: Functions_BaseInline.cxx:778
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::Matrix< T, Prop, ColSparse, Allocator >
Column-major sparse-matrix class.
Definition: Matrix_Sparse.hxx:197
Seldon::Vector< T, VectFull, Allocator >::Resize
void Resize(size_t i)
Changes the length of the vector, and keeps previous values.
Definition: Vector.cxx:34
Seldon::General
Definition: Properties.hxx:26
Seldon::ReadComplexValue
void ReadComplexValue(istream &FileStream, T &entry)
reads a real or complex value in a file
Definition: IOMatrixMarket.cxx:62
Seldon::Vector< T, VectFull, Allocator >
Full vector class.
Definition: Vector.hxx:88
Seldon::Matrix< T, Prop, RowSymSparse, Allocator >
Row-major sparse-matrix class.
Definition: Matrix_SymSparse.hxx:218
Seldon::WrongArgument
Definition: Errors.hxx:76
Seldon::RowSymSparse
Definition: Storage.hxx:114
Seldon::Symmetric
Definition: Properties.hxx:30
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::IOError
Definition: Errors.hxx:150
Seldon::NoMemory
Definition: Errors.hxx:90