FFTReal.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. /*****************************************************************************
  2. FFTReal.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_FFTReal_CURRENT_CODEHEADER)
  12. #error Recursive inclusion of FFTReal code header.
  13. #endif
  14. #define ffft_FFTReal_CURRENT_CODEHEADER
  15. #if ! defined (ffft_FFTReal_CODEHEADER_INCLUDED)
  16. #define ffft_FFTReal_CODEHEADER_INCLUDED
  17. /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  18. #include <cassert>
  19. #include <cmath>
  20. namespace ffft
  21. {
  22. static inline bool FFTReal_is_pow2 (long x)
  23. {
  24. assert (x > 0);
  25. return ((x & -x) == x);
  26. }
  27. static inline int FFTReal_get_next_pow2 (long x)
  28. {
  29. --x;
  30. int p = 0;
  31. while ((x & ~0xFFFFL) != 0)
  32. {
  33. p += 16;
  34. x >>= 16;
  35. }
  36. while ((x & ~0xFL) != 0)
  37. {
  38. p += 4;
  39. x >>= 4;
  40. }
  41. while (x > 0)
  42. {
  43. ++p;
  44. x >>= 1;
  45. }
  46. return (p);
  47. }
  48. /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  49. /*
  50. ==============================================================================
  51. Name: ctor
  52. Input parameters:
  53. - length: length of the array on which we want to do a FFT. Range: power of
  54. 2 only, > 0.
  55. Throws: std::bad_alloc
  56. ==============================================================================
  57. */
  58. template <class DT>
  59. FFTReal <DT>::FFTReal (long length)
  60. : _length (length)
  61. , _nbr_bits (FFTReal_get_next_pow2 (length))
  62. , _br_lut ()
  63. , _trigo_lut ()
  64. , _buffer (length)
  65. , _trigo_osc ()
  66. {
  67. assert (FFTReal_is_pow2 (length));
  68. assert (_nbr_bits <= MAX_BIT_DEPTH);
  69. init_br_lut ();
  70. init_trigo_lut ();
  71. init_trigo_osc ();
  72. }
  73. /*
  74. ==============================================================================
  75. Name: get_length
  76. Description:
  77. Returns the number of points processed by this FFT object.
  78. Returns: The number of points, power of 2, > 0.
  79. Throws: Nothing
  80. ==============================================================================
  81. */
  82. template <class DT>
  83. long FFTReal <DT>::get_length () const
  84. {
  85. return (_length);
  86. }
  87. /*
  88. ==============================================================================
  89. Name: do_fft
  90. Description:
  91. Compute the FFT of the array.
  92. Input parameters:
  93. - x: pointer on the source array (time).
  94. Output parameters:
  95. - f: pointer on the destination array (frequencies).
  96. f [0...length(x)/2] = real values,
  97. f [length(x)/2+1...length(x)-1] = negative imaginary values of
  98. coefficents 1...length(x)/2-1.
  99. Throws: Nothing
  100. ==============================================================================
  101. */
  102. template <class DT>
  103. void FFTReal <DT>::do_fft (DataType f [], const DataType x []) const
  104. {
  105. assert (f != 0);
  106. assert (f != use_buffer ());
  107. assert (x != 0);
  108. assert (x != use_buffer ());
  109. assert (x != f);
  110. // General case
  111. if (_nbr_bits > 2)
  112. {
  113. compute_fft_general (f, x);
  114. }
  115. // 4-point FFT
  116. else if (_nbr_bits == 2)
  117. {
  118. f [1] = x [0] - x [2];
  119. f [3] = x [1] - x [3];
  120. const DataType b_0 = x [0] + x [2];
  121. const DataType b_2 = x [1] + x [3];
  122. f [0] = b_0 + b_2;
  123. f [2] = b_0 - b_2;
  124. }
  125. // 2-point FFT
  126. else if (_nbr_bits == 1)
  127. {
  128. f [0] = x [0] + x [1];
  129. f [1] = x [0] - x [1];
  130. }
  131. // 1-point FFT
  132. else
  133. {
  134. f [0] = x [0];
  135. }
  136. }
  137. /*
  138. ==============================================================================
  139. Name: do_ifft
  140. Description:
  141. Compute the inverse FFT of the array. Note that data must be post-scaled:
  142. IFFT (FFT (x)) = x * length (x).
  143. Input parameters:
  144. - f: pointer on the source array (frequencies).
  145. f [0...length(x)/2] = real values
  146. f [length(x)/2+1...length(x)-1] = negative imaginary values of
  147. coefficents 1...length(x)/2-1.
  148. Output parameters:
  149. - x: pointer on the destination array (time).
  150. Throws: Nothing
  151. ==============================================================================
  152. */
  153. template <class DT>
  154. void FFTReal <DT>::do_ifft (const DataType f [], DataType x []) const
  155. {
  156. assert (f != 0);
  157. assert (f != use_buffer ());
  158. assert (x != 0);
  159. assert (x != use_buffer ());
  160. assert (x != f);
  161. // General case
  162. if (_nbr_bits > 2)
  163. {
  164. compute_ifft_general (f, x);
  165. }
  166. // 4-point IFFT
  167. else if (_nbr_bits == 2)
  168. {
  169. const DataType b_0 = f [0] + f [2];
  170. const DataType b_2 = f [0] - f [2];
  171. x [0] = b_0 + f [1] * 2;
  172. x [2] = b_0 - f [1] * 2;
  173. x [1] = b_2 + f [3] * 2;
  174. x [3] = b_2 - f [3] * 2;
  175. }
  176. // 2-point IFFT
  177. else if (_nbr_bits == 1)
  178. {
  179. x [0] = f [0] + f [1];
  180. x [1] = f [0] - f [1];
  181. }
  182. // 1-point IFFT
  183. else
  184. {
  185. x [0] = f [0];
  186. }
  187. }
  188. /*
  189. ==============================================================================
  190. Name: rescale
  191. Description:
  192. Scale an array by divide each element by its length. This function should
  193. be called after FFT + IFFT.
  194. Input parameters:
  195. - x: pointer on array to rescale (time or frequency).
  196. Throws: Nothing
  197. ==============================================================================
  198. */
  199. template <class DT>
  200. void FFTReal <DT>::rescale (DataType x []) const
  201. {
  202. const DataType mul = DataType (1.0 / _length);
  203. if (_length < 4)
  204. {
  205. long i = _length - 1;
  206. do
  207. {
  208. x [i] *= mul;
  209. --i;
  210. }
  211. while (i >= 0);
  212. }
  213. else
  214. {
  215. assert ((_length & 3) == 0);
  216. // Could be optimized with SIMD instruction sets (needs alignment check)
  217. long i = _length - 4;
  218. do
  219. {
  220. x [i + 0] *= mul;
  221. x [i + 1] *= mul;
  222. x [i + 2] *= mul;
  223. x [i + 3] *= mul;
  224. i -= 4;
  225. }
  226. while (i >= 0);
  227. }
  228. }
  229. /*
  230. ==============================================================================
  231. Name: use_buffer
  232. Description:
  233. Access the internal buffer, whose length is the FFT one.
  234. Buffer content will be erased at each do_fft() / do_ifft() call!
  235. This buffer cannot be used as:
  236. - source for FFT or IFFT done with this object
  237. - destination for FFT or IFFT done with this object
  238. Returns:
  239. Buffer start address
  240. Throws: Nothing
  241. ==============================================================================
  242. */
  243. template <class DT>
  244. typename FFTReal <DT>::DataType * FFTReal <DT>::use_buffer () const
  245. {
  246. return (&_buffer [0]);
  247. }
  248. /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  249. /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  250. template <class DT>
  251. void FFTReal <DT>::init_br_lut ()
  252. {
  253. const long length = 1L << _nbr_bits;
  254. _br_lut.resize (length);
  255. _br_lut [0] = 0;
  256. long br_index = 0;
  257. for (long cnt = 1; cnt < length; ++cnt)
  258. {
  259. // ++br_index (bit reversed)
  260. long bit = length >> 1;
  261. while (((br_index ^= bit) & bit) == 0)
  262. {
  263. bit >>= 1;
  264. }
  265. _br_lut [cnt] = br_index;
  266. }
  267. }
  268. template <class DT>
  269. void FFTReal <DT>::init_trigo_lut ()
  270. {
  271. using namespace std;
  272. if (_nbr_bits > 3)
  273. {
  274. const long total_len = (1L << (_nbr_bits - 1)) - 4;
  275. _trigo_lut.resize (total_len);
  276. for (int level = 3; level < _nbr_bits; ++level)
  277. {
  278. const long level_len = 1L << (level - 1);
  279. DataType * const level_ptr =
  280. &_trigo_lut [get_trigo_level_index (level)];
  281. const double mul = PI / (level_len << 1);
  282. for (long i = 0; i < level_len; ++ i)
  283. {
  284. level_ptr [i] = static_cast <DataType> (cos (i * mul));
  285. }
  286. }
  287. }
  288. }
  289. template <class DT>
  290. void FFTReal <DT>::init_trigo_osc ()
  291. {
  292. const int nbr_osc = _nbr_bits - TRIGO_BD_LIMIT;
  293. if (nbr_osc > 0)
  294. {
  295. _trigo_osc.resize (nbr_osc);
  296. for (int osc_cnt = 0; osc_cnt < nbr_osc; ++osc_cnt)
  297. {
  298. OscType & osc = _trigo_osc [osc_cnt];
  299. const long len = 1L << (TRIGO_BD_LIMIT + osc_cnt);
  300. const double mul = (0.5 * PI) / len;
  301. osc.set_step (mul);
  302. }
  303. }
  304. }
  305. template <class DT>
  306. const long * FFTReal <DT>::get_br_ptr () const
  307. {
  308. return (&_br_lut [0]);
  309. }
  310. template <class DT>
  311. const typename FFTReal <DT>::DataType * FFTReal <DT>::get_trigo_ptr (int level) const
  312. {
  313. assert (level >= 3);
  314. return (&_trigo_lut [get_trigo_level_index (level)]);
  315. }
  316. template <class DT>
  317. long FFTReal <DT>::get_trigo_level_index (int level) const
  318. {
  319. assert (level >= 3);
  320. return ((1L << (level - 1)) - 4);
  321. }
  322. // Transform in several passes
  323. template <class DT>
  324. void FFTReal <DT>::compute_fft_general (DataType f [], const DataType x []) const
  325. {
  326. assert (f != 0);
  327. assert (f != use_buffer ());
  328. assert (x != 0);
  329. assert (x != use_buffer ());
  330. assert (x != f);
  331. DataType * sf;
  332. DataType * df;
  333. if ((_nbr_bits & 1) != 0)
  334. {
  335. df = use_buffer ();
  336. sf = f;
  337. }
  338. else
  339. {
  340. df = f;
  341. sf = use_buffer ();
  342. }
  343. compute_direct_pass_1_2 (df, x);
  344. compute_direct_pass_3 (sf, df);
  345. for (int pass = 3; pass < _nbr_bits; ++ pass)
  346. {
  347. compute_direct_pass_n (df, sf, pass);
  348. DataType * const temp_ptr = df;
  349. df = sf;
  350. sf = temp_ptr;
  351. }
  352. }
  353. template <class DT>
  354. void FFTReal <DT>::compute_direct_pass_1_2 (DataType df [], const DataType x []) const
  355. {
  356. assert (df != 0);
  357. assert (x != 0);
  358. assert (df != x);
  359. const long * const bit_rev_lut_ptr = get_br_ptr ();
  360. long coef_index = 0;
  361. do
  362. {
  363. const long rev_index_0 = bit_rev_lut_ptr [coef_index];
  364. const long rev_index_1 = bit_rev_lut_ptr [coef_index + 1];
  365. const long rev_index_2 = bit_rev_lut_ptr [coef_index + 2];
  366. const long rev_index_3 = bit_rev_lut_ptr [coef_index + 3];
  367. DataType * const df2 = df + coef_index;
  368. df2 [1] = x [rev_index_0] - x [rev_index_1];
  369. df2 [3] = x [rev_index_2] - x [rev_index_3];
  370. const DataType sf_0 = x [rev_index_0] + x [rev_index_1];
  371. const DataType sf_2 = x [rev_index_2] + x [rev_index_3];
  372. df2 [0] = sf_0 + sf_2;
  373. df2 [2] = sf_0 - sf_2;
  374. coef_index += 4;
  375. }
  376. while (coef_index < _length);
  377. }
  378. template <class DT>
  379. void FFTReal <DT>::compute_direct_pass_3 (DataType df [], const DataType sf []) const
  380. {
  381. assert (df != 0);
  382. assert (sf != 0);
  383. assert (df != sf);
  384. const DataType sqrt2_2 = DataType (SQRT2 * 0.5);
  385. long coef_index = 0;
  386. do
  387. {
  388. DataType v;
  389. df [coef_index] = sf [coef_index] + sf [coef_index + 4];
  390. df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4];
  391. df [coef_index + 2] = sf [coef_index + 2];
  392. df [coef_index + 6] = sf [coef_index + 6];
  393. v = (sf [coef_index + 5] - sf [coef_index + 7]) * sqrt2_2;
  394. df [coef_index + 1] = sf [coef_index + 1] + v;
  395. df [coef_index + 3] = sf [coef_index + 1] - v;
  396. v = (sf [coef_index + 5] + sf [coef_index + 7]) * sqrt2_2;
  397. df [coef_index + 5] = v + sf [coef_index + 3];
  398. df [coef_index + 7] = v - sf [coef_index + 3];
  399. coef_index += 8;
  400. }
  401. while (coef_index < _length);
  402. }
  403. template <class DT>
  404. void FFTReal <DT>::compute_direct_pass_n (DataType df [], const DataType sf [], int pass) const
  405. {
  406. assert (df != 0);
  407. assert (sf != 0);
  408. assert (df != sf);
  409. assert (pass >= 3);
  410. assert (pass < _nbr_bits);
  411. if (pass <= TRIGO_BD_LIMIT)
  412. {
  413. compute_direct_pass_n_lut (df, sf, pass);
  414. }
  415. else
  416. {
  417. compute_direct_pass_n_osc (df, sf, pass);
  418. }
  419. }
  420. template <class DT>
  421. void FFTReal <DT>::compute_direct_pass_n_lut (DataType df [], const DataType sf [], int pass) const
  422. {
  423. assert (df != 0);
  424. assert (sf != 0);
  425. assert (df != sf);
  426. assert (pass >= 3);
  427. assert (pass < _nbr_bits);
  428. const long nbr_coef = 1 << pass;
  429. const long h_nbr_coef = nbr_coef >> 1;
  430. const long d_nbr_coef = nbr_coef << 1;
  431. long coef_index = 0;
  432. const DataType * const cos_ptr = get_trigo_ptr (pass);
  433. do
  434. {
  435. const DataType * const sf1r = sf + coef_index;
  436. const DataType * const sf2r = sf1r + nbr_coef;
  437. DataType * const dfr = df + coef_index;
  438. DataType * const dfi = dfr + nbr_coef;
  439. // Extreme coefficients are always real
  440. dfr [0] = sf1r [0] + sf2r [0];
  441. dfi [0] = sf1r [0] - sf2r [0]; // dfr [nbr_coef] =
  442. dfr [h_nbr_coef] = sf1r [h_nbr_coef];
  443. dfi [h_nbr_coef] = sf2r [h_nbr_coef];
  444. // Others are conjugate complex numbers
  445. const DataType * const sf1i = sf1r + h_nbr_coef;
  446. const DataType * const sf2i = sf1i + nbr_coef;
  447. for (long i = 1; i < h_nbr_coef; ++ i)
  448. {
  449. const DataType c = cos_ptr [i]; // cos (i*PI/nbr_coef);
  450. const DataType s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef);
  451. DataType v;
  452. v = sf2r [i] * c - sf2i [i] * s;
  453. dfr [i] = sf1r [i] + v;
  454. dfi [-i] = sf1r [i] - v; // dfr [nbr_coef - i] =
  455. v = sf2r [i] * s + sf2i [i] * c;
  456. dfi [i] = v + sf1i [i];
  457. dfi [nbr_coef - i] = v - sf1i [i];
  458. }
  459. coef_index += d_nbr_coef;
  460. }
  461. while (coef_index < _length);
  462. }
  463. template <class DT>
  464. void FFTReal <DT>::compute_direct_pass_n_osc (DataType df [], const DataType sf [], int pass) const
  465. {
  466. assert (df != 0);
  467. assert (sf != 0);
  468. assert (df != sf);
  469. assert (pass > TRIGO_BD_LIMIT);
  470. assert (pass < _nbr_bits);
  471. const long nbr_coef = 1 << pass;
  472. const long h_nbr_coef = nbr_coef >> 1;
  473. const long d_nbr_coef = nbr_coef << 1;
  474. long coef_index = 0;
  475. OscType & osc = _trigo_osc [pass - (TRIGO_BD_LIMIT + 1)];
  476. do
  477. {
  478. const DataType * const sf1r = sf + coef_index;
  479. const DataType * const sf2r = sf1r + nbr_coef;
  480. DataType * const dfr = df + coef_index;
  481. DataType * const dfi = dfr + nbr_coef;
  482. osc.clear_buffers ();
  483. // Extreme coefficients are always real
  484. dfr [0] = sf1r [0] + sf2r [0];
  485. dfi [0] = sf1r [0] - sf2r [0]; // dfr [nbr_coef] =
  486. dfr [h_nbr_coef] = sf1r [h_nbr_coef];
  487. dfi [h_nbr_coef] = sf2r [h_nbr_coef];
  488. // Others are conjugate complex numbers
  489. const DataType * const sf1i = sf1r + h_nbr_coef;
  490. const DataType * const sf2i = sf1i + nbr_coef;
  491. for (long i = 1; i < h_nbr_coef; ++ i)
  492. {
  493. osc.step ();
  494. const DataType c = osc.get_cos ();
  495. const DataType s = osc.get_sin ();
  496. DataType v;
  497. v = sf2r [i] * c - sf2i [i] * s;
  498. dfr [i] = sf1r [i] + v;
  499. dfi [-i] = sf1r [i] - v; // dfr [nbr_coef - i] =
  500. v = sf2r [i] * s + sf2i [i] * c;
  501. dfi [i] = v + sf1i [i];
  502. dfi [nbr_coef - i] = v - sf1i [i];
  503. }
  504. coef_index += d_nbr_coef;
  505. }
  506. while (coef_index < _length);
  507. }
  508. // Transform in several pass
  509. template <class DT>
  510. void FFTReal <DT>::compute_ifft_general (const DataType f [], DataType x []) const
  511. {
  512. assert (f != 0);
  513. assert (f != use_buffer ());
  514. assert (x != 0);
  515. assert (x != use_buffer ());
  516. assert (x != f);
  517. DataType * sf = const_cast <DataType *> (f);
  518. DataType * df;
  519. DataType * df_temp;
  520. if (_nbr_bits & 1)
  521. {
  522. df = use_buffer ();
  523. df_temp = x;
  524. }
  525. else
  526. {
  527. df = x;
  528. df_temp = use_buffer ();
  529. }
  530. for (int pass = _nbr_bits - 1; pass >= 3; -- pass)
  531. {
  532. compute_inverse_pass_n (df, sf, pass);
  533. if (pass < _nbr_bits - 1)
  534. {
  535. DataType * const temp_ptr = df;
  536. df = sf;
  537. sf = temp_ptr;
  538. }
  539. else
  540. {
  541. sf = df;
  542. df = df_temp;
  543. }
  544. }
  545. compute_inverse_pass_3 (df, sf);
  546. compute_inverse_pass_1_2 (x, df);
  547. }
  548. template <class DT>
  549. void FFTReal <DT>::compute_inverse_pass_n (DataType df [], const DataType sf [], int pass) const
  550. {
  551. assert (df != 0);
  552. assert (sf != 0);
  553. assert (df != sf);
  554. assert (pass >= 3);
  555. assert (pass < _nbr_bits);
  556. if (pass <= TRIGO_BD_LIMIT)
  557. {
  558. compute_inverse_pass_n_lut (df, sf, pass);
  559. }
  560. else
  561. {
  562. compute_inverse_pass_n_osc (df, sf, pass);
  563. }
  564. }
  565. template <class DT>
  566. void FFTReal <DT>::compute_inverse_pass_n_lut (DataType df [], const DataType sf [], int pass) const
  567. {
  568. assert (df != 0);
  569. assert (sf != 0);
  570. assert (df != sf);
  571. assert (pass >= 3);
  572. assert (pass < _nbr_bits);
  573. const long nbr_coef = 1 << pass;
  574. const long h_nbr_coef = nbr_coef >> 1;
  575. const long d_nbr_coef = nbr_coef << 1;
  576. long coef_index = 0;
  577. const DataType * const cos_ptr = get_trigo_ptr (pass);
  578. do
  579. {
  580. const DataType * const sfr = sf + coef_index;
  581. const DataType * const sfi = sfr + nbr_coef;
  582. DataType * const df1r = df + coef_index;
  583. DataType * const df2r = df1r + nbr_coef;
  584. // Extreme coefficients are always real
  585. df1r [0] = sfr [0] + sfi [0]; // + sfr [nbr_coef]
  586. df2r [0] = sfr [0] - sfi [0]; // - sfr [nbr_coef]
  587. df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2;
  588. df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2;
  589. // Others are conjugate complex numbers
  590. DataType * const df1i = df1r + h_nbr_coef;
  591. DataType * const df2i = df1i + nbr_coef;
  592. for (long i = 1; i < h_nbr_coef; ++ i)
  593. {
  594. df1r [i] = sfr [i] + sfi [-i]; // + sfr [nbr_coef - i]
  595. df1i [i] = sfi [i] - sfi [nbr_coef - i];
  596. const DataType c = cos_ptr [i]; // cos (i*PI/nbr_coef);
  597. const DataType s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef);
  598. const DataType vr = sfr [i] - sfi [-i]; // - sfr [nbr_coef - i]
  599. const DataType vi = sfi [i] + sfi [nbr_coef - i];
  600. df2r [i] = vr * c + vi * s;
  601. df2i [i] = vi * c - vr * s;
  602. }
  603. coef_index += d_nbr_coef;
  604. }
  605. while (coef_index < _length);
  606. }
  607. template <class DT>
  608. void FFTReal <DT>::compute_inverse_pass_n_osc (DataType df [], const DataType sf [], int pass) const
  609. {
  610. assert (df != 0);
  611. assert (sf != 0);
  612. assert (df != sf);
  613. assert (pass > TRIGO_BD_LIMIT);
  614. assert (pass < _nbr_bits);
  615. const long nbr_coef = 1 << pass;
  616. const long h_nbr_coef = nbr_coef >> 1;
  617. const long d_nbr_coef = nbr_coef << 1;
  618. long coef_index = 0;
  619. OscType & osc = _trigo_osc [pass - (TRIGO_BD_LIMIT + 1)];
  620. do
  621. {
  622. const DataType * const sfr = sf + coef_index;
  623. const DataType * const sfi = sfr + nbr_coef;
  624. DataType * const df1r = df + coef_index;
  625. DataType * const df2r = df1r + nbr_coef;
  626. osc.clear_buffers ();
  627. // Extreme coefficients are always real
  628. df1r [0] = sfr [0] + sfi [0]; // + sfr [nbr_coef]
  629. df2r [0] = sfr [0] - sfi [0]; // - sfr [nbr_coef]
  630. df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2;
  631. df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2;
  632. // Others are conjugate complex numbers
  633. DataType * const df1i = df1r + h_nbr_coef;
  634. DataType * const df2i = df1i + nbr_coef;
  635. for (long i = 1; i < h_nbr_coef; ++ i)
  636. {
  637. df1r [i] = sfr [i] + sfi [-i]; // + sfr [nbr_coef - i]
  638. df1i [i] = sfi [i] - sfi [nbr_coef - i];
  639. osc.step ();
  640. const DataType c = osc.get_cos ();
  641. const DataType s = osc.get_sin ();
  642. const DataType vr = sfr [i] - sfi [-i]; // - sfr [nbr_coef - i]
  643. const DataType vi = sfi [i] + sfi [nbr_coef - i];
  644. df2r [i] = vr * c + vi * s;
  645. df2i [i] = vi * c - vr * s;
  646. }
  647. coef_index += d_nbr_coef;
  648. }
  649. while (coef_index < _length);
  650. }
  651. template <class DT>
  652. void FFTReal <DT>::compute_inverse_pass_3 (DataType df [], const DataType sf []) const
  653. {
  654. assert (df != 0);
  655. assert (sf != 0);
  656. assert (df != sf);
  657. const DataType sqrt2_2 = DataType (SQRT2 * 0.5);
  658. long coef_index = 0;
  659. do
  660. {
  661. df [coef_index] = sf [coef_index] + sf [coef_index + 4];
  662. df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4];
  663. df [coef_index + 2] = sf [coef_index + 2] * 2;
  664. df [coef_index + 6] = sf [coef_index + 6] * 2;
  665. df [coef_index + 1] = sf [coef_index + 1] + sf [coef_index + 3];
  666. df [coef_index + 3] = sf [coef_index + 5] - sf [coef_index + 7];
  667. const DataType vr = sf [coef_index + 1] - sf [coef_index + 3];
  668. const DataType vi = sf [coef_index + 5] + sf [coef_index + 7];
  669. df [coef_index + 5] = (vr + vi) * sqrt2_2;
  670. df [coef_index + 7] = (vi - vr) * sqrt2_2;
  671. coef_index += 8;
  672. }
  673. while (coef_index < _length);
  674. }
  675. template <class DT>
  676. void FFTReal <DT>::compute_inverse_pass_1_2 (DataType x [], const DataType sf []) const
  677. {
  678. assert (x != 0);
  679. assert (sf != 0);
  680. assert (x != sf);
  681. const long * bit_rev_lut_ptr = get_br_ptr ();
  682. const DataType * sf2 = sf;
  683. long coef_index = 0;
  684. do
  685. {
  686. {
  687. const DataType b_0 = sf2 [0] + sf2 [2];
  688. const DataType b_2 = sf2 [0] - sf2 [2];
  689. const DataType b_1 = sf2 [1] * 2;
  690. const DataType b_3 = sf2 [3] * 2;
  691. x [bit_rev_lut_ptr [0]] = b_0 + b_1;
  692. x [bit_rev_lut_ptr [1]] = b_0 - b_1;
  693. x [bit_rev_lut_ptr [2]] = b_2 + b_3;
  694. x [bit_rev_lut_ptr [3]] = b_2 - b_3;
  695. }
  696. {
  697. const DataType b_0 = sf2 [4] + sf2 [6];
  698. const DataType b_2 = sf2 [4] - sf2 [6];
  699. const DataType b_1 = sf2 [5] * 2;
  700. const DataType b_3 = sf2 [7] * 2;
  701. x [bit_rev_lut_ptr [4]] = b_0 + b_1;
  702. x [bit_rev_lut_ptr [5]] = b_0 - b_1;
  703. x [bit_rev_lut_ptr [6]] = b_2 + b_3;
  704. x [bit_rev_lut_ptr [7]] = b_2 - b_3;
  705. }
  706. sf2 += 8;
  707. coef_index += 8;
  708. bit_rev_lut_ptr += 8;
  709. }
  710. while (coef_index < _length);
  711. }
  712. } // namespace ffft
  713. #endif // ffft_FFTReal_CODEHEADER_INCLUDED
  714. #undef ffft_FFTReal_CURRENT_CODEHEADER
  715. /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/