FFTRealFixLen.hpp 5.7 KB

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