gsl_fft__hc_pass_n.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /* fft/hc_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_halfcomplex,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 < product_1; k1++)
  38. {
  39. /* compute z = W(factor) x, for x halfcomplex */
  40. ATOMIC dw_real = 1.0, dw_imag = 0.0;
  41. for (e1 = 0; e1 < factor; e1++)
  42. {
  43. ATOMIC sum_real = 0.0;
  44. ATOMIC w_real = 1.0, w_imag = 0.0;
  45. if (e1 > 0)
  46. {
  47. ATOMIC tmp_real = dw_real * cos_d_theta - dw_imag * sin_d_theta;
  48. ATOMIC tmp_imag = dw_real * sin_d_theta + dw_imag * cos_d_theta;
  49. dw_real = tmp_real;
  50. dw_imag = tmp_imag;
  51. }
  52. for (e2 = 0; e2 <= factor - e2; e2++)
  53. {
  54. ATOMIC z_real, z_imag;
  55. if (e2 > 0)
  56. {
  57. ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
  58. ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
  59. w_real = tmp_real;
  60. w_imag = tmp_imag;
  61. }
  62. if (e2 == 0)
  63. {
  64. size_t from_idx = factor * k1 * q;
  65. z_real = VECTOR(in,istride,from_idx);
  66. z_imag = 0.0;
  67. sum_real += w_real * z_real - w_imag * z_imag;
  68. }
  69. else if (e2 == factor - e2)
  70. {
  71. size_t from_idx = factor * q * k1 + 2 * e2 * q - 1;
  72. z_real = VECTOR(in,istride,from_idx);
  73. z_imag = 0.0;
  74. sum_real += w_real * z_real;
  75. }
  76. else
  77. {
  78. size_t from_idx = factor * q * k1 + 2 * e2 * q - 1;
  79. z_real = VECTOR(in,istride,from_idx);
  80. z_imag = VECTOR(in,istride,from_idx + 1);
  81. sum_real += 2 * (w_real * z_real - w_imag * z_imag);
  82. }
  83. }
  84. {
  85. const size_t to_idx = q * k1 + e1 * m;
  86. VECTOR(out,ostride,to_idx) = sum_real;
  87. }
  88. }
  89. }
  90. if (q == 1)
  91. return;
  92. for (k = 1; k < (q + 1) / 2; k++)
  93. {
  94. for (k1 = 0; k1 < product_1; k1++)
  95. {
  96. ATOMIC dw_real = 1.0, dw_imag = 0.0;
  97. for (e1 = 0; e1 < factor; e1++)
  98. {
  99. ATOMIC z_real, z_imag;
  100. ATOMIC sum_real = 0.0;
  101. ATOMIC sum_imag = 0.0;
  102. ATOMIC w_real = 1.0, w_imag = 0.0;
  103. if (e1 > 0)
  104. {
  105. ATOMIC t_real = dw_real * cos_d_theta - dw_imag * sin_d_theta;
  106. ATOMIC t_imag = dw_real * sin_d_theta + dw_imag * cos_d_theta;
  107. dw_real = t_real;
  108. dw_imag = t_imag;
  109. }
  110. for (e2 = 0; e2 < factor; e2++)
  111. {
  112. if (e2 > 0)
  113. {
  114. ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
  115. ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
  116. w_real = tmp_real;
  117. w_imag = tmp_imag;
  118. }
  119. if (e2 < factor - e2)
  120. {
  121. const size_t from0 = factor * k1 * q + 2 * k + 2 * e2 * q - 1;
  122. z_real = VECTOR(in,istride,from0);
  123. z_imag = VECTOR(in,istride,from0 + 1);
  124. }
  125. else
  126. {
  127. const size_t from0 = factor * k1 * q - 2 * k + 2 * (factor - e2) * q - 1;
  128. z_real = VECTOR(in,istride,from0);
  129. z_imag = -VECTOR(in,istride,from0 + 1);
  130. }
  131. sum_real += w_real * z_real - w_imag * z_imag;
  132. sum_imag += w_real * z_imag + w_imag * z_real;
  133. }
  134. if (k == 0 || e1 == 0)
  135. {
  136. w_real = 1.0;
  137. w_imag = 0.0;
  138. }
  139. else
  140. {
  141. size_t tskip = (q + 1) / 2 - 1;
  142. w_real = GSL_REAL(twiddle[k - 1 + tskip * (e1 - 1)]);
  143. w_imag = GSL_IMAG(twiddle[k - 1 + tskip * (e1 - 1)]);
  144. }
  145. {
  146. const size_t to0 = k1 * q + 2 * k + e1 * m - 1;
  147. VECTOR(out,ostride,to0) = w_real * sum_real - w_imag * sum_imag;
  148. VECTOR(out,ostride,to0 + 1) = w_real * sum_imag + w_imag * sum_real;
  149. }
  150. }
  151. }
  152. }
  153. if (q % 2 == 1)
  154. return;
  155. {
  156. double tw_arg = M_PI / ((double) factor);
  157. ATOMIC cos_tw_arg = cos (tw_arg);
  158. ATOMIC sin_tw_arg = sin (tw_arg);
  159. for (k1 = 0; k1 < product_1; k1++)
  160. {
  161. ATOMIC dw_real = 1.0, dw_imag = 0.0;
  162. ATOMIC tw_real = 1.0, tw_imag = 0.0;
  163. for (e1 = 0; e1 < factor; e1++)
  164. {
  165. ATOMIC w_real, w_imag, z_real, z_imag;
  166. ATOMIC sum_real = 0.0;
  167. if (e1 > 0)
  168. {
  169. ATOMIC tmp_real = tw_real * cos_tw_arg - tw_imag * sin_tw_arg;
  170. ATOMIC tmp_imag = tw_real * sin_tw_arg + tw_imag * cos_tw_arg;
  171. tw_real = tmp_real;
  172. tw_imag = tmp_imag;
  173. }
  174. w_real = tw_real;
  175. w_imag = tw_imag;
  176. if (e1 > 0)
  177. {
  178. ATOMIC t_real = dw_real * cos_d_theta - dw_imag * sin_d_theta;
  179. ATOMIC t_imag = dw_real * sin_d_theta + dw_imag * cos_d_theta;
  180. dw_real = t_real;
  181. dw_imag = t_imag;
  182. }
  183. for (e2 = 0; e2 <= factor - e2 - 1; e2++)
  184. {
  185. if (e2 > 0)
  186. {
  187. ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag;
  188. ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real;
  189. w_real = tmp_real;
  190. w_imag = tmp_imag;
  191. }
  192. if (e2 == factor - e2 - 1)
  193. {
  194. const size_t from0 = factor * k1 * q + q + 2 * e2 * q - 1;
  195. z_real = VECTOR(in,istride,from0);
  196. z_imag = 0.0;
  197. sum_real += w_real * z_real - w_imag * z_imag;
  198. }
  199. else
  200. {
  201. const size_t from0 = factor * k1 * q + q + 2 * e2 * q - 1;
  202. z_real = VECTOR(in,istride,from0);
  203. z_imag = VECTOR(in,istride,from0 + 1);
  204. sum_real += 2 * (w_real * z_real - w_imag * z_imag);
  205. }
  206. }
  207. {
  208. const size_t to0 = k1 * q + q + e1 * m - 1;
  209. VECTOR(out,ostride,to0) = sum_real;
  210. }
  211. }
  212. }
  213. }
  214. return;
  215. }