Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/sketch/FUT.hpp
Go to the documentation of this file.
00001 #ifndef SKYLARK_FUT_HPP
00002 #define SKYLARK_FUT_HPP
00003 
00004 #ifndef SKYLARK_SKETCH_HPP
00005 #error "Include top-level sketch.hpp instead of including individuals headers"
00006 #endif
00007 
00008 #if SKYLARK_HAVE_FFTW && SKYLARK_HAVE_ELEMENTAL
00009 
00010 #include <fftw3.h>
00011 
00012 namespace skylark { namespace sketch {
00013 
00014 template < typename ValueType,
00015            typename PlanType, typename KindType,
00016            KindType Kind, KindType KindInverse,
00017            PlanType (*PlanFun)(int, ValueType*, ValueType*, KindType, unsigned),
00018            void (*ExecuteFun)(PlanType, ValueType*, ValueType*),
00019            void (*DestroyFun)(PlanType),
00020            int ScaleVal >
00021 struct fftw_r2r_fut_t {
00022 
00023     fftw_r2r_fut_t<ValueType,
00024                    PlanType, KindType,
00025                    Kind, KindInverse,
00026                    PlanFun, ExecuteFun, DestroyFun, ScaleVal>(int N) : _N(N) {
00027         ValueType *tmp = new ValueType[N];
00028         _plan = PlanFun(N, tmp, tmp, Kind, FFTW_UNALIGNED | FFTW_ESTIMATE);
00029         _plan_inverse = PlanFun(N, tmp, tmp, KindInverse,
00030             FFTW_UNALIGNED | FFTW_ESTIMATE);
00031         delete[] tmp;
00032 
00033         // TODO: detect failure to form plans.
00034     }
00035 
00036     virtual ~fftw_r2r_fut_t<ValueType,
00037                             PlanType, KindType,
00038                             Kind, KindInverse,
00039                             PlanFun, ExecuteFun, DestroyFun, ScaleVal>() {
00040         DestroyFun(_plan);
00041         DestroyFun(_plan_inverse);
00042     }
00043 
00044 
00045     template <typename Dimension>
00046     void apply(elem::Matrix<ValueType>& A, Dimension dimension) const {
00047         return apply_impl (A, dimension);
00048     }
00049 
00050     template <typename Dimension>
00051     void apply_inverse(elem::Matrix<ValueType>& A, Dimension dimension) const {
00052         return apply_inverse_impl (A, dimension);
00053     }
00054 
00055     double scale() const {
00056         return 1 / sqrt((double)ScaleVal * _N);
00057     }
00058 
00059 private:
00060 
00061     void apply_impl(elem::Matrix<ValueType>& A,
00062                     skylark::sketch::columnwise_tag) const {
00063         double* AA = A.Buffer();
00064         int j;
00065 #ifdef SKYLARK_HAVE_OPENMP
00066 #pragma omp parallel for private(j)
00067 #endif
00068         for (j = 0; j < A.Width(); j++)
00069             ExecuteFun(_plan, AA + j * A.LDim(), AA + j * A.LDim());
00070     }
00071 
00072     void apply_inverse_impl(elem::Matrix<ValueType>& A,
00073                             skylark::sketch::columnwise_tag) const {
00074         double* AA = A.Buffer();
00075         int j;
00076 #ifdef SKYLARK_HAVE_OPENMP
00077 #pragma omp parallel for private(j)
00078 #endif
00079         for (j = 0; j < A.Width(); j++)
00080             ExecuteFun(_plan_inverse, AA + j * A.LDim(), AA + j * A.LDim());
00081     }
00082 
00083     void apply_impl(elem::Matrix<ValueType>& A,
00084                     skylark::sketch::rowwise_tag) const {
00085         // Using transpositions instead of moving to the advanced interface
00086         // of FFTW
00087         elem::Matrix<ValueType> matrix;
00088         elem::Transpose(A, matrix);
00089         double* matrix_buffer = matrix.Buffer();
00090         int j;
00091 #ifdef SKYLARK_HAVE_OPENMP
00092 #pragma omp parallel for private(j)
00093 #endif
00094         for (j = 0; j < matrix.Width(); j++)
00095             ExecuteFun(_plan, matrix_buffer + j * matrix.LDim(),
00096                 matrix_buffer + j * matrix.LDim());
00097         elem::Transpose(matrix, A);
00098     }
00099 
00100     void apply_inverse_impl(elem::Matrix<ValueType>& A,
00101                             skylark::sketch::rowwise_tag) const {
00102         // Using transpositions instead of moving to the advanced interface
00103         // of FFTW
00104         elem::Matrix<ValueType> matrix;
00105         elem::Transpose(A, matrix);
00106         double* matrix_buffer = matrix.Buffer();
00107         int j;
00108 #ifdef SKYLARK_HAVE_OPENMP
00109 #pragma omp parallel for private(j)
00110 #endif
00111         for (j = 0; j < matrix.Width(); j++)
00112             ExecuteFun(_plan_inverse, matrix_buffer + j * matrix.LDim(),
00113                 matrix_buffer + j * matrix.LDim());
00114         elem::Transpose(matrix, A);
00115     }
00116 
00117 private:
00118     const int _N;
00119     PlanType _plan, _plan_inverse;
00120 
00121 
00122 };
00123 
00124 template<typename ValueType>
00125 struct fft_futs {
00126 
00127 };
00128 
00129 template<>
00130 struct fft_futs<double> {
00131     typedef fftw_r2r_fut_t <
00132             double, fftw_plan, fftw_r2r_kind, FFTW_REDFT10, FFTW_REDFT01,
00133             fftw_plan_r2r_1d, fftw_execute_r2r, fftw_destroy_plan, 2 > DCT_t;
00134 
00135     typedef fftw_r2r_fut_t <
00136             double, fftw_plan, fftw_r2r_kind, FFTW_DHT, FFTW_DHT,
00137             fftw_plan_r2r_1d, fftw_execute_r2r, fftw_destroy_plan, 1 > DHT_t;
00138 };
00139 
00140 template<>
00141 struct fft_futs<float> {
00142     typedef fftw_r2r_fut_t <
00143             float, fftwf_plan, fftwf_r2r_kind, FFTW_REDFT10, FFTW_REDFT01,
00144             fftwf_plan_r2r_1d, fftwf_execute_r2r, fftwf_destroy_plan, 2 > DCT_t;
00145 
00146     typedef fftw_r2r_fut_t <
00147             float, fftwf_plan, fftwf_r2r_kind, FFTW_DHT, FFTW_DHT,
00148             fftwf_plan_r2r_1d, fftwf_execute_r2r, fftwf_destroy_plan, 1 > DHT_t;
00149 };
00150 
00151 
00152 } } 
00154 #endif // SKYLARK_HAVE_FFTW && SKYLARK_HAVE_ELEMENTAL
00155 
00156 #if SKYLARK_HAVE_SPIRALWHT && SKYLARK_HAVE_ELEMENTAL
00157 
00158 
00159 extern "C" {
00160 #include <spiral_wht.h>
00161 }
00162 
00163 namespace skylark { namespace sketch {
00164 
00165 template<typename ValueType>
00166 struct WHT_t {
00167 
00168 };
00169 
00170 template<>
00171 struct WHT_t<double> {
00172 
00173     typedef double value_type;
00174 
00175     WHT_t<double>(int N) : _N(N) {
00176         // TODO check that N is a power of two.
00177         _tree = wht_get_tree(ceil(log(N) / log(2)));
00178     }
00179 
00180     ~WHT_t<double>() {
00181         delete _tree;
00182     }
00183 
00184     template <typename Dimension>
00185     void apply(elem::Matrix<value_type>& A, Dimension dimension) const {
00186         return apply_impl (A, dimension);
00187     }
00188 
00189     template <typename Dimension>
00190     void apply_inverse(elem::Matrix<value_type>& A, Dimension dimension) const {
00191         return apply_inverse_impl (A, dimension);
00192     }
00193 
00194     double scale() const {
00195         return 1 / sqrt(_N);
00196     }
00197 
00198 private:
00199 
00200     void apply_impl(elem::Matrix<value_type>& A,
00201                     skylark::sketch::columnwise_tag) const {
00202         double* AA = A.Buffer();
00203         int j;
00204 #ifdef SKYLARK_HAVE_OPENMP
00205 #pragma omp parallel for private(j)
00206 #endif
00207         for (j = 0; j < A.Width(); j++)
00208             wht_apply(_tree, 1, AA + j * A.LDim());
00209     }
00210 
00211     void apply_inverse_impl(elem::Matrix<value_type>& A,
00212         skylark::sketch::columnwise_tag) const {
00213         double* AA = A.Buffer();
00214         int j;
00215 #ifdef SKYLARK_HAVE_OPENMP
00216 #pragma omp parallel for private(j)
00217 #endif
00218         for (j = 0; j < A.Width(); j++)
00219             wht_apply(_tree, 1, AA + j * A.LDim());
00220     }
00221 
00222     void apply_impl(elem::Matrix<value_type>& A,
00223         skylark::sketch::rowwise_tag) const {
00224         double* AA = A.Buffer();
00225         int j;
00226 #ifdef SKYLARK_HAVE_OPENMP
00227 #pragma omp parallel for private(j)
00228 #endif
00229         for (j = 0; j < A.Width(); j++)
00230             wht_apply(_tree, A.Height(), AA + j);
00231         // Not sure stride is used correctly here.
00232     }
00233 
00234     void apply_inverse_impl(elem::Matrix<value_type>& A,
00235         skylark::sketch::rowwise_tag) const {
00236         double* AA = A.Buffer();
00237         int j;
00238 #ifdef SKYLARK_HAVE_OPENMP
00239 #pragma omp parallel for private(j)
00240 #endif
00241         for (j = 0; j < A.Width(); j++)
00242             wht_apply(_tree, A.Height(), AA + j);
00243         // Not sure stride is used correctly here.
00244     }
00245 
00246 
00247     const int _N;
00248     Wht *_tree;
00249 };
00250 
00251 } } 
00253 #endif // SKYLARK_HAVE_SPIRALWHT && SKYLARK_HAVE_ELEMENTAL
00254 
00255 #endif // SKYLARK_FUT_HPP