ViennaCL - The Vienna Computing Library
1.5.0
|
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