gsl_fft__real_pass_n.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* fft/real_pass_n.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. static void
  20. FUNCTION(fft_real,pass_n) (const BASE in[],
  21. const size_t istride,
  22. BASE out[],
  23. const size_t ostride,
  24. const size_t factor,
  25. const size_t product,
  26. const size_t n,
  27. const TYPE(gsl_complex) twiddle[])
  28. {
  29. size_t k, k1;
  30. const size_t m = n / factor;
  31. const size_t q = n / product;
  32. const size_t product_1 = product / factor;
  33. size_t e1, e2;
  34. const double d_theta = 2.0 * M_PI / ((double) factor);
  35. const ATOMIC cos_d_theta = cos (d_theta);
  36. const ATOMIC sin_d_theta = sin (d_theta);
  37. for (k1 = 0; k1 < q; k1++)
  38. {
  39. /* compute x = W(factor) z, for z real */
  40. ATOMIC dw_real = 1.0, dw_imag = 0.0;
  41. for (e1 = 0; e1 <= factor - e1; e1++)
  42. {
  43. ATOMIC sum_real = 0.0;
  44. ATOMIC sum_imag = 0.0;
  45. ATOMIC w_real = 1.0, w_imag = 0.0;
  46. if (e1 > 0)
  47. {
  48. ATOMIC tmp_real = dw_real * cos_d_theta + dw_imag * sin_d_theta;
  49. ATOMIC tmp_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta;
  50. dw_real = tmp_real;
  51. dw_imag = tmp_imag;
  52. }
  53. for (e2 = 0; e2 < factor; e2++)
  54. {
  55. ATOMIC z_real = VECTOR(in,istride,k1 * product_1 + e2 * m);
  56. if (e2 > 0)
  57. {
  58. ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
  59. ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
  60. w_real = tmp_real;
  61. w_imag = tmp_imag;
  62. }
  63. sum_real += w_real * z_real;
  64. sum_imag += w_imag * z_real;
  65. }
  66. if (e1 == 0)
  67. {
  68. const size_t to0 = product * k1;
  69. VECTOR(out,ostride,to0) = sum_real;
  70. }
  71. else if (e1 < factor - e1)
  72. {
  73. const size_t to0 = k1 * product + 2 * e1 * product_1 - 1;
  74. VECTOR(out,ostride,to0) = sum_real;
  75. VECTOR(out,ostride,to0 + 1) = sum_imag;
  76. }
  77. else if (e1 == factor - e1)
  78. {
  79. const size_t to0 = k1 * product + 2 * e1 * product_1 - 1;
  80. VECTOR(out,ostride,to0) = sum_real;
  81. }
  82. }
  83. }
  84. if (product_1 == 1)
  85. return;
  86. for (k = 1; k < (product_1 + 1) / 2; k++)
  87. {
  88. for (k1 = 0; k1 < q; k1++)
  89. {
  90. ATOMIC dw_real = 1.0, dw_imag = 0.0;
  91. for (e1 = 0; e1 < factor; e1++)
  92. {
  93. ATOMIC sum_real = 0.0, sum_imag = 0.0;
  94. ATOMIC w_real = 1.0, w_imag = 0.0;
  95. if (e1 > 0)
  96. {
  97. const ATOMIC tmp_real = dw_real * cos_d_theta + dw_imag * sin_d_theta;
  98. const ATOMIC tmp_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta;
  99. dw_real = tmp_real;
  100. dw_imag = tmp_imag;
  101. }
  102. for (e2 = 0; e2 < factor; e2++)
  103. {
  104. int tskip = (product_1 + 1) / 2 - 1;
  105. const size_t from0 = k1 * product_1 + 2 * k + e2 * m - 1;
  106. ATOMIC tw_real, tw_imag;
  107. ATOMIC z_real, z_imag;
  108. if (e2 == 0)
  109. {
  110. tw_real = 1.0;
  111. tw_imag = 0.0;
  112. }
  113. else
  114. {
  115. const size_t t_index = (k - 1) + (e2 - 1) * tskip;
  116. tw_real = GSL_REAL(twiddle[t_index]);
  117. tw_imag = -GSL_IMAG(twiddle[t_index]);
  118. }
  119. {
  120. const ATOMIC f0_real = VECTOR(in,istride,from0);
  121. const ATOMIC f0_imag = VECTOR(in,istride,from0 + 1);
  122. z_real = tw_real * f0_real - tw_imag * f0_imag;
  123. z_imag = tw_real * f0_imag + tw_imag * f0_real;
  124. }
  125. if (e2 > 0)
  126. {
  127. const ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
  128. const ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
  129. w_real = tmp_real;
  130. w_imag = tmp_imag;
  131. }
  132. sum_real += w_real * z_real - w_imag * z_imag;
  133. sum_imag += w_real * z_imag + w_imag * z_real;
  134. }
  135. if (e1 < factor - e1)
  136. {
  137. const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k;
  138. VECTOR(out,ostride,to0) = sum_real;
  139. VECTOR(out,ostride,to0 + 1) = sum_imag;
  140. }
  141. else
  142. {
  143. const size_t to0 = k1 * product - 1 + 2 * (factor - e1) * product_1 - 2 * k;
  144. VECTOR(out,ostride,to0) = sum_real;
  145. VECTOR(out,ostride,to0 + 1) = -sum_imag;
  146. }
  147. }
  148. }
  149. }
  150. if (product_1 % 2 == 1)
  151. return;
  152. {
  153. double tw_arg = M_PI / ((double) factor);
  154. ATOMIC cos_tw_arg = cos (tw_arg);
  155. ATOMIC sin_tw_arg = -sin (tw_arg);
  156. for (k1 = 0; k1 < q; k1++)
  157. {
  158. ATOMIC dw_real = 1.0, dw_imag = 0.0;
  159. for (e1 = 0; e1 < factor; e1++)
  160. {
  161. ATOMIC z_real, z_imag;
  162. ATOMIC sum_real = 0.0;
  163. ATOMIC sum_imag = 0.0;
  164. ATOMIC w_real = 1.0, w_imag = 0.0;
  165. ATOMIC tw_real = 1.0, tw_imag = 0.0;
  166. if (e1 > 0)
  167. {
  168. ATOMIC t_real = dw_real * cos_d_theta + dw_imag * sin_d_theta;
  169. ATOMIC t_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta;
  170. dw_real = t_real;
  171. dw_imag = t_imag;
  172. }
  173. for (e2 = 0; e2 < factor; e2++)
  174. {
  175. if (e2 > 0)
  176. {
  177. ATOMIC tmp_real = tw_real * cos_tw_arg - tw_imag * sin_tw_arg;
  178. ATOMIC tmp_imag = tw_real * sin_tw_arg + tw_imag * cos_tw_arg;
  179. tw_real = tmp_real;
  180. tw_imag = tmp_imag;
  181. }
  182. if (e2 > 0)
  183. {
  184. ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
  185. ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
  186. w_real = tmp_real;
  187. w_imag = tmp_imag;
  188. }
  189. {
  190. const size_t from0 = k1 * product_1 + 2 * k + e2 * m - 1;
  191. const ATOMIC f0_real = VECTOR(in,istride,from0);
  192. z_real = tw_real * f0_real;
  193. z_imag = tw_imag * f0_real;
  194. }
  195. sum_real += w_real * z_real - w_imag * z_imag;
  196. sum_imag += w_real * z_imag + w_imag * z_real;
  197. }
  198. if (e1 + 1 < factor - e1)
  199. {
  200. const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k;
  201. VECTOR(out,ostride,to0) = sum_real;
  202. VECTOR(out,ostride,to0 + 1) = sum_imag;
  203. }
  204. else if (e1 + 1 == factor - e1)
  205. {
  206. const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k;
  207. VECTOR(out,ostride,to0) = sum_real;
  208. }
  209. else
  210. {
  211. const size_t to0 = k1 * product - 1 + 2 * (factor - e1) * product_1 - 2 * k;
  212. VECTOR(out,ostride,to0) = sum_real;
  213. VECTOR(out,ostride,to0 + 1) = -sum_imag;
  214. }
  215. }
  216. }
  217. }
  218. return;
  219. }