NEURON
nrngsl_real_radix2.cpp
Go to the documentation of this file.
1 /* fft/real_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 /* Hines: for greater self-containment */
21 #include "nrngsl.h"
22 /* from gsl/fft/factorize.cpp */
23 static int fft_binary_logn(const size_t n) {
24  size_t ntest;
25  size_t binary_logn = 0;
26  size_t k = 1;
27 
28  while (k < n) {
29  k *= 2;
30  binary_logn++;
31  }
32 
33  ntest = (1 << binary_logn);
34 
35  if (n != ntest) {
36  return -1; /* n is not a power of 2 */
37  }
38 
39  return binary_logn;
40 }
41 
42 /* from gsl/fft/bitreverse.cpp */
43 static int FUNCTION(fft_real, bitreverse_order)(BASE data[],
44  const size_t stride,
45  const size_t n,
46  size_t logn) {
47  /* This is the Goldrader bit-reversal algorithm */
48 
49  size_t i;
50  size_t j = 0;
51 
52  logn = 0; /* not needed for this algorithm */
53 
54  for (i = 0; i < n - 1; i++) {
55  size_t k = n / 2;
56 
57  if (i < j) {
58  const BASE tmp = VECTOR(data, stride, i);
60  VECTOR(data, stride, j) = tmp;
61  }
62 
63  while (k <= j) {
64  j = j - k;
65  k = k / 2;
66  }
67 
68  j += k;
69  }
70 
71  return 0;
72 }
73 /*-----------------------------------------*/
74 
75 int FUNCTION(gsl_fft_real, radix2_transform)(BASE data[], const size_t stride, const size_t n) {
76  int result;
77  size_t p, p_1, q;
78  size_t i;
79  size_t logn = 0;
80  int status;
81 
82  if (n == 1) /* identity operation */
83  {
84  return 0;
85  }
86 
87  /* make sure that n is a power of 2 */
88 
90 
91  if (result == -1) {
92  GSL_ERROR("n is not a power of 2", GSL_EINVAL);
93  } else {
94  logn = result;
95  }
96 
97  /* bit reverse the ordering of input data for decimation in time algorithm */
98 
99  status = FUNCTION(fft_real, bitreverse_order)(data, stride, n, logn);
100 
101  /* apply fft recursion */
102 
103  p = 1;
104  q = n;
105 
106  for (i = 1; i <= logn; i++) {
107  size_t a, b;
108 
109  p_1 = p;
110  p = 2 * p;
111  q = q / 2;
112 
113  /* a = 0 */
114 
115  for (b = 0; b < q; b++) {
116  ATOMIC t0_real = VECTOR(data, stride, b * p) + VECTOR(data, stride, b * p + p_1);
117  ATOMIC t1_real = VECTOR(data, stride, b * p) - VECTOR(data, stride, b * p + p_1);
118 
119  VECTOR(data, stride, b * p) = t0_real;
120  VECTOR(data, stride, b * p + p_1) = t1_real;
121  }
122 
123  /* a = 1 ... p_{i-1}/2 - 1 */
124 
125  {
126  ATOMIC w_real = 1.0;
127  ATOMIC w_imag = 0.0;
128 
129  const double theta = -2.0 * M_PI / p;
130 
131  const ATOMIC s = sin(theta);
132  const ATOMIC t = sin(theta / 2.0);
133  const ATOMIC s2 = 2.0 * t * t;
134 
135  for (a = 1; a < (p_1) / 2; a++) {
136  /* trignometric recurrence for w-> exp(i theta) w */
137 
138  {
139  const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real;
140  const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag;
141  w_real = tmp_real;
142  w_imag = tmp_imag;
143  }
144 
145  for (b = 0; b < q; b++) {
146  ATOMIC z0_real = VECTOR(data, stride, b * p + a);
147  ATOMIC z0_imag = VECTOR(data, stride, b * p + p_1 - a);
148  ATOMIC z1_real = VECTOR(data, stride, b * p + p_1 + a);
149  ATOMIC z1_imag = VECTOR(data, stride, b * p + p - a);
150 
151  /* t0 = z0 + w * z1 */
152 
153  ATOMIC t0_real = z0_real + w_real * z1_real - w_imag * z1_imag;
154  ATOMIC t0_imag = z0_imag + w_real * z1_imag + w_imag * z1_real;
155 
156  /* t1 = z0 - w * z1 */
157 
158  ATOMIC t1_real = z0_real - w_real * z1_real + w_imag * z1_imag;
159  ATOMIC t1_imag = z0_imag - w_real * z1_imag - w_imag * z1_real;
160 
161  VECTOR(data, stride, b * p + a) = t0_real;
162  VECTOR(data, stride, b * p + p - a) = t0_imag;
163 
164  VECTOR(data, stride, b * p + p_1 - a) = t1_real;
165  VECTOR(data, stride, b * p + p_1 + a) = -t1_imag;
166  }
167  }
168  }
169 
170  if (p_1 > 1) {
171  for (b = 0; b < q; b++) {
172  /* a = p_{i-1}/2 */
173 
174  VECTOR(data, stride, b * p + p - p_1 / 2) *= -1;
175  }
176  }
177  }
178  return 0;
179 }
#define data
Definition: md1redef.h:36
static RNG::key_type k
Definition: nrnran123.cpp:9
#define M_PI
Definition: ivocvect.cpp:46
sin
Definition: extdef.h:3
#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
int status
size_t q
static int FUNCTION(fft_real, bitreverse_order)(BASE data[]
size_t p_1
static int fft_binary_logn(const size_t n)
static int const size_t stride
static int const size_t const size_t size_t logn
size_t j
size_t p
static int const size_t const size_t n
size_t i
s
Definition: multisend.cpp:521