ViennaCL - The Vienna Computing Library
1.5.1
|
00001 #ifndef VIENNACL_TOEPLITZ_MATRIX_HPP 00002 #define VIENNACL_TOEPLITZ_MATRIX_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 "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