ViennaCL - The Vienna Computing Library  1.5.0
viennacl/circulant_matrix.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_CIRCULANT_MATRIX_HPP
00002 #define VIENNACL_CIRCULANT_MATRIX_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2013, 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 "viennacl/forwards.h"
00026 #include "viennacl/vector.hpp"
00027 #include "viennacl/ocl/backend.hpp"
00028 
00029 #include "viennacl/linalg/circulant_matrix_operations.hpp"
00030 
00031 #include "viennacl/fft.hpp"
00032 
00033 namespace viennacl
00034 {
00040     template<class SCALARTYPE, unsigned int ALIGNMENT>
00041     class circulant_matrix
00042     {
00043       public:
00044         typedef viennacl::backend::mem_handle                                                              handle_type;
00045         typedef scalar<typename viennacl::tools::CHECK_SCALAR_TEMPLATE_ARGUMENT<SCALARTYPE>::ResultType>   value_type;
00046 
00051         explicit circulant_matrix() {}
00052 
00059         explicit circulant_matrix(vcl_size_t rows, vcl_size_t cols) : elements_(rows)
00060         {
00061           assert(rows == cols && bool("Circulant matrix must be square!"));
00062           (void)cols;  // avoid 'unused parameter' warning in optimized builds
00063         }
00064 
00071         void resize(vcl_size_t sz, bool preserve = true)
00072         {
00073             elements_.resize(sz, preserve);
00074         }
00075 
00080         handle_type const & handle() const { return elements_.handle(); }
00081 
00086         viennacl::vector<SCALARTYPE, ALIGNMENT> & elements() { return elements_; }
00087         viennacl::vector<SCALARTYPE, ALIGNMENT> const & elements() const { return elements_; }
00088 
00092         vcl_size_t size1() const { return elements_.size(); }
00093 
00097         vcl_size_t size2() const { return elements_.size(); }
00098 
00104         vcl_size_t internal_size() const { return elements_.internal_size(); }
00105 
00113         entry_proxy<SCALARTYPE> operator()(vcl_size_t row_index, vcl_size_t col_index)
00114         {
00115             long index = static_cast<long>(row_index) - static_cast<long>(col_index);
00116 
00117             assert(row_index < size1() && col_index < size2() && bool("Invalid access"));
00118 
00119             while (index < 0)
00120               index += static_cast<long>(size1());
00121             return elements_[index];
00122         }
00123 
00130         circulant_matrix<SCALARTYPE, ALIGNMENT>& operator +=(circulant_matrix<SCALARTYPE, ALIGNMENT>& that)
00131         {
00132             elements_ += that.elements();
00133             return *this;
00134         }
00135 
00136     private:
00137         circulant_matrix(circulant_matrix const &) {}
00138         circulant_matrix & operator=(circulant_matrix const & t);
00139 
00140         viennacl::vector<SCALARTYPE, ALIGNMENT> elements_;
00141     };
00142 
00149     template <typename SCALARTYPE, unsigned int ALIGNMENT>
00150     void copy(std::vector<SCALARTYPE>& cpu_vec, circulant_matrix<SCALARTYPE, ALIGNMENT>& gpu_mat)
00151     {
00152         assert( (gpu_mat.size1() == 0 || cpu_vec.size() == gpu_mat.size1()) && bool("Size mismatch"));
00153         copy(cpu_vec, gpu_mat.elements());
00154     }
00155 
00162     template <typename SCALARTYPE, unsigned int ALIGNMENT>
00163     void copy(circulant_matrix<SCALARTYPE, ALIGNMENT>& gpu_mat, std::vector<SCALARTYPE>& cpu_vec)
00164     {
00165         assert(cpu_vec.size() == gpu_mat.size1() && bool("Size mismatch"));
00166         copy(gpu_mat.elements(), cpu_vec);
00167     }
00168 
00175     template <typename SCALARTYPE, unsigned int ALIGNMENT, typename MATRIXTYPE>
00176     void copy(circulant_matrix<SCALARTYPE, ALIGNMENT>& circ_src, MATRIXTYPE& com_dst) {
00177         vcl_size_t size = circ_src.size1();
00178         assert(size == viennacl::traits::size1(com_dst) && bool("Size mismatch"));
00179         assert(size == viennacl::traits::size2(com_dst) && bool("Size mismatch"));
00180         std::vector<SCALARTYPE> tmp(size);
00181         copy(circ_src, tmp);
00182 
00183         for (vcl_size_t i = 0; i < size; i++) {
00184             for (vcl_size_t j = 0; j < size; j++) {
00185                 long index = static_cast<long>(i) - static_cast<long>(j);
00186                 if (index < 0)
00187                   index = static_cast<long>(size + index);
00188                 com_dst(i, j) = tmp[index];
00189             }
00190         }
00191     }
00192 
00199     template <typename SCALARTYPE, unsigned int ALIGNMENT, typename MATRIXTYPE>
00200     void copy(MATRIXTYPE& com_src, circulant_matrix<SCALARTYPE, ALIGNMENT>& circ_dst)
00201     {
00202         assert( (circ_dst.size1() == 0 || circ_dst.size1() == viennacl::traits::size1(com_src)) && bool("Size mismatch"));
00203         assert( (circ_dst.size2() == 0 || circ_dst.size2() == viennacl::traits::size2(com_src)) && bool("Size mismatch"));
00204 
00205         vcl_size_t size = viennacl::traits::size1(com_src);
00206 
00207         std::vector<SCALARTYPE> tmp(size);
00208 
00209         for(vcl_size_t i = 0; i < size; i++) tmp[i] = com_src(i, 0);
00210 
00211         copy(tmp, circ_dst);
00212     }
00213 
00214     /*namespace linalg
00215     {
00216       template <typename SCALARTYPE, unsigned int ALIGNMENT, unsigned int VECTOR_ALIGNMENT>
00217       void prod_impl(circulant_matrix<SCALARTYPE, ALIGNMENT> const & mat,
00218                       vector<SCALARTYPE, VECTOR_ALIGNMENT> const & vec,
00219                       vector<SCALARTYPE, VECTOR_ALIGNMENT>& result) {
00220           viennacl::vector<SCALARTYPE, VECTOR_ALIGNMENT> circ(mat.elements().size() * 2);
00221           fft::real_to_complex(mat.elements(), circ, mat.elements().size());
00222 
00223           viennacl::vector<SCALARTYPE, VECTOR_ALIGNMENT> tmp(vec.size() * 2);
00224           viennacl::vector<SCALARTYPE, VECTOR_ALIGNMENT> tmp2(vec.size() * 2);
00225 
00226           fft::real_to_complex(vec, tmp, vec.size());
00227           fft::convolve(circ, tmp, tmp2);
00228           fft::complex_to_real(tmp2, result, vec.size());
00229       }
00230     }*/
00231 
00237     template<class SCALARTYPE, unsigned int ALIGNMENT>
00238     std::ostream & operator<<(std::ostream& s, circulant_matrix<SCALARTYPE, ALIGNMENT>& gpu_matrix)
00239     {
00240         vcl_size_t size = gpu_matrix.size1();
00241         std::vector<SCALARTYPE> tmp(size);
00242         copy(gpu_matrix, tmp);
00243         s << "[" << size << "," << size << "](";
00244 
00245         for(vcl_size_t i = 0; i < size; i++) {
00246             s << "(";
00247             for(vcl_size_t j = 0; j < size; j++) {
00248                 long index = static_cast<long>(i) - static_cast<long>(j);
00249                 if(index < 0) index = static_cast<long>(size) + index;
00250                 s << tmp[index];
00251                 //s << index;
00252                 if(j < (size - 1)) s << ",";
00253             }
00254             s << ")";
00255         }
00256         s << ")";
00257         return s;
00258     }
00259 
00260     //
00261     // Specify available operations:
00262     //
00263 
00266     namespace linalg
00267     {
00268       namespace detail
00269       {
00270         // x = A * y
00271         template <typename T, unsigned int A>
00272         struct op_executor<vector_base<T>, op_assign, vector_expression<const circulant_matrix<T, A>, const vector_base<T>, op_prod> >
00273         {
00274             static void apply(vector_base<T> & lhs, vector_expression<const circulant_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
00275             {
00276               // check for the special case x = A * x
00277               if (viennacl::traits::handle(lhs) == viennacl::traits::handle(rhs.rhs()))
00278               {
00279                 viennacl::vector<T> temp(lhs);
00280                 viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
00281                 lhs = temp;
00282               }
00283               else
00284                 viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), lhs);
00285             }
00286         };
00287 
00288         template <typename T, unsigned int A>
00289         struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const circulant_matrix<T, A>, const vector_base<T>, op_prod> >
00290         {
00291             static void apply(vector_base<T> & lhs, vector_expression<const circulant_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
00292             {
00293               viennacl::vector<T> temp(lhs);
00294               viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
00295               lhs += temp;
00296             }
00297         };
00298 
00299         template <typename T, unsigned int A>
00300         struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const circulant_matrix<T, A>, const vector_base<T>, op_prod> >
00301         {
00302             static void apply(vector_base<T> & lhs, vector_expression<const circulant_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
00303             {
00304               viennacl::vector<T> temp(lhs);
00305               viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
00306               lhs -= temp;
00307             }
00308         };
00309 
00310 
00311         // x = A * vec_op
00312         template <typename T, unsigned int A, typename LHS, typename RHS, typename OP>
00313         struct op_executor<vector_base<T>, op_assign, vector_expression<const circulant_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> >
00314         {
00315             static void apply(vector_base<T> & lhs, vector_expression<const circulant_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
00316             {
00317               viennacl::vector<T> temp(rhs.rhs());
00318               viennacl::linalg::prod_impl(rhs.lhs(), temp, lhs);
00319             }
00320         };
00321 
00322         // x = A * vec_op
00323         template <typename T, unsigned int A, typename LHS, typename RHS, typename OP>
00324         struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const circulant_matrix<T, A>, vector_expression<const LHS, const RHS, OP>, op_prod> >
00325         {
00326             static void apply(vector_base<T> & lhs, vector_expression<const circulant_matrix<T, A>, vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
00327             {
00328               viennacl::vector<T> temp(rhs.rhs());
00329               viennacl::vector<T> temp_result(lhs);
00330               viennacl::linalg::prod_impl(rhs.lhs(), temp, temp_result);
00331               lhs += temp_result;
00332             }
00333         };
00334 
00335         // x = A * vec_op
00336         template <typename T, unsigned int A, typename LHS, typename RHS, typename OP>
00337         struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const circulant_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> >
00338         {
00339             static void apply(vector_base<T> & lhs, vector_expression<const circulant_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
00340             {
00341               viennacl::vector<T> temp(rhs.rhs());
00342               viennacl::vector<T> temp_result(lhs);
00343               viennacl::linalg::prod_impl(rhs.lhs(), temp, temp_result);
00344               lhs -= temp_result;
00345             }
00346         };
00347 
00348       } // namespace detail
00349     } // namespace linalg
00350 
00352 }
00353 
00354 #endif // VIENNACL_CIRCULANT_MATRIX_HPP