KSquare Utilities
kku_fftw.cpp
Go to the documentation of this file.
1 #include "FirstIncludes.h"
2 #include <stdlib.h>
3 #include <memory>
4 #include <math.h>
5 
6 #include <complex>
7 #include <fstream>
8 #include <iostream>
9 #include <string>
10 #include <vector>
11 
12 #include "MemoryDebug.h"
13 using namespace std;
14 
15 #if defined(FFTW_AVAILABLE)
16 #endif
17 
18 #include "KKBaseTypes.h"
19 #include "GoalKeeper.h"
20 #include "kku_fftw.h"
21 using namespace KKB;
22 
23 
24 /*
25 fftw_plan_class::fftw_plan_class (kkint32 _n,
26  fftw_direction _dir,
27  kkint32 _flags
28  ):
29  n (_n),
30  dir (_dir),
31  flags (_flags)
32 {
33 }
34 
35 
36 
37 fftwnd_plan_class::fftwnd_plan_class (kkint32 _nx,
38  kkint32 _ny,
39  fftw_direction _dir,
40  kkint32 _flags
41  ):
42  nx (_nx),
43  ny (_ny),
44  dir (_dir),
45  flags (_flags)
46 {
47 }
48 
49 
50 
51 fftw_plan KKB::fftw_create_plan (kkint32 n,
52  fftw_direction dir,
53  kkint32 flags
54  )
55 {
56  return new fftw_plan_class (n, dir, flags);
57 }
58 
59 
60 
61 void KKB::fftw_destroy_plan (fftw_plan plan)
62 {
63  delete plan;
64  plan = NULL;
65 }
66 
67 
68 
69 fftwnd_plan KKB::fftw2d_create_plan (kkint32 nx,
70  kkint32 ny,
71  fftw_direction dir,
72  kkint32 flags
73  )
74 {
75  return new fftwnd_plan_class (nx, ny, dir, flags);
76 } // fftw2d_create_plan
77 
78 
79 
80 void KKB::fftwnd_destroy_plan (fftwnd_plan plan)
81 {
82  delete plan;
83 }
84 
85 
86 
87 void KKB::fftw_one (fftw_plan plan,
88  fftw_complex* in,
89  fftw_complex* out
90  )
91 {
92  cerr << endl << endl
93  << "fftw_one ****ERROR*** This function is not implemented." << endl
94  << endl;
95 
96  for (kkint32 x = 0; x < plan->N (); ++x)
97  {
98  out[x].im = 0.0;
99  out[x].re = 0.0;
100  }
101 } // fftw_one
102 
103 
104 
105 
106 void KKB::fftwnd_one (fftwnd_plan p,
107  fftw_complex* in,
108  fftw_complex* out
109  )
110 {
111  cerr << endl << endl
112  << "fftw_one ****ERROR*** This function is not implemented." << endl
113  << endl;
114 
115  kkint32 totCells = p->NX () * p->NY ();
116 
117  for (kkint32 x = 0; x < totCells; ++x)
118  {
119  out[x].im = 0.0;
120  out[x].re = 0.0;
121  }
122 } // fftwnd_one
123 
124 */
125 
126 
127 
128 
129 
130 void SWAP (float& a, float& b)
131 {
132  float zed = a;
133  a = b;
134  b = zed;
135 }
136 
137 
138 
139 // http://www.codeproject.com/Articles/9388/How-to-implement-the-FFT-algorithm
140 //data -> float array that represent the array of complex samples
141 //number_of_complex_samples -> number of samples (N^2 order number)
142 //isign -> 1 to calculate FFT and -1 to calculate Reverse FFT
143 void KKB::FFT (float data[],
144  kkuint32 number_of_complex_samples,
145  kkint32 isign
146  )
147 {
148  //variables for trigonometric recurrences
149  kkuint32 n = 0;
150  kkuint32 mmax = 0;
151  kkuint32 m = 0;
152  kkuint32 j = 0;
153  kkuint32 istep = 0;
154  kkuint32 i = 0;
155 
156  float wtemp = 0.0;
157  float wr = 0.0;
158  float wpr = 0.0;
159  float wpi = 0.0;
160  float wi = 0.0;
161  float theta = 0.0;
162  float tempr = 0.0;
163  float tempi = 0.0;
164 
165  /*
166  * The Bit-Reversal Method
167  *
168  * First, the original array must be transformed in order to perform the Danielson-Lanzcos
169  * algorithm. For example, the complex[index] will swap places with the
170  * complex[bit-reverse-order-index]. If the index (in binary) is 0b00001, the
171  * bit-reverse-order-index will be 0b10000. In figure 1, you can see what happens to the
172  * data array after the transformation.
173  *
174  * The implementation of this method according to Numerical Recipes In C goes like this:
175  */
176 
177  //the complex array is real+complex so the array
178  //as a size n = 2* number of complex samples
179  // real part is the data[index] and
180  //the complex part is the data[index+1]
181  n = number_of_complex_samples * 2;
182 
183  //binary inversion (note that the indexes
184  //start from 0 witch means that the
185  //real part of the complex is on the even-indexes
186  //and the complex part is on the odd-indexes
187  j = 0;
188  for (i = 0; i < n / 2; i += 2)
189  {
190  if (j > i)
191  {
192  //swap the real part
193  SWAP (data[j], data[i]);
194 
195  //swap the complex part
196  SWAP (data[j + 1],data[i + 1]);
197 
198  // checks if the changes occurs in the first half
199  // and use the mirrored effect on the second half
200  if ((j / 2) < (n / 4))
201  {
202  //swap the real part
203  SWAP (data[(n - (i + 2))], data[(n - (j + 2))]);
204  //swap the complex part
205  SWAP (data[(n - (i + 2)) + 1], data[(n - (j + 2)) + 1]);
206  }
207  }
208  m = n / 2;
209  while (m >= 2 && j >= m)
210  {
211  j -= m;
212  m = m / 2;
213  }
214  j += m;
215  }
216 
217  //Danielson-Lanzcos routine
218  mmax = 2;
219  //external loop
220  while (n > mmax)
221  {
222  istep = mmax << 1;
223  theta = isign * (2 * (float)PIE / mmax);
224  wtemp = sin (0.5f * theta);
225  wpr = -2.0f * wtemp * wtemp;
226  wpi = sin (theta);
227  wr = 1.0f;
228  wi = 0.0f;
229  //internal loops
230  for (m = 1; m < mmax; m += 2)
231  {
232  for (i = m; i <= n; i += istep)
233  {
234  j = i + mmax;
235  tempr = wr * data[j - 1] - wi * data[j];
236  tempi = wr * data[j] + wi * data[j - 1];
237  data[j - 1] = data[i - 1] - tempr;
238  data[j] = data[i] - tempi;
239  data[i - 1] += tempr;
240  data[i] += tempi;
241  }
242  wr = (wtemp = wr) * wpr - wi * wpi + wr;
243  wi = wi * wpr + wtemp * wpi + wi;
244  }
245  mmax = istep;
246  }
247 } /* FFT */
248 
249 
250 float KKB::Log2 (float x)
251 {
252  return log10 (x) / log10 (2.0f);
253 }
254 
255 
256 
257 
258 
259 volatile KKB::GoalKeeperPtr fftwGoalKeeper = NULL;
260 
261 #if defined(FFTW_AVAILABLE)
262 fftwf_plan KKB::fftwCreateTwoDPlan (kkint32 height,
263  kkint32 width,
264  fftwf_complex* src,
265  fftwf_complex* dest,
266  int sign,
267  int flag
268  )
269 {
270  if (!fftwGoalKeeper)
271  {
272  GoalKeeper::Create ("fftwGoalKeeper", fftwGoalKeeper);
273  }
274 
275  fftwGoalKeeper->StartBlock ();
276  fftwf_plan plan = fftwf_plan_dft_2d (height, width, src, dest, sign, flag);
277  fftwGoalKeeper->EndBlock ();
278  return plan;
279 }
280 
281 
282 
283 void KKB::fftwDestroyPlan (fftwf_plan& plan)
284 {
285  if (!fftwGoalKeeper)
286  GoalKeeper::Create ("fftwGoalKeeper", fftwGoalKeeper);
287 
288  fftwGoalKeeper->StartBlock ();
289  fftwf_destroy_plan (plan);
290  plan = NULL;
291  fftwGoalKeeper->EndBlock ();
292 }
293 
294 
295 
296 fftwf_plan KKB::fftwCreateOneDPlan (kkint32 len,
297  fftwf_complex* src,
298  fftwf_complex* dest,
299  int sign,
300  int flag
301  )
302 {
303  if (!fftwGoalKeeper)
304  GoalKeeper::Create ("fftwGoalKeeper", fftwGoalKeeper);
305 
306  fftwGoalKeeper->StartBlock ();
307  fftwf_plan plan = fftwf_plan_dft_1d (len, src, dest, sign, flag);
308  fftwGoalKeeper->EndBlock ();
309  return plan;
310 }
311 
312 #endif
#define PIE
Definition: KKBaseTypes.h:52
float Log2(float x)
Definition: kku_fftw.cpp:250
__int32 kkint32
Definition: KKBaseTypes.h:88
void SWAP(float &a, float &b)
Definition: kku_fftw.cpp:130
unsigned __int32 kkuint32
Definition: KKBaseTypes.h:89
volatile KKB::GoalKeeperPtr fftwGoalKeeper
Definition: kku_fftw.cpp:259
KKTHread * KKTHreadPtr
void FFT(float data[], kkuint32 number_of_complex_samples, kkint32 isign)
Definition: kku_fftw.cpp:143