Skylark (Sketching Library)
0.1
|
00001 #ifndef SKYLARK_PPT_ELEMENTAL_HPP 00002 #define SKYLARK_PPT_ELEMENTAL_HPP 00003 00004 #if (SKYLARK_HAVE_FFTW || SKYLARK_HAVE_FFTWF) && SKYLARK_HAVE_ELEMENTAL 00005 00006 #include <fftw3.h> 00007 00008 namespace skylark { namespace sketch { 00009 00013 namespace internal { 00014 00015 template <typename T> 00016 struct fftw { 00017 00018 }; 00019 00020 #ifdef SKYLARK_HAVE_FFTW 00021 00022 template <> 00023 struct fftw<double> { 00024 typedef fftw_complex complex_t; 00025 typedef fftw_plan plan_t; 00026 00027 typedef plan_t (*fplanfun_t)(int, double*, complex_t*, unsigned); 00028 static fplanfun_t fplanfun; 00029 typedef plan_t (*bplanfun_t)(int, complex_t*, double*, unsigned); 00030 static bplanfun_t bplanfun; 00031 typedef void (*destroyfun_t)(plan_t); 00032 static destroyfun_t destroyfun; 00033 typedef void (*executeffun_t)(plan_t, double*, complex_t*); 00034 static executeffun_t executeffun; 00035 typedef void (*executebfun_t)(plan_t, complex_t*, double*); 00036 static executebfun_t executebfun; 00037 }; 00038 00039 fftw<double>::fplanfun_t fftw<double>::fplanfun = fftw_plan_dft_r2c_1d; 00040 fftw<double>::bplanfun_t fftw<double>::bplanfun = fftw_plan_dft_c2r_1d; 00041 fftw<double>::destroyfun_t fftw<double>::destroyfun = fftw_destroy_plan; 00042 fftw<double>::executeffun_t fftw<double>::executeffun = fftw_execute_dft_r2c; 00043 fftw<double>::executebfun_t fftw<double>::executebfun = fftw_execute_dft_c2r; 00044 00045 #endif /* SKYLARK_HAVE_FFTW */ 00046 00047 #ifdef SKYLARK_HAVE_FFTWF 00048 00049 template <> 00050 struct fftw<float> { 00051 typedef fftwf_complex complex_t; 00052 typedef fftwf_plan plan_t; 00053 00054 typedef plan_t (*fplanfun_t)(int, float*, complex_t*, unsigned); 00055 static fplanfun_t fplanfun; 00056 typedef plan_t (*bplanfun_t)(int, complex_t*, float*, unsigned); 00057 static bplanfun_t bplanfun; 00058 typedef void (*destroyfun_t)(plan_t); 00059 static destroyfun_t destroyfun; 00060 typedef void (*executeffun_t)(plan_t, float*, complex_t*); 00061 static executffun_t executeffun; 00062 typedef void (*executebfun_t)(plan_t, complex_t*, float*); 00063 static executbfun_t executebfun; 00064 }; 00065 00066 fftw<float>::fplanfun_t fftw<float>::fplanfun = fftwf_plan_dft_r2c_1d; 00067 fftw<float>::bplanfun_t fftw<float>::bplanfun = fftwf_plan_dft_c2r_1d; 00068 fftw<float>::destroyfun_t fftw<float>::destroyfun = fftwf_destroy_plan; 00069 fftw<float>::executeffun_t fftw<float>::executeffun = fftwf_execute_dft_r2c; 00070 fftw<float>::executebfun_t fftw<float>::executebfun = fftwf_execute_dft_c2r; 00071 00072 #endif /* SKYLARK_HAVE_FFTWF */ 00073 00074 } 00079 template<typename ValueType> 00080 struct PPT_t < 00081 elem::Matrix<ValueType>, 00082 elem::Matrix<ValueType> > : 00083 public PPT_data_t, 00084 virtual public sketch_transform_t<elem::Matrix<ValueType>, 00085 elem::Matrix<ValueType> >{ 00086 00087 typedef ValueType value_type; 00088 typedef elem::Matrix<value_type> matrix_type; 00089 typedef elem::Matrix<value_type> output_matrix_type; 00090 00091 typedef PPT_data_t data_type; 00092 typedef data_type::params_t params_t; 00093 00094 PPT_t(int N, int S, int q, double c, double gamma, base::context_t& context) 00095 : data_type (N, S, q, c, gamma, context) { 00096 00097 build_internal(); 00098 } 00099 00100 PPT_t(int N, int S, const params_t& params, base::context_t& context) 00101 : data_type (N, S, params, context) { 00102 00103 build_internal(); 00104 } 00105 00106 PPT_t(const boost::property_tree::ptree &pt) 00107 : data_type(pt) { 00108 build_internal(); 00109 } 00110 00111 template <typename OtherInputMatrixType, 00112 typename OtherOutputMatrixType> 00113 PPT_t(const PPT_t<OtherInputMatrixType, OtherOutputMatrixType>& other) 00114 : data_type(other) { 00115 00116 build_internal(); 00117 } 00118 00119 PPT_t(const data_type& other_data) 00120 : data_type(other_data) { 00121 00122 build_internal(); 00123 } 00124 00125 ~PPT_t() { 00126 internal::fftw<value_type>::destroyfun(_fftw_fplan); 00127 internal::fftw<value_type>::destroyfun(_fftw_bplan); 00128 } 00129 00134 void apply (const matrix_type& A, 00135 output_matrix_type& sketch_of_A, 00136 columnwise_tag dimension) const { 00137 00138 // TODO verify sizes etc. 00139 const int S = data_type::_S; 00140 const int N = data_type::_N; 00141 00142 # ifdef SKYLARK_HAVE_OPENMP 00143 # pragma omp parallel 00144 # endif 00145 { 00146 matrix_type W(S, 1); 00147 matrix_type SAv; 00148 matrix_type Av; 00149 00150 std::complex<value_type> *FW = new std::complex<value_type>[S]; 00151 std::complex<value_type> *P = new std::complex<value_type>[S]; 00152 00153 # ifdef SKYLARK_HAVE_OPENMP 00154 # pragma omp for 00155 # endif 00156 for(int i = 0; i < A.Width(); i++) { 00157 elem::LockedView(Av, A, 0, i, A.Height(), 1); 00158 00159 for(int j = 0; j < S; j++) 00160 P[j] = 1.0; 00161 00162 typename std::list<_CWT_t>::const_iterator it; 00163 int qc = 0; 00164 for(it = _cwts.begin(); it != _cwts.end(); it++, qc++) { 00165 const _CWT_t &C = *it; 00166 C.apply(Av, W, columnwise_tag()); 00167 elem::Scal(std::sqrt(data_type::_gamma), W); 00168 W.Update(data_type::_hash_idx[qc], 0, 00169 std::sqrt(data_type::_c) * data_type::_hash_val[qc]); 00170 internal::fftw<value_type>::executeffun(_fftw_fplan, W.Buffer(), 00171 reinterpret_cast<_fftw_complex_t*>(FW)); 00172 for(int j = 0; j < S; j++) 00173 P[j] *= FW[j]; 00174 } 00175 00176 // In FFTW, both fft and ifft are not scaled. 00177 // That is norm(ifft(fft(x)) = norm(x) * #els(x). 00178 for(int j = 0; j < S; j++) 00179 P[j] /= (value_type)S; 00180 00181 elem::View(SAv, sketch_of_A, 0, i, A.Height(), 1); 00182 internal::fftw<value_type>::executebfun(_fftw_bplan, 00183 reinterpret_cast<_fftw_complex_t*>(P), SAv.Buffer()); 00184 } 00185 00186 delete[] FW; 00187 delete[] P; 00188 00189 } 00190 } 00191 00196 void apply (const matrix_type& A, 00197 output_matrix_type& sketch_of_A, 00198 rowwise_tag dimension) const { 00199 // TODO verify sizes etc. 00200 const int S = data_type::_S; 00201 const int N = data_type::_N; 00202 00203 # ifdef SKYLARK_HAVE_OPENMP 00204 # pragma omp parallel 00205 # endif 00206 { 00207 00208 matrix_type W(S, 1); 00209 matrix_type ASv, SATv(S, 1); 00210 00211 matrix_type Av, ATv; 00212 00213 std::complex<value_type> *FW = new std::complex<value_type>[S]; 00214 std::complex<value_type> *P = new std::complex<value_type>[S]; 00215 00216 # ifdef SKYLARK_HAVE_OPENMP 00217 # pragma omp for 00218 # endif 00219 for(int i = 0; i < A.Height(); i++) { 00220 elem::LockedView(Av, A, i, 0, 1, A.Width()); 00221 elem::Transpose(Av, ATv); 00222 00223 for(int j = 0; j < S; j++) 00224 P[j] = 1.0; 00225 00226 typename std::list<_CWT_t>::const_iterator it; 00227 int qc = 0; 00228 for(it = _cwts.begin(); it != _cwts.end(); it++, qc++) { 00229 const _CWT_t &C = *it; 00230 C.apply(ATv, W, columnwise_tag()); 00231 elem::Scal(std::sqrt(data_type::_gamma), W); 00232 W.Update(data_type::_hash_idx[qc], 0, 00233 std::sqrt(data_type::_c) * data_type::_hash_val[qc]); 00234 internal::fftw<value_type>::executeffun(_fftw_fplan, W.Buffer(), 00235 reinterpret_cast<_fftw_complex_t*>(FW)); 00236 for(int j = 0; j < S; j++) 00237 P[j] *= FW[j]; 00238 } 00239 00240 // In FFTW, both fft and ifft are not scaled. 00241 // That is norm(ifft(fft(x)) = norm(x) * #els(x). 00242 for(int j = 0; j < S; j++) 00243 P[j] /= (value_type)S; 00244 00245 internal::fftw<value_type>::executebfun(_fftw_bplan, 00246 reinterpret_cast<_fftw_complex_t*>(P), SATv.Buffer()); 00247 elem::View(ASv, sketch_of_A, i, 0, 1, sketch_of_A.Width()); 00248 elem::Transpose(SATv, ASv); 00249 } 00250 00251 delete[] FW; 00252 delete[] P; 00253 00254 } 00255 } 00256 00257 int get_N() const { return data_type::_N; } 00258 int get_S() const { return data_type::_S; } 00260 const sketch_transform_data_t* get_data() const { return this; } 00261 00262 protected: 00263 00264 typedef CWT_t<matrix_type, output_matrix_type> _CWT_t; 00265 00266 typedef typename internal::fftw<value_type>::complex_t _fftw_complex_t; 00267 typedef typename internal::fftw<value_type>::plan_t _fftw_plan_t; 00268 00269 _fftw_plan_t _fftw_fplan, _fftw_bplan; 00270 std::list<_CWT_t> _cwts; 00271 00272 void build_internal() { 00273 int S = data_type::_S; 00274 00275 for(typename std::list<CWT_data_t>::iterator it = 00276 data_type::_cwts_data.begin(); 00277 it != data_type::_cwts_data.end(); it++) 00278 _cwts.push_back(_CWT_t(*it)); 00279 00280 double *dtmp = new double[S]; 00281 std::complex<double> *ctmp = new std::complex<double>[S]; 00282 _fftw_fplan = fftw_plan_dft_r2c_1d(S, dtmp, 00283 reinterpret_cast<fftw_complex*>(ctmp), 00284 FFTW_UNALIGNED | FFTW_ESTIMATE); 00285 _fftw_bplan = fftw_plan_dft_c2r_1d(S, 00286 reinterpret_cast<fftw_complex*>(ctmp), dtmp, 00287 FFTW_UNALIGNED | FFTW_ESTIMATE); 00288 delete[] dtmp; 00289 delete[] ctmp; 00290 } 00291 }; 00292 00296 template<typename ValueType> 00297 struct PPT_t < 00298 base::sparse_matrix_t<ValueType>, 00299 elem::Matrix<ValueType> > : 00300 public PPT_data_t, 00301 virtual public sketch_transform_t<base::sparse_matrix_t<ValueType>, 00302 elem::Matrix<ValueType> >{ 00303 00304 typedef ValueType value_type; 00305 typedef base::sparse_matrix_t<value_type> matrix_type; 00306 typedef elem::Matrix<value_type> output_matrix_type; 00307 00308 typedef PPT_data_t data_type; 00309 typedef data_type::params_t params_t; 00310 00311 PPT_t(int N, int S, int q, double c, double gamma, base::context_t& context) 00312 : data_type (N, S, q, c, gamma, context) { 00313 00314 build_internal(); 00315 } 00316 00317 PPT_t(int N, int S, const params_t& params, base::context_t& context) 00318 : data_type (N, S, params, context) { 00319 00320 build_internal(); 00321 } 00322 00323 PPT_t(const boost::property_tree::ptree &pt) 00324 : data_type(pt) { 00325 00326 build_internal(); 00327 } 00328 00329 template <typename OtherInputMatrixType, 00330 typename OtherOutputMatrixType> 00331 PPT_t(const PPT_t<OtherInputMatrixType, OtherOutputMatrixType>& other) 00332 : data_type(other) { 00333 00334 build_internal(); 00335 } 00336 00337 PPT_t(const data_type& other_data) 00338 : data_type(other_data) { 00339 00340 build_internal(); 00341 } 00342 00343 ~PPT_t() { 00344 internal::fftw<value_type>::destroyfun(_fftw_fplan); 00345 internal::fftw<value_type>::destroyfun(_fftw_bplan); 00346 } 00351 void apply (const matrix_type& A, 00352 output_matrix_type& sketch_of_A, 00353 columnwise_tag dimension) const { 00354 00355 // TODO verify sizes etc. 00356 // TODO I am not sure this implementation is the most efficient 00357 // for sparse matrices. Maybe you want to do the CWT right on 00358 // start? 00359 00360 const int S = data_type::_S; 00361 const int N = data_type::_N; 00362 00363 # ifdef SKYLARK_HAVE_OPENMP 00364 # pragma omp parallel 00365 # endif 00366 { 00367 00368 output_matrix_type W(S, 1); 00369 output_matrix_type SAv; 00370 00371 std::complex<value_type> *FW = new std::complex<value_type>[S]; 00372 std::complex<value_type> *P = new std::complex<value_type>[S]; 00373 00374 # ifdef SKYLARK_HAVE_OPENMP 00375 # pragma omp for 00376 # endif 00377 for(int i = 0; i < base::Width(A); i++) { 00378 const matrix_type Av = base::ColumnView(A, i, 1); 00379 00380 for(int j = 0; j < S; j++) 00381 P[j] = 1.0; 00382 00383 typename std::list<_CWT_t>::const_iterator it; 00384 int qc = 0; 00385 for(it = _cwts.begin(); it != _cwts.end(); it++, qc++) { 00386 const _CWT_t &C = *it; 00387 C.apply(Av, W, columnwise_tag()); 00388 elem::Scal(std::sqrt(data_type::_gamma), W); 00389 W.Update(data_type::_hash_idx[qc], 0, 00390 std::sqrt(data_type::_c) * data_type::_hash_val[qc]); 00391 internal::fftw<value_type>::executeffun(_fftw_fplan, W.Buffer(), 00392 reinterpret_cast<_fftw_complex_t*>(FW)); 00393 for(int j = 0; j < S; j++) 00394 P[j] *= FW[j]; 00395 } 00396 00397 // In FFTW, both fft and ifft are not scaled. 00398 // That is norm(ifft(fft(x)) = norm(x) * #els(x). 00399 for(int j = 0; j < S; j++) 00400 P[j] /= (value_type)S; 00401 00402 elem::View(SAv, sketch_of_A, 0, i, base::Height(A), 1); 00403 internal::fftw<value_type>::executebfun(_fftw_bplan, 00404 reinterpret_cast<_fftw_complex_t*>(P), SAv.Buffer()); 00405 } 00406 00407 delete[] FW; 00408 delete[] P; 00409 00410 } 00411 } 00412 00417 void apply (const matrix_type& A, 00418 output_matrix_type& sketch_of_A, 00419 rowwise_tag dimension) const { 00420 // TODO perhaps not the best way to do this... 00421 matrix_type AT; 00422 base::Transpose(A, AT); 00423 output_matrix_type SAT(sketch_of_A.Width(), sketch_of_A.Height()); 00424 apply(AT, SAT, columnwise_tag()); 00425 elem::Transpose(SAT, sketch_of_A); 00426 } 00427 00428 int get_N() const { return data_type::_N; } 00429 int get_S() const { return data_type::_S; } 00431 const sketch_transform_data_t* get_data() const { return this; } 00432 00433 protected: 00434 00435 typedef CWT_t<matrix_type, output_matrix_type> _CWT_t; 00436 00437 typedef typename internal::fftw<value_type>::complex_t _fftw_complex_t; 00438 typedef typename internal::fftw<value_type>::plan_t _fftw_plan_t; 00439 00440 _fftw_plan_t _fftw_fplan, _fftw_bplan; 00441 std::list<_CWT_t> _cwts; 00442 00443 void build_internal() { 00444 int S = data_type::_S; 00445 00446 for(typename std::list<CWT_data_t>::iterator it = 00447 data_type::_cwts_data.begin(); 00448 it != data_type::_cwts_data.end(); it++) 00449 _cwts.push_back(_CWT_t(*it)); 00450 00451 double *dtmp = new double[S]; 00452 std::complex<double> *ctmp = new std::complex<double>[S]; 00453 _fftw_fplan = fftw_plan_dft_r2c_1d(S, dtmp, 00454 reinterpret_cast<fftw_complex*>(ctmp), 00455 FFTW_UNALIGNED | FFTW_ESTIMATE); 00456 _fftw_bplan = fftw_plan_dft_c2r_1d(S, 00457 reinterpret_cast<fftw_complex*>(ctmp), dtmp, 00458 FFTW_UNALIGNED | FFTW_ESTIMATE); 00459 delete[] dtmp; 00460 delete[] ctmp; 00461 } 00462 }; 00463 00464 } } 00466 #endif // SKYLARK_HAVE_FFTW && SKYLARK_HAVE_ELEMENTAL 00467 00468 #endif // PPT_ELEMENTAL_HPP