• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/data/development/ViennaCL/dev/viennacl/io/matrix_market.hpp

Go to the documentation of this file.
00001 #ifndef VIENNACL_IO_MATRIX_MARKET_HPP
00002 #define VIENNACL_IO_MATRIX_MARKET_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2011, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                   ViennaCL - The Vienna Computing Library
00011                             -----------------
00012 
00013    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00014                
00015    (A list of authors and contributors can be found in the PDF manual)
00016 
00017    License:         MIT (X11), see file LICENSE in the base directory
00018 ============================================================================= */
00019 
00020 
00025 #include <algorithm>
00026 #include <string>
00027 #include <iostream>
00028 #include <fstream>
00029 #include <sstream>
00030 #include <vector>
00031 #include <map>
00032 #include <cctype>
00033 #include "viennacl/tools/adapter.hpp"
00034 #include "viennacl/traits/size.hpp"
00035 #include "viennacl/traits/fill.hpp"
00036 
00037 namespace viennacl
00038 {
00039   namespace io
00040   {
00041     //helper
00042     namespace
00043     {
00044       void trim(char * buffer, long max_size)
00045       {
00046         //trim at beginning of string
00047         long start = 0;
00048         for (long i=0; i<max_size; ++i)
00049         {
00050           if (buffer[i] == ' ')
00051             ++start;
00052           else
00053             break;
00054         }
00055 
00056         //trim at end of string
00057         long stop = start;
00058         for (long i=stop; i<max_size; ++i)
00059         {
00060           if (buffer[i] == 0)   //end of string
00061             break;
00062           
00063           if (buffer[i] != ' ')
00064             stop = i;
00065         }
00066 
00067         for (long i=0; i<=stop - start; ++i)
00068         {
00069           buffer[i] = buffer[start + i];
00070         }
00071         
00072         if (buffer[0] != ' ')
00073           buffer[stop - start + 1] = 0; //terminate string
00074         else
00075           buffer[0] = 0;
00076       }      
00077       
00078       std::string tolower(std::string & s)
00079       {
00080         std::transform(s.begin(), s.end(), s.begin(), static_cast < int(*)(int) > (std::tolower));
00081         return s;
00082       }
00083       
00084       
00085       
00086     } //namespace 
00087     
00089     
00098     template <typename MatrixType>
00099     long read_matrix_market_file_impl(MatrixType & mat,
00100                                       const char * file,
00101                                       long index_base)
00102     {
00103       std::cout << "Reading matrix market file" << std::endl;
00104       char buffer[1025];
00105       std::ifstream reader(file);
00106       std::string token;
00107       long linenum = 0;
00108       bool symmetric = false;
00109       bool dense_format = false;
00110       bool is_header = true;
00111       long cur_row = 0;
00112       long cur_col = 0;
00113       long valid_entries = 0;
00114       long nnz = 0;
00115 
00116       
00117       if (!reader){
00118         std::cerr << "ViennaCL: Matrix Market Reader: Cannot open file " << file << std::endl;
00119         return 0;
00120       }
00121       
00122       while (reader.good())
00123       {
00124         // get a non-empty line
00125         do
00126         {
00127           reader.getline(buffer, 1024);
00128           ++linenum;
00129           trim(buffer, 1024);
00130         }
00131         while (reader.good() && buffer[0] == 0);
00132         
00133         if (buffer[0] == '%')
00134         {
00135           if (buffer[1] == '%')
00136           {
00137             //parse header:
00138             std::stringstream line(std::string(buffer + 2));
00139             line >> token;
00140             if (tolower(token) != "matrixmarket")
00141             {
00142               std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'MatrixMarket', got '" << token << "'" << std::endl;
00143               return 0;
00144             }
00145 
00146             line >> token;
00147             if (tolower(token) != "matrix")
00148             {
00149               std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'matrix', got '" << token << "'" << std::endl;
00150               return 0;
00151             }
00152 
00153             line >> token;
00154             if (tolower(token) != "coordinate")
00155             {
00156               if (tolower(token) == "array")
00157               {
00158                 dense_format = true;
00159                 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": 'array' type is not supported yet!" << std::endl;
00160                 return 0;
00161               }
00162               else
00163               {
00164                 std::cerr << "Error in file " << file << " at line " << linenum << " in file " << file << ": Expected 'array' or 'coordinate', got '" << token << "'" << std::endl;
00165                 return 0;
00166               }
00167             }
00168 
00169             line >> token;
00170             if (tolower(token) != "real")
00171             {
00172               std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only real valued floating point arithmetic." << std::endl;
00173               return 0;
00174             }
00175 
00176             line >> token;
00177             if (tolower(token) == "general"){ }
00178             else if (tolower(token) == "symmetric"){ symmetric = true; }
00179             else
00180             {
00181               std::cerr << "Error in file " << file << ": The MatrixMarket reader provided with ViennaCL supports only general or symmetric matrices." << std::endl;
00182               return 0;
00183             }
00184             
00185           }
00186         }
00187         else
00188         {
00189           std::stringstream line(std::stringstream::in | std::stringstream::out);
00190           line << std::string(buffer);
00191 
00192           if (is_header)
00193           {
00194             //read header line
00195             long rows;
00196             long cols;
00197             
00198             if (line.good())
00199               line >> rows;
00200             else
00201             {
00202               std::cerr << "Error in file " << file << ": Could not get matrix dimensions (rows) in line " << linenum << std::endl;
00203               return 0;
00204             }
00205             
00206             if (line.good())
00207               line >> cols;
00208             else
00209             {
00210               std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
00211               return 0;
00212             }
00213             if (!dense_format)
00214             {
00215               if (line.good())
00216                 line >> nnz;
00217               else
00218               {
00219                 std::cerr << "Error in file " << file << ": Could not get matrix dimensions (columns) in line " << linenum << std::endl;
00220                 return 0;
00221               }
00222             }
00223             
00224             if (rows > 0 && cols > 0)
00225               viennacl::traits::resize(mat, rows, cols);
00226             
00227             is_header = false;
00228           }
00229           else
00230           {
00231             //read data
00232             if (dense_format)
00233             {
00234               double value;
00235               line >> value;
00236               viennacl::traits::fill(mat, cur_row, cur_col, value);
00237               
00238               if (++cur_row == static_cast<long>(viennacl::traits::size1(mat)))
00239               {
00240                 //next column
00241                 ++cur_col;
00242                 cur_row = 0;
00243               }
00244             }
00245             else //sparse format
00246             {
00247               long row;
00248               long col;
00249               double value;
00250               
00251               //parse data:
00252               if (line.good())
00253                 line >> row;
00254               else
00255               {
00256                 std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
00257                 return 0;
00258               }
00259               
00260               if (line.good())
00261                 line >> col;
00262               else
00263               {
00264                 std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
00265                 return 0;
00266               }
00267               
00268               //take index_base base into account:
00269               row -= index_base;
00270               col -= index_base;
00271               
00272               if (line.good())
00273                 line >> value;
00274               else
00275               {
00276                 std::cerr << "Error in file " << file << ": Parse error for matrix entry in line " << linenum << std::endl;
00277                 return 0;
00278               }
00279               
00280               if (row >= static_cast<long>(viennacl::traits::size1(mat)) || row < 0)
00281               {
00282                 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;
00283                 return 0;
00284               }
00285                   
00286               if (col >= static_cast<long>(viennacl::traits::size2(mat)) || col < 0)
00287               {
00288                 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;
00289                 return 0;
00290               }
00291               
00292               viennacl::traits::fill(mat, row, col, value); //basically equivalent to mat(row, col) = value;
00293               if (symmetric)
00294                 viennacl::traits::fill(mat, col, row, value); //basically equivalent to mat(col, row) = value;
00295               
00296               if (++valid_entries == nnz)
00297                 break;
00298               
00299             } //else dense_format
00300           }
00301         }
00302       }
00303       
00304       std::cout << linenum << " lines read." << std::endl;
00305       reader.close();
00306       return linenum;
00307     }
00308     
00309 
00318     template <typename MatrixType>
00319     long read_matrix_market_file(MatrixType & mat,
00320                                  const char * file,
00321                                  long index_base = 1)
00322     {
00323       return read_matrix_market_file_impl(mat, file, index_base);  
00324     }
00325 
00326     template <typename MatrixType>
00327     long read_matrix_market_file(MatrixType & mat,
00328                                  const std::string & file,
00329                                  long index_base = 1)
00330     {
00331       return read_matrix_market_file_impl(mat, file.c_str(), index_base);
00332     }
00333     
00334     template <typename ScalarType>
00335     long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat,
00336                                  const char * file,
00337                                  long index_base = 1)
00338     {
00339       viennacl::tools::sparse_matrix_adapter<ScalarType> adapted_matrix(mat);
00340       return read_matrix_market_file_impl(adapted_matrix, file, index_base);
00341     }
00342     
00343     template <typename ScalarType>
00344     long read_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > & mat,
00345                                  const std::string & file,
00346                                  long index_base = 1)
00347     {
00348       viennacl::tools::sparse_matrix_adapter<ScalarType> adapted_matrix(mat);
00349       return read_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
00350     }
00351 
00352 
00354     template <typename MatrixType>
00355     void write_matrix_market_file_impl(MatrixType const & mat, const char * file, long index_base)
00356     {
00357       std::ofstream writer(file);
00358       
00359       long num_entries = 0;
00360       for (typename MatrixType::const_iterator1 row_it = mat.begin1();
00361             row_it != mat.end1();
00362             ++row_it)
00363         for (typename MatrixType::const_iterator2 col_it = row_it.begin();
00364               col_it != row_it.end();
00365               ++col_it)
00366           ++num_entries;
00367 
00368       writer << "%%MatrixMarket matrix coordinate real general" << std::endl;
00369       writer << mat.size1() << " " << mat.size2() << " " << num_entries << std::endl;
00370       
00371       for (typename MatrixType::const_iterator1 row_it = mat.begin1();
00372             row_it != mat.end1();
00373             ++row_it)
00374         for (typename MatrixType::const_iterator2 col_it = row_it.begin();
00375               col_it != row_it.end();
00376               ++col_it)
00377           writer << col_it.index1() + index_base << " " << col_it.index2() + index_base << " " << *col_it << std::endl;
00378       
00379       writer.close();
00380     }
00381 
00382     template <typename ScalarType>
00383     void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat,
00384                                   const char * file,
00385                                   long index_base = 1)
00386     {
00387       viennacl::tools::const_sparse_matrix_adapter<ScalarType> adapted_matrix(mat);
00388       return write_matrix_market_file_impl(adapted_matrix, file, index_base);
00389     }
00390 
00391     template <typename ScalarType>
00392     void write_matrix_market_file(std::vector< std::map<unsigned int, ScalarType> > const & mat,
00393                                   const std::string & file,
00394                                   long index_base = 1)
00395     {
00396       viennacl::tools::const_sparse_matrix_adapter<ScalarType> adapted_matrix(mat);
00397       return write_matrix_market_file_impl(adapted_matrix, file.c_str(), index_base);
00398     }
00399 
00408     template <typename MatrixType>
00409     void write_matrix_market_file(MatrixType const & mat,
00410                                   const std::string & file,
00411                                   long index_base = 1)
00412     {
00413       write_matrix_market_file_impl(mat, file.c_str(), index_base);
00414     }
00415 
00416     
00417   } //namespace io
00418 } //namespace viennacl
00419 
00420 #endif

Generated on Fri Dec 30 2011 23:20:42 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1