Skylark (Sketching Library)
0.1
|
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