gsl_fft__hc_main.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* fft/hc_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__config.h"
  20. #include <stdlib.h>
  21. #include <math.h>
  22. #include "gsl_errno.h"
  23. #include "gsl_complex.h"
  24. #include "gsl_fft_halfcomplex.h"
  25. #include "gsl_fft__hc_pass.h"
  26. int
  27. FUNCTION(gsl_fft_halfcomplex,backward) (BASE data[], const size_t stride,
  28. const size_t n,
  29. const TYPE(gsl_fft_halfcomplex_wavetable) * wavetable,
  30. TYPE(gsl_fft_real_workspace) * work)
  31. {
  32. int status = FUNCTION(gsl_fft_halfcomplex,transform) (data, stride, n, wavetable, work) ;
  33. return status ;
  34. }
  35. int
  36. FUNCTION(gsl_fft_halfcomplex,inverse) (BASE data[], const size_t stride,
  37. const size_t n,
  38. const TYPE(gsl_fft_halfcomplex_wavetable) * wavetable,
  39. TYPE(gsl_fft_real_workspace) * work)
  40. {
  41. int status = FUNCTION(gsl_fft_halfcomplex,transform) (data, stride, n, wavetable, work);
  42. if (status)
  43. {
  44. return status;
  45. }
  46. /* normalize inverse fft with 1/n */
  47. {
  48. const double norm = 1.0 / n;
  49. size_t i;
  50. for (i = 0; i < n; i++)
  51. {
  52. data[stride*i] *= norm;
  53. }
  54. }
  55. return status;
  56. }
  57. int
  58. FUNCTION(gsl_fft_halfcomplex,transform) (BASE data[], const size_t stride, const size_t n,
  59. const TYPE(gsl_fft_halfcomplex_wavetable) * wavetable,
  60. TYPE(gsl_fft_real_workspace) * work)
  61. {
  62. BASE * const scratch = work->scratch;
  63. BASE * in;
  64. BASE * out;
  65. size_t istride, ostride ;
  66. size_t factor, product, q;
  67. size_t i;
  68. size_t nf;
  69. int state;
  70. int product_1;
  71. int tskip;
  72. TYPE(gsl_complex) *twiddle1, *twiddle2, *twiddle3, *twiddle4;
  73. if (n == 0)
  74. {
  75. GSL_ERROR ("length n must be positive integer", GSL_EDOM);
  76. }
  77. if (n == 1)
  78. { /* FFT of one data point is the identity */
  79. return 0;
  80. }
  81. if (n != wavetable->n)
  82. {
  83. GSL_ERROR ("wavetable does not match length of data", GSL_EINVAL);
  84. }
  85. if (n != work->n)
  86. {
  87. GSL_ERROR ("workspace does not match length of data", GSL_EINVAL);
  88. }
  89. nf = wavetable->nf;
  90. product = 1;
  91. state = 0;
  92. for (i = 0; i < nf; i++)
  93. {
  94. factor = wavetable->factor[i];
  95. product_1 = product;
  96. product *= factor;
  97. q = n / product;
  98. tskip = (q + 1) / 2 - 1;
  99. if (state == 0)
  100. {
  101. in = data;
  102. istride = stride;
  103. out = scratch;
  104. ostride = 1;
  105. state = 1;
  106. }
  107. else
  108. {
  109. in = scratch;
  110. istride = 1;
  111. out = data;
  112. ostride = stride;
  113. state = 0;
  114. }
  115. if (factor == 2)
  116. {
  117. twiddle1 = wavetable->twiddle[i];
  118. FUNCTION(fft_halfcomplex,pass_2) (in, istride, out, ostride,
  119. product, n, twiddle1);
  120. }
  121. else if (factor == 3)
  122. {
  123. twiddle1 = wavetable->twiddle[i];
  124. twiddle2 = twiddle1 + tskip;
  125. FUNCTION(fft_halfcomplex,pass_3) (in, istride, out, ostride,
  126. product, n, twiddle1, twiddle2);
  127. }
  128. else if (factor == 4)
  129. {
  130. twiddle1 = wavetable->twiddle[i];
  131. twiddle2 = twiddle1 + tskip;
  132. twiddle3 = twiddle2 + tskip;
  133. FUNCTION(fft_halfcomplex,pass_4) (in, istride, out, ostride,
  134. product, n, twiddle1, twiddle2,
  135. twiddle3);
  136. }
  137. else if (factor == 5)
  138. {
  139. twiddle1 = wavetable->twiddle[i];
  140. twiddle2 = twiddle1 + tskip;
  141. twiddle3 = twiddle2 + tskip;
  142. twiddle4 = twiddle3 + tskip;
  143. FUNCTION(fft_halfcomplex,pass_5) (in, istride, out, ostride,
  144. product, n, twiddle1, twiddle2,
  145. twiddle3, twiddle4);
  146. }
  147. else
  148. {
  149. twiddle1 = wavetable->twiddle[i];
  150. FUNCTION(fft_halfcomplex,pass_n) (in, istride, out, ostride,
  151. factor, product, n, twiddle1);
  152. }
  153. }
  154. if (state == 1) /* copy results back from scratch to data */
  155. {
  156. for (i = 0; i < n; i++)
  157. {
  158. data[stride*i] = scratch[i] ;
  159. }
  160. }
  161. return 0;
  162. }