ViennaCL - The Vienna Computing Library  1.5.2
viennacl/tools/adapter.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_TOOLS_ADAPTER_HPP_
00002 #define VIENNACL_TOOLS_ADAPTER_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #include <string>
00026 #include <fstream>
00027 #include <sstream>
00028 #include <assert.h>
00029 #include "viennacl/forwards.h"
00030 
00031 #include <vector>
00032 #include <map>
00033 
00034 namespace viennacl
00035 {
00036   namespace tools
00037   {
00038 
00047     template <typename SCALARTYPE, typename SizeType, bool is_iterator1, bool is_forward>
00048     class const_sparse_matrix_adapted_iterator
00049     {
00050       typedef const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, is_iterator1, is_forward>    self_type;
00051 
00052       public:
00053         typedef self_type     iterator1;
00054         typedef self_type     iterator2;
00055         typedef vcl_size_t   size_type;
00056 
00057         const_sparse_matrix_adapted_iterator(std::vector<std::map<SizeType, SCALARTYPE> > const & mat, int i, int j)
00058          : mat_(mat), i_(i), j_(j)
00059         {
00060           if (i < 0) //reverse iterator end
00061           {
00062             //iter2 = mat_[0].rend();  //reverse iterator end
00063           }
00064           else  //i_ is valid
00065           {
00066             if (j < 0)
00067             {
00068               //iter2 = mat_[i].rend();
00069             }
00070             else //j_ is valid
00071             {
00072               if (i_ < mat_.size() && mat_[i].size() > 0 )
00073               {
00074                 //TODO: Start at entry j, not at the beginning
00075                 if (static_cast<int>(mat_[i].rbegin()->first) < j)
00076                   iter2 = mat_[i].end();
00077                 else
00078                   iter2 = mat_[i].begin();
00079               }
00080               else if (i_ < mat_.size() && mat_[i].size() == 0)
00081                 iter2 = mat_[i].end();
00082               else //i is out of range -> end iterator requested
00083                 iter2 = mat_.back().end(); //forward iterator end
00084             }
00085           }
00086         }
00087 
00088         SCALARTYPE operator*(void) const
00089         {
00090           if (is_iterator1)
00091           {
00092             typedef typename std::map<SizeType, SCALARTYPE>::const_iterator  col_iterator;
00093 
00094             col_iterator colit = mat_[i_].find(static_cast<unsigned int>(j_));
00095 
00096             if (colit != mat_[i_].end())
00097               return colit->second;
00098             return 0.0;
00099           }
00100           else
00101             return iter2->second;
00102         }
00103 
00104         self_type & operator++(void)
00105         {
00106           if (is_iterator1)
00107           {
00108             if (is_forward)
00109               ++i_;
00110             else
00111               --i_;
00112           }
00113           else
00114             ++iter2;
00115           return *this;
00116         }
00117         self_type operator++(int) { self_type tmp = *this; ++(*this); return tmp; }
00118 
00119         self_type operator+=(SizeType offset)
00120         {
00121           if (is_iterator1)
00122           {
00123             if (is_forward)
00124               i_ += offset;
00125             else
00126               i_ -= offset;
00127           }
00128           else
00129           {
00130             for (SizeType k=0; k<offset; ++k)
00131               ++iter2;  //Note: User must ensure that this is always valid...
00132           }
00133           return *this;
00134         }
00135 
00136         bool operator==(self_type const & other) const
00137         {
00138           return is_iterator1 ? (i_ == other.i_) : (iter2 == other.iter2);
00139         }
00140 
00141         bool operator!=(self_type const & other) const { return !(*this == other); }
00142 
00143         size_type index1() const { return i_; }
00144         size_type index2() const
00145         {
00146           if (is_iterator1)
00147             return 0;
00148           else
00149             return iter2->first;
00150         }
00151 
00152         const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1, true> begin() const
00153         {
00154           return const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1, true>(mat_, static_cast<int>(i_), 0);
00155         }
00156         const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1, true> end() const
00157         {
00158           int end_ = static_cast<int>(mat_[i_].size());
00159           if (end_ > 0)
00160             end_ = mat_[i_].rbegin()->first;
00161           return const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1, true>(mat_, static_cast<int>(i_), end_ + 1);
00162         }
00163 
00164       private:
00165         std::vector<std::map<SizeType, SCALARTYPE> > const & mat_;
00166         typename std::map<SizeType, SCALARTYPE>::const_iterator iter2;
00167         size_type i_;
00168         size_type j_;
00169     };
00170 
00175     template <typename SCALARTYPE, typename SizeType = unsigned int>
00176     class const_sparse_matrix_adapter
00177     {
00178       public:
00179         typedef const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, true, true>      const_iterator1;
00180         typedef const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, false, true>     const_iterator2;
00181 
00182         typedef const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, true, false>   const_reverse_iterator1;
00183         typedef SCALARTYPE    value_type;
00184         typedef vcl_size_t   size_type;
00185 
00186         const_sparse_matrix_adapter(std::vector<std::map<SizeType, SCALARTYPE> > const & mat)
00187          : mat_(mat), size1_(mat_.size()), size2_(mat_.size()) {}
00188 
00189         const_sparse_matrix_adapter(std::vector<std::map<SizeType, SCALARTYPE> > const & mat, size_type num_rows, size_type num_cols)
00190          : mat_(mat), size1_(num_rows), size2_(num_cols) {}
00191 
00192         size_type size1() const { return size1_; }
00193         size_type size2() const { return size2_; }
00194 
00195         const_iterator1 begin1() const { return const_iterator1(mat_, 0, 0); }
00196         const_iterator1 end1() const   { return const_iterator1(mat_, static_cast<int>(size1()), static_cast<int>(size2())); }
00197 
00198         const_reverse_iterator1 rbegin1() const { return const_reverse_iterator1(mat_, static_cast<int>(size1() - 1), 0); }
00199         const_reverse_iterator1 rend1() const   { return const_reverse_iterator1(mat_, -1, static_cast<int>(size2())); }
00200 
00201         const_iterator2 begin2() const { return const_iterator2(mat_, 0, 0); }
00202         const_iterator2 end2() const   { return const_iterator2(mat_, size1(), size2()); }
00203 
00204         SCALARTYPE operator()(SizeType i, SizeType j) const
00205         {
00206           typedef typename std::map<SizeType, SCALARTYPE>::const_iterator  col_iterator;
00207 
00208           col_iterator colit = mat_[i].find(j);
00209 
00210           if (colit != mat_[i].end())
00211             return colit->second;
00212           return 0.0;
00213         }
00214 
00215       private:
00216         std::vector<std::map<SizeType, SCALARTYPE> > const & mat_;
00217         size_type size1_;
00218         size_type size2_;
00219     };
00220 
00221 
00229     template <typename SCALARTYPE, typename SizeType, bool is_iterator1>
00230     class sparse_matrix_adapted_iterator
00231     {
00232       typedef sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, is_iterator1>    self_type;
00233 
00234       public:
00235         typedef self_type     iterator1;
00236         typedef self_type     iterator2;
00237         typedef vcl_size_t   size_type;
00238 
00239         sparse_matrix_adapted_iterator(std::vector<std::map<SizeType, SCALARTYPE> > & mat, int i, int j)
00240          : mat_(mat), i_(i), j_(j)
00241         {
00242           if (i < 0) //reverse iterator end
00243           {
00244             //iter2 = mat_[0].rend();  //reverse iterator end
00245           }
00246           else  //_i is valid
00247           {
00248             if (j < 0)
00249             {
00250               //iter2 = mat[i]_.rend();
00251             }
00252             else //_j is valid
00253             {
00254               if (i_ < mat_.size() && mat_[i].size() > 0 )
00255               {
00256                 //TODO: Start at entry j, not at the beginning
00257                 if (static_cast<int>(mat_[i].rbegin()->first) < j)
00258                   iter2 = mat_[i].end();
00259                 else
00260                   iter2 = mat_[i].begin();
00261               }
00262               else if (i_ < mat_.size() && mat_[i].size() == 0)
00263                 iter2 = mat_[i].end();
00264               else //i is out of range -> end iterator requested
00265                 iter2 = mat_.back().end(); //forward iterator end
00266             }
00267           }
00268         }
00269 
00270         SCALARTYPE & operator*(void)
00271         {
00272           if (is_iterator1)
00273           {
00274             return mat_[i_][static_cast<SizeType>(j_)];
00275           }
00276           else
00277             return iter2->second;
00278         }
00279 
00280         self_type & operator++(void)
00281         {
00282           if (is_iterator1)
00283             ++i_;
00284           else
00285             ++iter2;
00286           return *this;
00287         }
00288         self_type operator++(int) { self_type tmp = *this; ++(*this); return tmp; }
00289 
00290         self_type operator+=(size_type offset)
00291         {
00292           if (is_iterator1)
00293             i_ += offset;
00294           else
00295           {
00296             for (size_type k=0; k<offset; ++k)
00297               ++iter2;  //Note: User must ensure that this is always valid...
00298           }
00299           return *this;
00300         }
00301 
00302         bool operator==(self_type const & other) const
00303         {
00304           if (is_iterator1)
00305             return (i_ == other.i_);
00306           return (iter2 == other.iter2);
00307         }
00308         bool operator!=(self_type const & other) const { return !(*this == other); }
00309 
00310         size_type index1() const { return i_; }
00311         size_type index2() const
00312         {
00313           if (is_iterator1)
00314             return 0;
00315           else
00316             return iter2->first;
00317         }
00318 
00319         sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1> begin() const
00320         {
00321           return sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1>(mat_, static_cast<int>(i_), 0);
00322         }
00323         sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1> end() const
00324         {
00325           int end_ = static_cast<int>(mat_[i_].size());
00326           if (end_ > 0)
00327             end_ = mat_[i_].rbegin()->first;
00328           return sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, !is_iterator1>(mat_, static_cast<int>(i_), end_ + 1);
00329         }
00330 
00331       private:
00332         std::vector<std::map<SizeType, SCALARTYPE> > & mat_;
00333         typename std::map<SizeType, SCALARTYPE>::iterator iter2;
00334         size_type i_;
00335         size_type j_;
00336     };
00337 
00338 
00339 
00344     template <typename SCALARTYPE, typename SizeType = unsigned int>
00345     class sparse_matrix_adapter : public const_sparse_matrix_adapter<SCALARTYPE, SizeType>
00346     {
00347         typedef const_sparse_matrix_adapter<SCALARTYPE, SizeType>   BaseType;
00348       public:
00349         typedef sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, true>      iterator1;
00350         typedef sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, false>     iterator2;
00351         typedef const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, true, true>      const_iterator1;
00352         typedef const_sparse_matrix_adapted_iterator<SCALARTYPE, SizeType, false, true>     const_iterator2;
00353         typedef SizeType                                              size_type;
00354 
00355         sparse_matrix_adapter(std::vector<std::map<SizeType, SCALARTYPE> > & mat)
00356          : BaseType(mat), mat_(mat), size1_(mat_.size()), size2_(mat_.size()) {}
00357 
00358         sparse_matrix_adapter(std::vector<std::map<SizeType, SCALARTYPE> > & mat,
00359                               vcl_size_t num_rows,
00360                               vcl_size_t num_cols)
00361          : BaseType(mat, num_rows, num_cols), mat_(mat), size1_(static_cast<size_type>(num_rows)), size2_(static_cast<size_type>(num_cols)) {}
00362 
00363         iterator1 begin1() { return iterator1(mat_, 0, 0); }
00364         iterator1 end1() { return iterator1(mat_, static_cast<int>(mat_.size()), static_cast<int>(mat_.back().size())); }
00365 
00366         const_iterator1 begin1() const { return const_iterator1(mat_, 0, 0); }
00367         const_iterator1 end1() const   { return const_iterator1(mat_, size1(), size2()); }
00368 
00369         iterator2 begin2() { return iterator2(mat_, 0, 0); }
00370         iterator2 end2() { return iterator2(mat_, mat_.size(), mat_.back().size()); }
00371 
00372         const_iterator2 begin2() const { return const_iterator2(mat_, 0, 0); }
00373         const_iterator2 end2() const   { return const_iterator2(mat_, size1(), size2()); }
00374 
00375         SCALARTYPE & operator()(vcl_size_t i, vcl_size_t j) { return mat_[i][static_cast<size_type>(j)]; }
00376 
00377         void resize(vcl_size_t i, vcl_size_t j, bool preserve = true)
00378         {
00379           if (i>0)
00380             mat_.resize(i);
00381           if (!preserve)
00382             clear();
00383 
00384           size1_ = static_cast<size_type>(i);
00385           size2_ = static_cast<size_type>(j);
00386         }
00387 
00388         void clear()
00389         {
00390           for (size_type i=0; i<mat_.size(); ++i)
00391             mat_[i].clear();
00392         }
00393 
00394         size_type size1() { return size1_; }
00395         size_type size1() const { return size1_; } //Note: Due to name hiding it is not sufficient to have it in the base class
00396 
00397         //assume a square matrix
00398         size_type size2() { return size2_; }
00399         size_type size2() const { return size2_; } //Note: Due to name hiding it is not sufficient to have it in the base class
00400 
00401       private:
00402         std::vector<std::map<SizeType, SCALARTYPE> > & mat_;
00403         size_type size1_;
00404         size_type size2_;
00405     };
00406 
00407 
00408   }
00409 }
00410 #endif