FFTRealFixLen.hpp (6158B)
1 /***************************************************************************** 2 3 FFTRealFixLen.hpp 4 By Laurent de Soras 5 6 --- Legal stuff --- 7 8 This program is free software. It comes without any warranty, to 9 the extent permitted by applicable law. You can redistribute it 10 and/or modify it under the terms of the Do What The Fuck You Want 11 To Public License, Version 2, as published by Sam Hocevar. See 12 http://sam.zoy.org/wtfpl/COPYING for more details. 13 14 *Tab=3***********************************************************************/ 15 16 17 18 #if defined (ffft_FFTRealFixLen_CURRENT_CODEHEADER) 19 #error Recursive inclusion of FFTRealFixLen code header. 20 #endif 21 #define ffft_FFTRealFixLen_CURRENT_CODEHEADER 22 23 #if ! defined (ffft_FFTRealFixLen_CODEHEADER_INCLUDED) 24 #define ffft_FFTRealFixLen_CODEHEADER_INCLUDED 25 26 27 28 /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 30 #include "ffft/def.h" 31 #include "ffft/FFTRealPassDirect.h" 32 #include "ffft/FFTRealPassInverse.h" 33 #include "ffft/FFTRealSelect.h" 34 35 #include <cassert> 36 #include <cmath> 37 38 namespace std { } 39 40 41 42 namespace ffft 43 { 44 45 46 47 /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 48 49 50 51 template <int LL2> 52 FFTRealFixLen <LL2>::FFTRealFixLen () 53 : _buffer (FFT_LEN) 54 , _br_data (BR_ARR_SIZE) 55 , _trigo_data (TRIGO_TABLE_ARR_SIZE) 56 , _trigo_osc () 57 { 58 build_br_lut (); 59 build_trigo_lut (); 60 build_trigo_osc (); 61 } 62 63 64 65 template <int LL2> 66 long FFTRealFixLen <LL2>::get_length () const 67 { 68 return (FFT_LEN); 69 } 70 71 72 73 // General case 74 template <int LL2> 75 void FFTRealFixLen <LL2>::do_fft (DataType f [], const DataType x []) 76 { 77 assert (f != 0); 78 assert (x != 0); 79 assert (x != f); 80 assert (FFT_LEN_L2 >= 3); 81 82 // Do the transform in several passes 83 const DataType * cos_ptr = &_trigo_data [0]; 84 const long * br_ptr = &_br_data [0]; 85 86 FFTRealPassDirect <FFT_LEN_L2 - 1>::process ( 87 FFT_LEN, 88 f, 89 &_buffer [0], 90 x, 91 cos_ptr, 92 TRIGO_TABLE_ARR_SIZE, 93 br_ptr, 94 &_trigo_osc [0] 95 ); 96 } 97 98 // 4-point FFT 99 template <> 100 inline void FFTRealFixLen <2>::do_fft (DataType f [], const DataType x []) 101 { 102 assert (f != 0); 103 assert (x != 0); 104 assert (x != f); 105 106 f [1] = x [0] - x [2]; 107 f [3] = x [1] - x [3]; 108 109 const DataType b_0 = x [0] + x [2]; 110 const DataType b_2 = x [1] + x [3]; 111 112 f [0] = b_0 + b_2; 113 f [2] = b_0 - b_2; 114 } 115 116 // 2-point FFT 117 template <> 118 inline void FFTRealFixLen <1>::do_fft (DataType f [], const DataType x []) 119 { 120 assert (f != 0); 121 assert (x != 0); 122 assert (x != f); 123 124 f [0] = x [0] + x [1]; 125 f [1] = x [0] - x [1]; 126 } 127 128 // 1-point FFT 129 template <> 130 inline void FFTRealFixLen <0>::do_fft (DataType f [], const DataType x []) 131 { 132 assert (f != 0); 133 assert (x != 0); 134 135 f [0] = x [0]; 136 } 137 138 139 140 // General case 141 template <int LL2> 142 void FFTRealFixLen <LL2>::do_ifft (const DataType f [], DataType x []) 143 { 144 assert (f != 0); 145 assert (x != 0); 146 assert (x != f); 147 assert (FFT_LEN_L2 >= 3); 148 149 // Do the transform in several passes 150 DataType * s_ptr = 151 FFTRealSelect <FFT_LEN_L2 & 1>::sel_bin (&_buffer [0], x); 152 DataType * d_ptr = 153 FFTRealSelect <FFT_LEN_L2 & 1>::sel_bin (x, &_buffer [0]); 154 const DataType * cos_ptr = &_trigo_data [0]; 155 const long * br_ptr = &_br_data [0]; 156 157 FFTRealPassInverse <FFT_LEN_L2 - 1>::process ( 158 FFT_LEN, 159 d_ptr, 160 s_ptr, 161 f, 162 cos_ptr, 163 TRIGO_TABLE_ARR_SIZE, 164 br_ptr, 165 &_trigo_osc [0] 166 ); 167 } 168 169 // 4-point IFFT 170 template <> 171 inline void FFTRealFixLen <2>::do_ifft (const DataType f [], DataType x []) 172 { 173 assert (f != 0); 174 assert (x != 0); 175 assert (x != f); 176 177 const DataType b_0 = f [0] + f [2]; 178 const DataType b_2 = f [0] - f [2]; 179 180 x [0] = b_0 + f [1] * 2; 181 x [2] = b_0 - f [1] * 2; 182 x [1] = b_2 + f [3] * 2; 183 x [3] = b_2 - f [3] * 2; 184 } 185 186 // 2-point IFFT 187 template <> 188 inline void FFTRealFixLen <1>::do_ifft (const DataType f [], DataType x []) 189 { 190 assert (f != 0); 191 assert (x != 0); 192 assert (x != f); 193 194 x [0] = f [0] + f [1]; 195 x [1] = f [0] - f [1]; 196 } 197 198 // 1-point IFFT 199 template <> 200 inline void FFTRealFixLen <0>::do_ifft (const DataType f [], DataType x []) 201 { 202 assert (f != 0); 203 assert (x != 0); 204 assert (x != f); 205 206 x [0] = f [0]; 207 } 208 209 210 211 212 template <int LL2> 213 void FFTRealFixLen <LL2>::rescale (DataType x []) const 214 { 215 assert (x != 0); 216 217 const DataType mul = DataType (1.0 / FFT_LEN); 218 219 if (FFT_LEN < 4) 220 { 221 long i = FFT_LEN - 1; 222 do 223 { 224 x [i] *= mul; 225 --i; 226 } 227 while (i >= 0); 228 } 229 230 else 231 { 232 assert ((FFT_LEN & 3) == 0); 233 234 // Could be optimized with SIMD instruction sets (needs alignment check) 235 long i = FFT_LEN - 4; 236 do 237 { 238 x [i + 0] *= mul; 239 x [i + 1] *= mul; 240 x [i + 2] *= mul; 241 x [i + 3] *= mul; 242 i -= 4; 243 } 244 while (i >= 0); 245 } 246 } 247 248 249 250 /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 251 252 253 254 /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 255 256 257 258 template <int LL2> 259 void FFTRealFixLen <LL2>::build_br_lut () 260 { 261 _br_data [0] = 0; 262 for (long cnt = 1; cnt < BR_ARR_SIZE; ++cnt) 263 { 264 long index = cnt << 2; 265 long br_index = 0; 266 267 int bit_cnt = FFT_LEN_L2; 268 do 269 { 270 br_index <<= 1; 271 br_index += (index & 1); 272 index >>= 1; 273 274 -- bit_cnt; 275 } 276 while (bit_cnt > 0); 277 278 _br_data [cnt] = br_index; 279 } 280 } 281 282 283 284 template <int LL2> 285 void FFTRealFixLen <LL2>::build_trigo_lut () 286 { 287 const double mul = (0.5 * PI) / TRIGO_TABLE_ARR_SIZE; 288 for (long i = 0; i < TRIGO_TABLE_ARR_SIZE; ++ i) 289 { 290 using namespace std; 291 292 _trigo_data [i] = DataType (cos (i * mul)); 293 } 294 } 295 296 297 298 template <int LL2> 299 void FFTRealFixLen <LL2>::build_trigo_osc () 300 { 301 for (int i = 0; i < NBR_TRIGO_OSC; ++i) 302 { 303 OscType & osc = _trigo_osc [i]; 304 305 const long len = static_cast <long> (TRIGO_TABLE_ARR_SIZE) << (i + 1); 306 const double mul = (0.5 * PI) / len; 307 osc.set_step (mul); 308 } 309 } 310 311 312 313 } // namespace ffft 314 315 316 317 #endif // ffft_FFTRealFixLen_CODEHEADER_INCLUDED 318 319 #undef ffft_FFTRealFixLen_CURRENT_CODEHEADER 320 321 322 323 /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/