gsl_fft__c_main.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* fft/c_main.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. #include "gsl_fft__c_pass.h"
  20. int
  21. FUNCTION(gsl_fft_complex,forward) (TYPE(gsl_complex_packed_array) data,
  22. const size_t stride,
  23. const size_t n,
  24. const TYPE(gsl_fft_complex_wavetable) * wavetable,
  25. TYPE(gsl_fft_complex_workspace) * work)
  26. {
  27. gsl_fft_direction sign = gsl_fft_forward;
  28. int status = FUNCTION(gsl_fft_complex,transform) (data, stride, n,
  29. wavetable, work, sign);
  30. return status;
  31. }
  32. int
  33. FUNCTION(gsl_fft_complex,backward) (TYPE(gsl_complex_packed_array) data,
  34. const size_t stride,
  35. const size_t n,
  36. const TYPE(gsl_fft_complex_wavetable) * wavetable,
  37. TYPE(gsl_fft_complex_workspace) * work)
  38. {
  39. gsl_fft_direction sign = gsl_fft_backward;
  40. int status = FUNCTION(gsl_fft_complex,transform) (data, stride, n,
  41. wavetable, work, sign);
  42. return status;
  43. }
  44. int
  45. FUNCTION(gsl_fft_complex,inverse) (TYPE(gsl_complex_packed_array) data,
  46. const size_t stride,
  47. const size_t n,
  48. const TYPE(gsl_fft_complex_wavetable) * wavetable,
  49. TYPE(gsl_fft_complex_workspace) * work)
  50. {
  51. gsl_fft_direction sign = gsl_fft_backward;
  52. int status = FUNCTION(gsl_fft_complex,transform) (data, stride, n,
  53. wavetable, work, sign);
  54. if (status)
  55. {
  56. return status;
  57. }
  58. /* normalize inverse fft with 1/n */
  59. {
  60. const ATOMIC norm = ONE / (ATOMIC)n;
  61. size_t i;
  62. for (i = 0; i < n; i++)
  63. {
  64. REAL(data,stride,i) *= norm;
  65. IMAG(data,stride,i) *= norm;
  66. }
  67. }
  68. return status;
  69. }
  70. int
  71. FUNCTION(gsl_fft_complex,transform) (TYPE(gsl_complex_packed_array) data,
  72. const size_t stride,
  73. const size_t n,
  74. const TYPE(gsl_fft_complex_wavetable) * wavetable,
  75. TYPE(gsl_fft_complex_workspace) * work,
  76. const gsl_fft_direction sign)
  77. {
  78. const size_t nf = wavetable->nf;
  79. size_t i;
  80. size_t q, product = 1;
  81. TYPE(gsl_complex) *twiddle1, *twiddle2, *twiddle3, *twiddle4,
  82. *twiddle5, *twiddle6;
  83. size_t state = 0;
  84. BASE * const scratch = work->scratch;
  85. BASE * in = data;
  86. size_t istride = stride;
  87. BASE * out = scratch;
  88. size_t ostride = 1;
  89. if (n == 0)
  90. {
  91. GSL_ERROR ("length n must be positive integer", GSL_EDOM);
  92. }
  93. if (n == 1)
  94. { /* FFT of 1 data point is the identity */
  95. return 0;
  96. }
  97. if (n != wavetable->n)
  98. {
  99. GSL_ERROR ("wavetable does not match length of data", GSL_EINVAL);
  100. }
  101. if (n != work->n)
  102. {
  103. GSL_ERROR ("workspace does not match length of data", GSL_EINVAL);
  104. }
  105. for (i = 0; i < nf; i++)
  106. {
  107. const size_t factor = wavetable->factor[i];
  108. product *= factor;
  109. q = n / product;
  110. if (state == 0)
  111. {
  112. in = data;
  113. istride = stride;
  114. out = scratch;
  115. ostride = 1;
  116. state = 1;
  117. }
  118. else
  119. {
  120. in = scratch;
  121. istride = 1;
  122. out = data;
  123. ostride = stride;
  124. state = 0;
  125. }
  126. if (factor == 2)
  127. {
  128. twiddle1 = wavetable->twiddle[i];
  129. FUNCTION(fft_complex,pass_2) (in, istride, out, ostride, sign,
  130. product, n, twiddle1);
  131. }
  132. else if (factor == 3)
  133. {
  134. twiddle1 = wavetable->twiddle[i];
  135. twiddle2 = twiddle1 + q;
  136. FUNCTION(fft_complex,pass_3) (in, istride, out, ostride, sign,
  137. product, n, twiddle1, twiddle2);
  138. }
  139. else if (factor == 4)
  140. {
  141. twiddle1 = wavetable->twiddle[i];
  142. twiddle2 = twiddle1 + q;
  143. twiddle3 = twiddle2 + q;
  144. FUNCTION(fft_complex,pass_4) (in, istride, out, ostride, sign,
  145. product, n, twiddle1, twiddle2,
  146. twiddle3);
  147. }
  148. else if (factor == 5)
  149. {
  150. twiddle1 = wavetable->twiddle[i];
  151. twiddle2 = twiddle1 + q;
  152. twiddle3 = twiddle2 + q;
  153. twiddle4 = twiddle3 + q;
  154. FUNCTION(fft_complex,pass_5) (in, istride, out, ostride, sign,
  155. product, n, twiddle1, twiddle2,
  156. twiddle3, twiddle4);
  157. }
  158. else if (factor == 6)
  159. {
  160. twiddle1 = wavetable->twiddle[i];
  161. twiddle2 = twiddle1 + q;
  162. twiddle3 = twiddle2 + q;
  163. twiddle4 = twiddle3 + q;
  164. twiddle5 = twiddle4 + q;
  165. FUNCTION(fft_complex,pass_6) (in, istride, out, ostride, sign,
  166. product, n, twiddle1, twiddle2,
  167. twiddle3, twiddle4, twiddle5);
  168. }
  169. else if (factor == 7)
  170. {
  171. twiddle1 = wavetable->twiddle[i];
  172. twiddle2 = twiddle1 + q;
  173. twiddle3 = twiddle2 + q;
  174. twiddle4 = twiddle3 + q;
  175. twiddle5 = twiddle4 + q;
  176. twiddle6 = twiddle5 + q;
  177. FUNCTION(fft_complex,pass_7) (in, istride, out, ostride, sign,
  178. product, n, twiddle1, twiddle2,
  179. twiddle3, twiddle4, twiddle5,
  180. twiddle6);
  181. }
  182. else
  183. {
  184. twiddle1 = wavetable->twiddle[i];
  185. FUNCTION(fft_complex,pass_n) (in, istride, out, ostride, sign,
  186. factor, product, n, twiddle1);
  187. }
  188. }
  189. if (state == 1) /* copy results back from scratch to data */
  190. {
  191. for (i = 0; i < n; i++)
  192. {
  193. REAL(data,stride,i) = REAL(scratch,1,i) ;
  194. IMAG(data,stride,i) = IMAG(scratch,1,i) ;
  195. }
  196. }
  197. return 0;
  198. }