00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__FFT_FIXED__HPP
00014 #define __MMX__FFT_FIXED__HPP
00015 #include <algebramix/fft_naive.hpp>
00016
00017 namespace mmx {
00018
00019
00020
00021
00022
00023 template<typename D, typename R, nat steps, nat todo> struct fft_large_helper;
00024 template<typename D, typename R, nat steps, nat todo> struct fft_small_helper;
00025
00026 template<typename D, typename R, nat steps>
00027 struct fft_helper {
00028 static const nat half1= steps >> 1;
00029 static const nat half2= steps - half1;
00030 static const nat n1 = 1 << half1;
00031 static const nat n2 = 1 << half2;
00032 typedef typename R::C C;
00033 typedef typename R::U U;
00034
00035 static inline void
00036 tf (C* c, nat stride, U* u, nat shift) {
00037 fft_large_helper<D,R,half1,n2>::tf (c, stride<<half2, u, shift>>half2);
00038 fft_small_helper<D,R,half2,n1>::tf (c, stride, u, shift);
00039 }
00040 };
00041
00042 template<typename R, nat steps>
00043 struct fft_helper<fft_inverse,R,steps> {
00044 static const nat half1= steps >> 1;
00045 static const nat half2= steps - half1;
00046 static const nat n1 = 1 << half1;
00047 static const nat n2 = 1 << half2;
00048 typedef fft_inverse D;
00049 typedef typename R::C C;
00050 typedef typename R::U U;
00051
00052 static inline void
00053 tf (C* c, nat stride, U* u, nat shift) {
00054 fft_small_helper<D,R,half2,n1>::tf (c, stride, u, shift);
00055 fft_large_helper<D,R,half1,n2>::tf (c, stride<<half2, u, shift>>half2);
00056 }
00057 };
00058
00059 template<typename D, typename R>
00060 struct fft_helper<D,R,1> {
00061 typedef typename R::C C;
00062 typedef typename R::U U;
00063
00064 static inline void
00065 tf (C* c, nat stride, U* u, nat shift) {
00066 cross<R,D> (c, c + stride, u + shift);
00067 }
00068 };
00069
00070
00071
00072
00073
00074 template<typename D, typename R, nat steps, nat todo>
00075 struct fft_large_helper {
00076 typedef typename R::C C;
00077 typedef typename R::U U;
00078
00079 static inline void
00080 tf (C* c, nat stride, U* u, nat shift) {
00081 fft_helper<D,R,steps>::tf (c, stride, u, shift);
00082 fft_large_helper<D,R,steps,todo-1>::tf (c, stride, u, shift);
00083 }
00084 };
00085
00086 template<typename D, typename R, nat steps>
00087 struct fft_large_helper<D,R,steps,1> {
00088 typedef typename R::C C;
00089 typedef typename R::U U;
00090
00091 static inline void
00092 tf (C* c, nat stride, U* u, nat shift) {
00093 fft_helper<D,R,steps>::tf (c, stride, u, shift);
00094 }
00095 };
00096
00097
00098
00099
00100
00101 template<typename D, typename R, nat steps, nat todo>
00102 struct fft_small_helper {
00103 typedef typename R::C C;
00104 typedef typename R::U U;
00105
00106 static inline void
00107 tf (C* c, nat stride, U* u, nat shift) {
00108 fft_helper<D,R,steps>::tf (c, stride, u, shift);
00109 fft_small_helper<D,R,steps,todo-1>::tf (c, stride, u, shift + (1<<steps));
00110 }
00111 };
00112
00113 template<typename D, typename R, nat steps>
00114 struct fft_small_helper<D,R,steps,1> {
00115 typedef typename R::C C;
00116 typedef typename R::U U;
00117
00118 static inline void
00119 tf (C* c, nat stride, U* u, nat shift) {
00120 fft_helper<D,R,steps>::tf (c, stride, u, shift);
00121 }
00122 };
00123
00124
00125
00126
00127
00128 template<typename R, nat steps>
00129 struct fft_fixed_helper {
00130 typedef typename R::C C;
00131 typedef typename R::U U;
00132
00133 template<typename D> static inline void
00134 transform (nat s, C* c, nat stride, U* u, nat shift) {
00135 if (s < steps) fft_fixed_helper<R,steps>::
00136 template transform<D> (s, c, stride, u, shift);
00137 else fft_helper<D,R,steps>::tf (c, stride, u, shift);
00138 }
00139 };
00140
00141 template<typename R>
00142 struct fft_fixed_helper<R,1> {
00143 typedef typename R::C C;
00144 typedef typename R::U U;
00145
00146 template<typename D> static inline void
00147 transform (nat s, C* c, nat stride, U* u, nat shift) {
00148 (void) s;
00149 cross<R,D> (c, c + stride, u + shift);
00150 }
00151 };
00152
00153 template<typename R>
00154 struct fft_fixed_helper<R,2> {
00155 typedef typename R::C C;
00156 typedef typename R::U U;
00157
00158 template<typename D> static inline void
00159 transform (nat s, C* c, nat stride, U* u, nat shift) {
00160 switch (s) {
00161 case 1: cross<R,D> (c, c + stride, u + shift); break;
00162 case 2: fft_helper<D,R,2>::tf (c, stride, u, shift); break;
00163 }
00164 }
00165 };
00166
00167 template<typename R>
00168 struct fft_fixed_helper<R,3> {
00169 typedef typename R::C C;
00170 typedef typename R::U U;
00171
00172 template<typename D> static inline void
00173 transform (nat s, C* c, nat stride, U* u, nat shift) {
00174 switch (s) {
00175 case 1: cross<R,D> (c, c + stride, u + shift); break;
00176 case 2: fft_helper<D,R,2>::tf (c, stride, u, shift); break;
00177 case 3: fft_helper<D,R,3>::tf (c, stride, u, shift); break;
00178 }
00179 }
00180 };
00181
00182 template<typename R>
00183 struct fft_fixed_helper<R,4> {
00184 typedef typename R::C C;
00185 typedef typename R::U U;
00186
00187 template<typename D> static inline void
00188 transform (nat s, C* c, nat stride, U* u, nat shift) {
00189 switch (s) {
00190 case 1: cross<R,D> (c, c + stride, u + shift); break;
00191 case 2: fft_helper<D,R,2>::tf (c, stride, u, shift); break;
00192 case 3: fft_helper<D,R,3>::tf (c, stride, u, shift); break;
00193 case 4: fft_helper<D,R,4>::tf (c, stride, u, shift); break;
00194 }
00195 }
00196 };
00197
00198 template<typename R>
00199 struct fft_fixed_helper<R,5> {
00200 typedef typename R::C C;
00201 typedef typename R::U U;
00202
00203 template<typename D> static inline void
00204 transform (nat s, C* c, nat stride, U* u, nat shift) {
00205 switch (s) {
00206 case 1: cross<R,D> (c, c + stride, u + shift); break;
00207 case 2: fft_helper<D,R,2>::tf (c, stride, u, shift); break;
00208 case 3: fft_helper<D,R,3>::tf (c, stride, u, shift); break;
00209 case 4: fft_helper<D,R,4>::tf (c, stride, u, shift); break;
00210 case 5: fft_helper<D,R,5>::tf (c, stride, u, shift); break;
00211 }
00212 }
00213 };
00214
00215 template<typename R>
00216 struct fft_fixed_helper<R,6> {
00217 typedef typename R::C C;
00218 typedef typename R::U U;
00219
00220 template<typename D> static inline void
00221 transform (nat s, C* c, nat stride, U* u, nat shift) {
00222 switch (s) {
00223 case 1: cross<R,D> (c, c + stride, u + shift); break;
00224 case 2: fft_helper<D,R,2>::tf (c, stride, u, shift); break;
00225 case 3: fft_helper<D,R,3>::tf (c, stride, u, shift); break;
00226 case 4: fft_helper<D,R,4>::tf (c, stride, u, shift); break;
00227 case 5: fft_helper<D,R,5>::tf (c, stride, u, shift); break;
00228 case 6: fft_helper<D,R,6>::tf (c, stride, u, shift); break;
00229 }
00230 }
00231 };
00232
00233 }
00234 #endif //__MMX__FFT_FIXED__HPP