NEURON
nrngsl_hc_radix2.cpp
Go to the documentation of this file.
1 /* fft/hc_radix2.cpp
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 
20 int FUNCTION(gsl_fft_halfcomplex,
21  radix2_backward)(BASE data[], const size_t stride, const size_t n) {
22  int status = FUNCTION(gsl_fft_halfcomplex, radix2_transform)(data, stride, n);
23  return status;
24 }
25 
26 int FUNCTION(gsl_fft_halfcomplex,
27  radix2_inverse)(BASE data[], const size_t stride, const size_t n) {
28  int status = FUNCTION(gsl_fft_halfcomplex, radix2_transform)(data, stride, n);
29 
30  if (status) {
31  return status;
32  }
33 
34  /* normalize inverse fft with 1/n */
35 
36  {
37  const ATOMIC norm = 1.0 / n;
38  size_t i;
39  for (i = 0; i < n; i++) {
40  data[stride * i] *= norm;
41  }
42  }
43  return status;
44 }
45 
46 int FUNCTION(gsl_fft_halfcomplex,
47  radix2_transform)(BASE data[], const size_t stride, const size_t n) {
48  int result;
49  size_t p, p_1, q;
50  size_t i;
51  size_t logn = 0;
52  int status;
53 
54  if (n == 1) /* identity operation */
55  {
56  return 0;
57  }
58 
59  /* make sure that n is a power of 2 */
60 
62 
63  if (result == -1) {
64  GSL_ERROR("n is not a power of 2", GSL_EINVAL);
65  } else {
66  logn = result;
67  }
68 
69  /* apply fft recursion */
70 
71  p = n;
72  q = 1;
73  p_1 = n / 2;
74 
75  for (i = 1; i <= logn; i++) {
76  size_t a, b;
77 
78  /* a = 0 */
79 
80  for (b = 0; b < q; b++) {
81  const ATOMIC z0 = VECTOR(data, stride, b * p);
82  const ATOMIC z1 = VECTOR(data, stride, b * p + p_1);
83 
84  const ATOMIC t0_real = z0 + z1;
85  const ATOMIC t1_real = z0 - z1;
86 
87  VECTOR(data, stride, b * p) = t0_real;
88  VECTOR(data, stride, b * p + p_1) = t1_real;
89  }
90 
91  /* a = 1 ... p_{i-1}/2 - 1 */
92 
93  {
94  ATOMIC w_real = 1.0;
95  ATOMIC w_imag = 0.0;
96 
97  const ATOMIC theta = 2.0 * M_PI / p;
98 
99  const ATOMIC s = sin(theta);
100  const ATOMIC t = sin(theta / 2.0);
101  const ATOMIC s2 = 2.0 * t * t;
102 
103  for (a = 1; a < (p_1) / 2; a++) {
104  /* trignometric recurrence for w-> exp(i theta) w */
105 
106  {
107  const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real;
108  const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag;
109  w_real = tmp_real;
110  w_imag = tmp_imag;
111  }
112 
113  for (b = 0; b < q; b++) {
114  ATOMIC z0_real = VECTOR(data, stride, b * p + a);
115  ATOMIC z0_imag = VECTOR(data, stride, b * p + p - a);
116  ATOMIC z1_real = VECTOR(data, stride, b * p + p_1 - a);
117  ATOMIC z1_imag = -VECTOR(data, stride, b * p + p_1 + a);
118 
119  /* t0 = z0 + z1 */
120 
121  ATOMIC t0_real = z0_real + z1_real;
122  ATOMIC t0_imag = z0_imag + z1_imag;
123 
124  /* t1 = (z0 - z1) */
125 
126  ATOMIC t1_real = z0_real - z1_real;
127  ATOMIC t1_imag = z0_imag - z1_imag;
128 
129  VECTOR(data, stride, b * p + a) = t0_real;
130  VECTOR(data, stride, b * p + p_1 - a) = t0_imag;
131 
132  VECTOR(data, stride, b * p + p_1 + a) = (w_real * t1_real - w_imag * t1_imag);
133  VECTOR(data, stride, b * p + p - a) = (w_real * t1_imag + w_imag * t1_real);
134  }
135  }
136  }
137 
138  if (p_1 > 1) {
139  for (b = 0; b < q; b++) {
140  VECTOR(data, stride, b * p + p_1 / 2) *= 2;
141  VECTOR(data, stride, b * p + p_1 + p_1 / 2) *= -2;
142  }
143  }
144 
145  p_1 = p_1 / 2;
146  p = p / 2;
147  q = q * 2;
148  }
149 
150  /* bit reverse the ordering of output data for decimation in
151  frequency algorithm */
152 
153  status = FUNCTION(fft_real, bitreverse_order)(data, stride, n, logn);
154 
155  return 0;
156 }
#define data
Definition: md1redef.h:36
#define M_PI
Definition: ivocvect.cpp:46
sin
Definition: extdef.h:3
double norm(const Point3D &p1)
Definition: lfp.hpp:22
#define GSL_ERROR(a, b)
Definition: nrngsl.h:4
#define VECTOR(a, stride, i)
Definition: nrngsl.h:7
#define BASE
Definition: nrngsl.h:3
#define ATOMIC
Definition: nrngsl.h:6
size_t q
size_t p_1
return status
int const size_t stride
size_t logn
size_t p
int const size_t const size_t n
int FUNCTION(gsl_fft_halfcomplex, radix2_backward)(BASE data[]
size_t i
static int fft_binary_logn(const size_t n)
s
Definition: multisend.cpp:521