Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/sketch/PPT_Elemental.hpp
Go to the documentation of this file.
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