KSquare Utilities
kku_fftw.h
Go to the documentation of this file.
1 /* kku_fftw.cpp -- Implements a Fast Fourier transform via a template.
2  * Copyright (C) 2012-2014 Kurt Kramer
3  * For conditions of distribution and use, see copyright notice in KKB.h
4  */
5 #ifndef _KKU_FFTW_
6 #define _KKU_FFTW_
7 
8 #include <math.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <complex>
12 
13 #if defined(FFTW_AVAILABLE)
14 #include <fftw3.h>
15 #endif
16 
17 #include "KKBaseTypes.h"
18 
19 
20 namespace KKB
21 {
22  /*********************************************
23  * Complex numbers and operations
24  *********************************************/
25 
26  /*
27  typedef struct
28  {
29  double re;
30  double im;
31  } fftw_complex;
32 
33 
34  // flags for the planner
35  #define FFTW_ESTIMATE (0)
36  #define FFTW_MEASURE (1)
37 
38  typedef enum {FFTW_FORWARD = -1, FFTW_BACKWARD = 1} fftw_direction;
39 
40 
41  class fftw_plan_class
42  {
43  public:
44  fftw_plan_class (kkint32 _n,
45  fftw_direction _dir,
46  kkint32 _flags
47  );
48 
49  fftw_direction Dir () const {return dir;}
50  kkint32 Flags () const {return flags;}
51  kkint32 N () const {return n;}
52 
53 
54  private:
55  kkint32 n;
56  fftw_direction dir;
57  kkint32 flags;
58  }; // fftw_plan_class
59 
60 
61  class fftwnd_plan_class
62  {
63  public:
64  fftwnd_plan_class (kkint32 nx,
65  kkint32 ny,
66  fftw_direction dir,
67  kkint32 flags
68  );
69 
70  fftw_direction Dir () const {return dir;}
71  kkint32 Flags () const {return flags;}
72  kkint32 NX () const {return nx;}
73  kkint32 NY () const {return ny;}
74 
75  private:
76  kkint32 nx;
77  kkint32 ny;
78  fftw_direction dir;
79  kkint32 flags;
80  }; // fftwnd_plan_class
81 
82 
83  typedef fftw_plan_class* fftw_plan;
84  typedef fftwnd_plan_class* fftwnd_plan;
85 
86 
87  fftw_plan fftw_create_plan (kkint32 n,
88  fftw_direction dir,
89  kkint32 flags
90  );
91 
92  fftwnd_plan fftw2d_create_plan (kkint32 nx,
93  kkint32 ny,
94  fftw_direction dir,
95  kkint32 flags
96  );
97 
98  void fftw_destroy_plan (fftw_plan plan);
99 
100  void fftwnd_destroy_plan (fftwnd_plan plan);
101 
102 
103  void fftw_one (fftw_plan plan,
104  fftw_complex* in,
105  fftw_complex* out
106  );
107 
108 
109  void fftwnd_one (fftwnd_plan p,
110  fftw_complex* in,
111  fftw_complex* out
112  );
113  */
114 
115 
116  void FFT (float data[],
117  kkuint32 number_of_complex_samples,
118  kkint32 isign
119  );
120 
121  float Log2 (float x);
122 
123 
124 
125 
126  template<typename DftType>
127  class KK_DFT1D
128  {
129  public:
130  typedef std::complex<DftType> DftComplexType;
131 
132  KK_DFT1D (kkint32 _size,
133  bool _forwardTransform
134  );
135 
136  ~KK_DFT1D ();
137 
138 
139  void Transform (DftComplexType* src,
140  DftComplexType* dest
141  );
142 
143  void Transform (KKB::uchar* src,
144  DftComplexType* dest
145  );
146 
147  void TransformNR (DftComplexType* src);
148 
149 
151  {
152  if (!fourierMask)
153  BuildMask ();
154  return fourierMask;
155  }
156 
157  private:
158  void BuildMask ();
159 
160  DftComplexType MinusOne;
161  DftComplexType One;
162  DftComplexType Pi;
163  DftComplexType Two;
164  DftComplexType Zero;
165 
166  bool forwardTransform;
167  DftComplexType** fourierMask;
168  DftComplexType* fourierMaskArea;
169  kkint32 size;
170  }; /* KK_DFT1D */
171 
172  typedef KK_DFT1D<float> KK_DFT1D_Float;
173  typedef KK_DFT1D<double> KK_DFT1D_Double;
174 
175 
176 
177  template<typename DftType>
178  class KK_DFT2D
179  {
180  public:
181  typedef std::complex<DftType> DftComplexType;
182 
183  KK_DFT2D (kkint32 _height,
184  kkint32 _width,
185  bool _forwardTransform
186  );
187 
188  ~KK_DFT2D ();
189 
190  void Transform (DftComplexType** src,
191  DftComplexType** dest
192  );
193 
194  void Transform (KKB::uchar** src,
195  DftComplexType** dest
196  );
197 
198  void Transform2 (KKB::uchar** src,
199  DftComplexType** dest
200  );
201 
202  void AllocateArray (DftComplexType* &arrayArea,
203  DftComplexType** &array
204  ) const;
205 
206  void DestroyArray (DftComplexType* &arrayArea,
207  DftComplexType** &array
208  ) const;
209 
210  private:
211  kkint32 height;
212  kkint32 width;
213  bool forwardTransform;
214 
215  DftComplexType Zero;
216  DftComplexType** workArray;
217  DftComplexType* workArrayArea;
218  DftComplexType* workCol;
219 
220  KK_DFT1D<DftType>* rowDFT;
221  KK_DFT1D<DftType>* colDFT;
222  }; /* KK_DFT2D */
223 
224  typedef KK_DFT2D<float> KK_DFT2D_Float;
225  typedef KK_DFT2D<double> KK_DFT2D_Double;
226 
227 
228 
229  template<typename DftType>
230  KK_DFT1D<DftType>::KK_DFT1D (kkint32 _size,
231  bool _forwardTransform
232  ):
233  MinusOne ((DftType)-1.0, (DftType)0.0),
234  One ((DftType)1.0, (DftType)0.0),
235  Pi ((DftType)3.14159265359, (DftType)0.0),
236  Two ((DftType)2.0, (DftType)0.0),
237  Zero ((DftType)0.0, (DftType)0.0),
239  fourierMask (NULL),
240  fourierMaskArea (NULL),
241  size (_size)
242  {
243  //BuildMask ();
244  }
245 
246 
247  template<typename DftType>
248  KK_DFT1D<DftType>::~KK_DFT1D ()
249  {
250  delete fourierMask; fourierMask = NULL;
251  delete fourierMaskArea; fourierMaskArea = NULL;
252  }
253 
254 
255  template<typename DftType>
256  void KK_DFT1D<DftType>::BuildMask ()
257  {
260 
261  kkint32 x;
262 
264  if (forwardTransform)
265  direction = DftComplexType ((DftType)-1.0, (DftType)0.0);
266  else
267  direction = DftComplexType ((DftType)1.0, (DftType)0.0);
268 
272  for (x = 0; x < size; x++)
273  {
276  }
277 
279  j = sqrt (MinusOne);
280 
281  for (kkint32 m = 0; m < size; m++)
282  {
284 
285  for (kkint32 k = 0; k < size; k++)
286  {
288  fourierMask[m][k] = exp (direction * j * Two * Pi * kc * mc / M);
289  }
290  }
291 
292  return;
293  } /* BuildMask */
294 
295 
296 
297  template<typename DftType>
298  void KK_DFT1D<DftType>::Transform (DftComplexType* src,
299  DftComplexType* dest
300  )
301  {
303 
305  if (forwardTransform)
306  direction = DftComplexType ((DftType)-1.0, (DftType)0.0);
307  else
308  direction = DftComplexType ((DftType)1.0, (DftType)0.0);
309 
311  j = sqrt (MinusOne);
312 
313 
314  for (kkint32 l = 0; l < size; l++)
315  {
316  dest[l] = Zero;
317 
319  for (kkint32 k = 0; k < size; k++)
320  {
321  //DftType exponetPart = (DftType)2.0 * (DftType)3.14159265359 * (DftType)k * (DftType)l / (DftType)size;
322  //DftType realPart = cos (exponetPart);
323  //DftType imgPart = -sin (exponetPart);
324 
326  DftComplexType fm = exp (direction * j * Two * Pi * kc * lc / M);
327 
328  //dest[l] = dest[l] + src[k] * fourierMask[l][k];
329  dest[l] = dest[l] + src[k] * fm;
330  }
331  }
332 
333  /*
334  {
335  // Performs a comparison with a alternatve result that performs much faster but is only good for
336  // where size is = (n^2) for (n > 0)
337  kkint32 newSize = (kkint32)pow (2.0f, (float)ceil (Log2 ((float)size)));
338 
339  // Lets do a comparison
340  int x, y;
341  float* wa = new float[newSize * 2];
342  for (x = 0; x < (newSize * 2); ++x)
343  wa[x] = 0.0;
344 
345  for (x = 0, y = 0; x < size; ++x, y += 2)
346  {
347  wa[y] = src[x].real ();
348  wa[y + 1] = src[x].imag ();
349  }
350  FFT (wa, size, 1);
351 
352  for (x = 0, y = 0; x < size; ++x, y += 2)
353  {
354  float deltaR = (wa[y] - dest[x].real ());
355  float deltaI = (wa[y + 1] - dest[x].imag ());
356 
357  //if (deltaR != 0.0)
358  // cout << x << "\t" << wa[y] << "\t" << dest[x].real () << "\t" << deltaR << endl;
359 
360  //if (deltaI != 0.0)
361  // cout << x << "\t" << wa[y + 1] << "\t" << dest[x].imag () << "\t" << deltaI << endl;
362 
363  float waSquare = wa[y] * wa[y] + wa[y + 1] * wa[y + 1];
364  float destSquare = dest[x].real () * dest[x].real () + dest[x].imag () * dest[x].imag ();
365 
366  float waMag = sqrt (waSquare);
367  float destMag = sqrt (destSquare);
368 
369  cout << x << "\t" << waMag << "\t" << destMag << endl;
370  }
371  delete wa;
372  wa = NULL;
373  }
374  */
375 
376  return;
377  } /* Transform */
378 
379 
380 
381  template<typename DftType>
382  void KK_DFT1D<DftType>::Transform (KKB::uchar* src,
383  DftComplexType* dest
384  )
385  {
386  if (!fourierMask)
387  BuildMask ();
388 
389  kkint32 firstK = 0;
390  bool firstKFound = false;
391  kkint32 lastK = 0;
392 
393  for (kkint32 k = 0; k < size; ++k)
394  {
395  if (src[k] != 0)
396  {
397  lastK = k;
398  if (!firstKFound)
399  {
400  firstKFound = true;
401  firstK = k;
402  }
403  }
404  }
405 
406  for (kkint32 l = 0; l < size; l++)
407  {
409 
410  DftType destReal = 0.0;
411  DftType destImag = 0.0;
412 
413  for (kkint32 k = firstK; k <= lastK; k++)
414  {
415  destReal += src[k] * fourierMaskL[k].real ();
416  destImag += src[k] * fourierMaskL[k].imag ();
417  }
418 
420  }
421  return;
422  } /* Transform */
423 
424 
425 
426 
427  template<typename DftType>
428  void KK_DFT1D<DftType>::TransformNR (DftComplexType* src)
429  {
430  kkint32 n = 0;
431  kkint32 mmax = 0;
432  kkint32 m = 0;
433  kkint32 j = 0;
434  kkint32 istep = 0;
435  kkint32 i = 0;
436  kkint32 isign = (forwardTransform ? 1 : -1);
437 
438  DftType wtemp = (DftType)0.0;
439  DftType wr = (DftType)0.0;
440  DftType wpr = (DftType)0.0;
441  DftType wpi = (DftType)0.0;
442  DftType wi = (DftType)0.0;
443  DftType theta = (DftType)0.0;
444  DftType tempr = (DftType)0.0;
445  DftType tempi = (DftType)0.0;
446 
447  kkint32 nn = this->size;
448  n = nn << 1;
449  j = 1;
450  for (i = 1; i < nn; ++i)
451  {
452  if (j > i)
453  {
454  Swap (src[j].imag, src[i].imag);
455  Swap (src[j].real, src[i].real);
456  }
457 
458  m = nn;
459  while ((m >= 2) && (j > m))
460  {
461  j -= m;
462  m >>= 1;
463  }
464  j += m;
465  }
466 
467  mmax = 2;
468  while (n > mmax)
469  {
470  istep = mmax << 1;
471  theta = isign * (TwoPie / mmax);
472  wtemp = sin (0.5 * theta);
473  wpr = -2.0 * wtemp * wtemp;
474  wpi = sin (theta);
475  wr = 1.0;
476  wi = 0.0;
477  for (m = 1; m < mmax; m += 2)
478  {
479  j = i + mmax;
480 
481  }
482  }
483  } /* TransformNR */
484 
485 
486 
487  template<typename DftType>
488  KK_DFT2D<DftType>::KK_DFT2D (kkint32 _height,
489  kkint32 _width,
490  bool _forwardTransform
491  ):
492  height (_height),
493  width (_width),
495  rowDFT (NULL),
496  colDFT (NULL),
497  workArray (NULL),
498  workArrayArea (NULL),
499  workCol (NULL),
500  Zero ((DftType)0.0, (DftType)0.0)
501  {
504 
508  for (kkint32 row = 0; row < height; ++row)
509  {
512  }
514  }
515 
516 
517  template<typename DftType>
518  KK_DFT2D<DftType>::~KK_DFT2D ()
519  {
520  delete rowDFT; rowDFT = NULL;
521  delete colDFT; colDFT = NULL;
522  delete workArray; workArray = NULL;
523  delete workArrayArea; workArrayArea = NULL;
524  delete workCol; workCol = NULL;
525  }
526 
527 
528 
529  template<typename DftType>
530  void KK_DFT2D<DftType>::Transform (DftComplexType** src,
531  DftComplexType** dest
532  )
533  {
534  for (kkint32 row = 0; row < height; ++row)
536 
538 
539  for (kkint32 col = 0; col < width; ++col)
540  {
541  for (kkint32 row = 0; row < height; row++)
542  {
544  for (kkint32 k = 0; k < height; k++)
545  {
546  v = v + workArray[k][col] * colFourierMask[row][k];
547  }
548 
549  dest[row][col] = v;
550  }
551  }
552 
553  } /* Transform*/
554 
555 
556  template<typename DftType>
557  void KK_DFT2D<DftType>::Transform (KKB::uchar** src,
558  DftComplexType** dest
559  )
560  {
561  for (kkint32 row = 0; row < height; ++row)
563 
565 
566  for (kkint32 col = 0; col < width; ++col)
567  {
568  kkuint32 firstRow = 0;
569  bool firstRowFound = false;
570  kkuint32 lastRow = 0;
571 
572  for (kkint32 l = 0; l < height; ++l)
573  {
574  workCol[l] = workArray[l][col];
575  bool nonZero = (workCol[l].imag () != 0.0f) || (workCol[l].real () != 0.0f);
576  if (nonZero)
577  {
578  lastRow = l;
579  if (!firstRowFound)
580  {
581  firstRowFound = true;
582  firstRow = l;
583  }
584  }
585  }
586 
587  for (kkint32 row = 0; row < height; row++)
588  {
590 
592  for (kkuint32 k = firstRow; k <= lastRow; k++)
593  {
594  v = v + workCol[k] * colFourierMaskRow[k];
595  }
596 
597  dest[row][col] = v;
598  }
599  }
600  } /* Transform */
601 
602 
603 
604 
605 
606  template<typename DftType>
607  void KK_DFT2D<DftType>::AllocateArray (DftComplexType* &arrayArea,
608  DftComplexType** &array
609  ) const
610  {
612  array = NULL;
614  if (!arrayArea)
615  return;
616 
617  array = new DftComplexType*[height];
619 
620  for (kkint32 row = 0; row < height; ++row)
621  {
622  array[row] = rowPtr;
623  rowPtr = rowPtr + width;
624  }
625 
626  for (kkint32 x = 0; x < total; ++x)
627  {
628  arrayArea[x].real ((DftType)0.0);
629  arrayArea[x].imag ((DftType)0.0);
630  }
631 
632  return;
633  } /* AllocateArray */
634 
635 
636 
637 
638 
639  template<typename DftType>
640  void KK_DFT2D<DftType>::DestroyArray (DftComplexType* &arrayArea,
641  DftComplexType** &array
642  ) const
643  {
644  delete arrayArea; arrayArea = NULL;
645  delete array; array = NULL;
646  return;
647  } /* DestroyArray */
648 
649 
650 
651 
652 
653 #if !defined(FFTW_AVAILABLE)
654 #endif
655 
656 
657 
658 #if defined(FFTW_AVAILABLE)
660  kkint32 width,
663  int sign,
664  int flag
665  );
666 
670  int sign,
671  int flag
672  );
673 
675 #endif
676 
677 } /* KKB */
678 
679 
680 
681 
682 
683 
684 #endif /* _KKU_FFTW_ */
void Transform(DftComplexType *src, DftComplexType *dest)
Definition: kku_fftw.h:298
void AllocateArray(DftComplexType *&arrayArea, DftComplexType **&array) const
Definition: kku_fftw.h:607
float Log2(float x)
Definition: kku_fftw.cpp:250
KK_DFT2D< double > KK_DFT2D_Double
Definition: kku_fftw.h:225
void Transform(DftComplexType **src, DftComplexType **dest)
Definition: kku_fftw.h:530
__int32 kkint32
Definition: KKBaseTypes.h:88
std::complex< DftType > DftComplexType
Definition: kku_fftw.h:130
unsigned __int32 kkuint32
Definition: KKBaseTypes.h:89
void Transform2(KKB::uchar **src, DftComplexType **dest)
KK_DFT2D< float > KK_DFT2D_Float
Definition: kku_fftw.h:224
DftComplexType ** FourierMask()
Definition: kku_fftw.h:150
std::complex< DftType > DftComplexType
Definition: kku_fftw.h:181
KK_DFT1D< double > KK_DFT1D_Double
Definition: kku_fftw.h:173
KKTHread * KKTHreadPtr
void TransformNR(DftComplexType *src)
Definition: kku_fftw.h:428
KK_DFT1D< float > KK_DFT1D_Float
Definition: kku_fftw.h:172
KK_DFT2D(kkint32 _height, kkint32 _width, bool _forwardTransform)
Definition: kku_fftw.h:488
void Transform(KKB::uchar *src, DftComplexType *dest)
Definition: kku_fftw.h:382
unsigned char uchar
Unsigned character.
Definition: KKBaseTypes.h:77
#define TwoPie
Definition: KKBaseTypes.h:53
void Transform(KKB::uchar **src, DftComplexType **dest)
Definition: kku_fftw.h:557
void FFT(float data[], kkuint32 number_of_complex_samples, kkint32 isign)
Definition: kku_fftw.cpp:143
KK_DFT1D(kkint32 _size, bool _forwardTransform)
Definition: kku_fftw.h:230
void DestroyArray(DftComplexType *&arrayArea, DftComplexType **&array) const
Definition: kku_fftw.h:640