ViennaCL - The Vienna Computing Library  1.5.0
viennacl/toeplitz_matrix.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_TOEPLITZ_MATRIX_HPP
00002 #define VIENNACL_TOEPLITZ_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/fft.hpp"
00030 
00031 #include "viennacl/linalg/toeplitz_matrix_operations.hpp"
00032 
00033 
00034 namespace viennacl {
00035 
00041     template<class SCALARTYPE, unsigned int ALIGNMENT>
00042     class toeplitz_matrix
00043     {
00044       public:
00045         typedef viennacl::backend::mem_handle                                                              handle_type;
00046         typedef scalar<typename viennacl::tools::CHECK_SCALAR_TEMPLATE_ARGUMENT<SCALARTYPE>::ResultType>   value_type;
00047 
00052         explicit toeplitz_matrix() {}
00053 
00059         explicit toeplitz_matrix(vcl_size_t rows, vcl_size_t cols) : elements_(rows * 2)
00060         {
00061           assert(rows == cols && bool("Toeplitz matrix must be square!"));
00062           (void)cols;  // avoid 'unused parameter' warning in optimized builds
00063         }
00064 
00065 
00072         void resize(vcl_size_t sz, bool preserve = true) {
00073             elements_.resize(sz * 2, 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 
00089 
00093         vcl_size_t size1() const { return elements_.size() / 2; }
00094 
00098         vcl_size_t size2() const { return elements_.size() / 2; }
00099 
00105         vcl_size_t internal_size() const { return elements_.internal_size(); }
00106 
00107 
00115         entry_proxy<SCALARTYPE> operator()(vcl_size_t row_index, vcl_size_t col_index)
00116         {
00117             assert(row_index < size1() && col_index < size2() && bool("Invalid access"));
00118 
00119             long index = static_cast<long>(col_index) - static_cast<long>(row_index);
00120 
00121             if (index < 0)
00122               index = -index;
00123             else if
00124               (index > 0) index = 2 * static_cast<long>(size1()) - index;
00125             return elements_[index];
00126         }
00127 
00128 
00135         toeplitz_matrix<SCALARTYPE, ALIGNMENT>& operator +=(toeplitz_matrix<SCALARTYPE, ALIGNMENT>& that) {
00136             elements_ += that.elements();
00137             return *this;
00138         }
00139 
00140     private:
00141         toeplitz_matrix(toeplitz_matrix const &) {}
00142         toeplitz_matrix & operator=(toeplitz_matrix const & t);
00143 
00144 
00145         viennacl::vector<SCALARTYPE, ALIGNMENT> elements_;
00146     };
00147 
00154     template <typename SCALARTYPE, unsigned int ALIGNMENT>
00155     void copy(std::vector<SCALARTYPE> const & cpu_vec, toeplitz_matrix<SCALARTYPE, ALIGNMENT>& gpu_mat)
00156     {
00157         assert( (gpu_mat.size1() == 0 || (gpu_mat.size1() * 2 - 1)  == cpu_vec.size()) && bool("Size mismatch"));
00158 
00159         vcl_size_t size = gpu_mat.size1();
00160         std::vector<SCALARTYPE> rvrs(cpu_vec.size());
00161         std::copy(cpu_vec.begin(), cpu_vec.end(), rvrs.begin());
00162         std::reverse(rvrs.begin(), rvrs.end());
00163 
00164         std::vector<SCALARTYPE> tmp(size * 2);
00165         std::copy(rvrs.begin() + size - 1, rvrs.end(), tmp.begin());
00166         std::copy(rvrs.begin(), rvrs.begin() + size - 1, tmp.begin() + size + 1);
00167         tmp[size] = 0.0;
00168         copy(tmp, gpu_mat.elements());
00169     }
00170 
00177     template <typename SCALARTYPE, unsigned int ALIGNMENT>
00178     void copy(toeplitz_matrix<SCALARTYPE, ALIGNMENT> const & gpu_mat, std::vector<SCALARTYPE> & cpu_vec)
00179     {
00180         assert((gpu_mat.size1() * 2 - 1)  == cpu_vec.size() && bool("Size mismatch"));
00181 
00182         vcl_size_t size = gpu_mat.size1();
00183         std::vector<SCALARTYPE> tmp(size * 2);
00184         copy(gpu_mat.elements(), tmp);
00185         std::reverse(tmp.begin(), tmp.end());
00186 
00187         std::copy(tmp.begin(), tmp.begin() + size - 1, cpu_vec.begin() + size);
00188         std::copy(tmp.begin() + size, tmp.end(), cpu_vec.begin());
00189 
00190     }
00191 
00198     template <typename SCALARTYPE, unsigned int ALIGNMENT, typename MATRIXTYPE>
00199     void copy(toeplitz_matrix<SCALARTYPE, ALIGNMENT> const & tep_src, MATRIXTYPE & com_dst)
00200     {
00201         assert(tep_src.size1() == viennacl::traits::size1(com_dst) && bool("Size mismatch"));
00202         assert(tep_src.size2() == viennacl::traits::size2(com_dst) && bool("Size mismatch"));
00203 
00204         vcl_size_t size = tep_src.size1();
00205         std::vector<SCALARTYPE> tmp(tep_src.size1() * 2 - 1);
00206         copy(tep_src, tmp);
00207 
00208         for(vcl_size_t i = 0; i < size; i++)
00209             for(vcl_size_t j = 0; j < size; j++)
00210                 com_dst(i, j) = tmp[static_cast<int>(j) - static_cast<int>(i) + static_cast<int>(size) - 1];
00211     }
00212 
00219     template <typename SCALARTYPE, unsigned int ALIGNMENT, typename MATRIXTYPE>
00220     void copy(MATRIXTYPE const & com_src, toeplitz_matrix<SCALARTYPE, ALIGNMENT>& tep_dst)
00221     {
00222         assert( (tep_dst.size1() == 0 || tep_dst.size1() == viennacl::traits::size1(com_src)) && bool("Size mismatch"));
00223         assert( (tep_dst.size2() == 0 || tep_dst.size2() == viennacl::traits::size2(com_src)) && bool("Size mismatch"));
00224 
00225         vcl_size_t size = tep_dst.size1();
00226 
00227         std::vector<SCALARTYPE> tmp(2*size - 1);
00228 
00229         for(long i = static_cast<long>(size) - 1; i >= 0; i--)
00230             tmp[size - i - 1] = com_src(i, 0);
00231 
00232         for(vcl_size_t i = 1; i < size; i++)
00233             tmp[size + i - 1] = com_src(0, i);
00234 
00235         copy(tmp, tep_dst);
00236     }
00237 
00238     /*template <typename SCALARTYPE, unsigned int ALIGNMENT, unsigned int VECTOR_ALIGNMENT>
00239     void prod_impl(toeplitz_matrix<SCALARTYPE, ALIGNMENT>& mat,
00240                    vector<SCALARTYPE, VECTOR_ALIGNMENT>& vec,
00241                    vector<SCALARTYPE, VECTOR_ALIGNMENT>& result) {
00242         viennacl::vector<SCALARTYPE, VECTOR_ALIGNMENT> tep(mat.elements().size() * 2);
00243         fft::real_to_complex(mat.elements(), tep, mat.elements().size());
00244 
00245         viennacl::vector<SCALARTYPE, VECTOR_ALIGNMENT> tmp(vec.size() * 4);
00246         viennacl::vector<SCALARTYPE, VECTOR_ALIGNMENT> tmp2(vec.size() * 4);
00247 
00248         tmp.clear();
00249         copy(vec, tmp);
00250         fft::real_to_complex(tmp, tmp2, vec.size() * 2);
00251         fft::convolve(tep, tmp2, tmp);
00252         fft::complex_to_real(tmp, tmp2, vec.size() * 2);
00253         copy(tmp2.begin(), tmp2.begin() + vec.size(), result.begin());
00254     }*/
00255 
00261     template<class SCALARTYPE, unsigned int ALIGNMENT>
00262     std::ostream & operator<<(std::ostream & s, toeplitz_matrix<SCALARTYPE, ALIGNMENT>& gpu_matrix)
00263     {
00264         vcl_size_t size = gpu_matrix.size1();
00265         std::vector<SCALARTYPE> tmp(2*size - 1);
00266         copy(gpu_matrix, tmp);
00267         s << "[" << size << "," << size << "](";
00268 
00269         for(vcl_size_t i = 0; i < size; i++) {
00270             s << "(";
00271             for(vcl_size_t j = 0; j < size; j++) {
00272                 s << tmp[static_cast<int>(j) - static_cast<int>(i) + static_cast<int>(size - 1)];
00273                 //s << (int)i - (int)j;
00274                 if(j < (size - 1)) s << ",";
00275             }
00276             s << ")";
00277         }
00278         s << ")";
00279         return s;
00280     }
00281 
00282     //
00283     // Specify available operations:
00284     //
00285 
00288     namespace linalg
00289     {
00290       namespace detail
00291       {
00292         // x = A * y
00293         template <typename T, unsigned int A>
00294         struct op_executor<vector_base<T>, op_assign, vector_expression<const toeplitz_matrix<T, A>, const vector_base<T>, op_prod> >
00295         {
00296             static void apply(vector_base<T> & lhs, vector_expression<const toeplitz_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
00297             {
00298               // check for the special case x = A * x
00299               if (viennacl::traits::handle(lhs) == viennacl::traits::handle(rhs.rhs()))
00300               {
00301                 viennacl::vector<T> temp(lhs);
00302                 viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
00303                 lhs = temp;
00304               }
00305               else
00306                 viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), lhs);
00307             }
00308         };
00309 
00310         template <typename T, unsigned int A>
00311         struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const toeplitz_matrix<T, A>, const vector_base<T>, op_prod> >
00312         {
00313             static void apply(vector_base<T> & lhs, vector_expression<const toeplitz_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
00314             {
00315               viennacl::vector<T> temp(lhs);
00316               viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
00317               lhs += temp;
00318             }
00319         };
00320 
00321         template <typename T, unsigned int A>
00322         struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const toeplitz_matrix<T, A>, const vector_base<T>, op_prod> >
00323         {
00324             static void apply(vector_base<T> & lhs, vector_expression<const toeplitz_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
00325             {
00326               viennacl::vector<T> temp(lhs);
00327               viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
00328               lhs -= temp;
00329             }
00330         };
00331 
00332 
00333         // x = A * vec_op
00334         template <typename T, unsigned int A, typename LHS, typename RHS, typename OP>
00335         struct op_executor<vector_base<T>, op_assign, vector_expression<const toeplitz_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> >
00336         {
00337             static void apply(vector_base<T> & lhs, vector_expression<const toeplitz_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
00338             {
00339               viennacl::vector<T> temp(rhs.rhs());
00340               viennacl::linalg::prod_impl(rhs.lhs(), temp, lhs);
00341             }
00342         };
00343 
00344         // x = A * vec_op
00345         template <typename T, unsigned int A, typename LHS, typename RHS, typename OP>
00346         struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const toeplitz_matrix<T, A>, vector_expression<const LHS, const RHS, OP>, op_prod> >
00347         {
00348             static void apply(vector_base<T> & lhs, vector_expression<const toeplitz_matrix<T, A>, vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
00349             {
00350               viennacl::vector<T> temp(rhs.rhs());
00351               viennacl::vector<T> temp_result(lhs);
00352               viennacl::linalg::prod_impl(rhs.lhs(), temp, temp_result);
00353               lhs += temp_result;
00354             }
00355         };
00356 
00357         // x = A * vec_op
00358         template <typename T, unsigned int A, typename LHS, typename RHS, typename OP>
00359         struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const toeplitz_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> >
00360         {
00361             static void apply(vector_base<T> & lhs, vector_expression<const toeplitz_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
00362             {
00363               viennacl::vector<T> temp(rhs.rhs());
00364               viennacl::vector<T> temp_result(lhs);
00365               viennacl::linalg::prod_impl(rhs.lhs(), temp, temp_result);
00366               lhs -= temp_result;
00367             }
00368         };
00369 
00370       } // namespace detail
00371     } // namespace linalg
00372 
00375 }
00376 
00377 #endif // VIENNACL_TOEPLITZ_MATRIX_HPP