iRoCS Toolbox  1.1.0
BlitzFFTW.hh
Go to the documentation of this file.
1 /**************************************************************************
2  *
3  * Copyright (C) 2010 Thorsten Falk, Mario Emmenlauer
4  *
5  * Image Analysis Lab, University of Freiburg, Germany
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  **************************************************************************/
22 
23 /**************************************************************************
24 ** Title: fftw Wrapper for fast fftw Calculation using blitz++ Arrays
25 ** $RCSfile$
26 ** $Revision: 4730 $$Name$
27 ** $Date: 2011-07-06 17:43:02 +0200 (Wed, 06 Jul 2011) $
28 ** Copyright: GPL $Author: tschmidt $
29 ** Description:
30 **
31 ** Wrapper for libfftw and libblitz++, providing arbitrary dimensional
32 ** fft's
33 **
34 **
35 **************************************************************************/
36 #ifndef BLITZFFTW_HH
37 #define BLITZFFTW_HH
38 
39 #ifdef HAVE_CONFIG_H
40 #include <config.hh>
41 #endif
42 
43 #include "BlitzFFTWError.hh"
44 #include <fftw3.h>
45 
46 #include <blitz/array.h>
47 
48 #ifdef HAVE_BLITZ_V9
49 #include <blitz/tinyvec-et.h>
50 #endif
51 
52 #include <set>
53 
54 typedef int BlitzIndexT;
55 
56 template <typename DataT>
58 {
59 };
60 template <>
61 struct BlitzFFTWPlan<double>
62 {
63 public:
64  typedef fftw_plan real_fftw_plan;
65 };
66 template <>
67 struct BlitzFFTWPlan<float>
68 {
69 public:
70  typedef fftwf_plan real_fftw_plan;
71 };
72 
73 
74 template<typename DataT>
75 class BlitzFFTW
76 {
77 public:
79 
80  enum PaddingType { VALUE, REPEATBORDER, MIRRORBORDER, CYCLICBORDER };
81  enum DataPreservePolicy { PRESERVE, OVERWRITE };
82 
83  /*======================================================================*/
106  /*======================================================================*/
107  static BlitzFFTW* instance();
108 
109  /*======================================================================*/
115  /*======================================================================*/
116  static void clear();
117 
118  /*======================================================================*/
124  /*======================================================================*/
125  void loadWisdom();
126 
127  /*======================================================================*/
136  /*======================================================================*/
137  void saveWisdom() const;
138 
139  /*======================================================================*/
156  /*======================================================================*/
157  template<int Dim, typename IndexT>
158  blitz::TinyVector<IndexT,Dim>
159  getPaddedShape(const blitz::TinyVector<IndexT,Dim>& minimumExtents) const;
160 
161  /*======================================================================*/
191  /*======================================================================*/
192  template<int Dim, typename IndexT>
193  void pad(const blitz::Array<DataT,Dim>& in,
194  blitz::Array<DataT,Dim>& out,
195  blitz::TinyVector<IndexT,Dim>& lb,
196  blitz::TinyVector<IndexT,Dim>& ub,
197  const blitz::TinyVector<IndexT,Dim>& minimumExtents = IndexT(0),
198  const PaddingType paddingMode = VALUE,
199  const DataT paddingValue = static_cast<DataT>(0)) const;
200 
201  /*======================================================================*/
232  /*======================================================================*/
233  template<int Dim, typename IndexT>
234  void pad(const blitz::Array<std::complex<DataT>,Dim>& in,
235  blitz::Array<std::complex<DataT>,Dim>& out,
236  blitz::TinyVector<IndexT,Dim>& lb,
237  blitz::TinyVector<IndexT,Dim>& ub,
238  const blitz::TinyVector<IndexT,Dim>& minimumExtents = IndexT(0),
239  const PaddingType paddingMode = VALUE,
240  const std::complex<DataT> paddingValue =
241  static_cast< std::complex<DataT> >(0)) const;
242 
243  /*======================================================================*/
258  /*======================================================================*/
259  template<int Dim, typename IndexT>
260  void unpad(const blitz::Array<DataT,Dim>& in,
261  blitz::Array<DataT,Dim>& out,
262  const blitz::TinyVector<IndexT,Dim>& lb,
263  const blitz::TinyVector<IndexT,Dim>& ub) const;
264 
265  /*======================================================================*/
280  /*======================================================================*/
281  template<int Dim, typename IndexT>
282  void unpad(const blitz::Array<std::complex<DataT>,Dim>& in,
283  blitz::Array<std::complex<DataT>,Dim>& out,
284  const blitz::TinyVector<IndexT,Dim>& lb,
285  const blitz::TinyVector<IndexT,Dim>& ub) const;
286 
287  /*======================================================================*/
317  /*======================================================================*/
318  template<int Dim>
319  void plan_forward(blitz::Array<DataT,Dim>& in,
320  blitz::Array<std::complex<DataT>,Dim>& out,
321  const DataPreservePolicy policy = PRESERVE,
322  const unsigned int plan_flags = FFTW_MEASURE) const;
323 
324  /*======================================================================*/
354  /*======================================================================*/
355  template<int Dim>
356  void plan_backward(blitz::Array<std::complex<DataT>,Dim>& in,
357  blitz::Array<DataT,Dim>& out,
358  const DataPreservePolicy policy = PRESERVE,
359  const unsigned int plan_flags = FFTW_MEASURE) const;
360 
361 
362  /*======================================================================*/
391  /*======================================================================*/
392  template<int Dim>
393  void plan_forward(blitz::Array<std::complex<DataT>,Dim>& in,
394  blitz::Array<std::complex<DataT>,Dim>& out,
395  const DataPreservePolicy policy = PRESERVE,
396  const unsigned int plan_flags = FFTW_MEASURE) const;
397 
398  /*---------------------------------------------------------------------
399  * same as plan_forward, but returns plan for further use with
400  * execute_plan (guru interface). Useful mainly for multithreading
401  *--------------------------------------------------------------------*/
402  template<int Dim>
403  blitz_fftw_plan
404  get_plan_forward(blitz::Array<DataT,Dim>& in,
405  blitz::Array<std::complex<DataT>,Dim>& out,
406  const DataPreservePolicy policy = PRESERVE,
407  const unsigned int plan_flags = FFTW_MEASURE) const;
408 
409  template<int Dim>
410  blitz_fftw_plan
411  get_plan_forward(blitz::Array<std::complex<DataT>,Dim>& in,
412  blitz::Array<std::complex<DataT>,Dim>& out,
413  const DataPreservePolicy policy = PRESERVE,
414  const unsigned int plan_flags = FFTW_MEASURE) const;
415 
416 
417  /*======================================================================*/
446  /*======================================================================*/
447  template<int Dim>
448  void plan_backward(blitz::Array<std::complex<DataT>,Dim>& in,
449  blitz::Array<std::complex<DataT>,Dim>& out,
450  const DataPreservePolicy policy = PRESERVE,
451  const unsigned int plan_flags = FFTW_MEASURE) const;
452 
453  /*---------------------------------------------------------------------
454  * same as plan_backward, but returns plan for further use with execute_plan
455  * (guru interface)
456  * useful mainly for multithreading :-)
457  *--------------------------------------------------------------------*/
458  template<int Dim>
459  blitz_fftw_plan
460  get_plan_backward(blitz::Array<std::complex<DataT>,Dim>& in,
461  blitz::Array<DataT,Dim>& out,
462  const DataPreservePolicy policy = PRESERVE,
463  const unsigned int plan_flags = FFTW_MEASURE) const;
464 
465  template<int Dim>
466  blitz_fftw_plan
467  get_plan_backward(blitz::Array<std::complex<DataT>,Dim>& in,
468  blitz::Array<std::complex<DataT>,Dim>& out,
469  const DataPreservePolicy policy = PRESERVE,
470  const unsigned int plan_flags = FFTW_MEASURE) const;
471 
472 
473  /*======================================================================*/
486  /*======================================================================*/
487  template<int Dim>
488  void forward(const blitz::Array<DataT,Dim>& in,
489  blitz::Array<std::complex<DataT>,Dim>& out) const;
490 
491  /*======================================================================*/
505  /*======================================================================*/
506  template<int Dim>
507  void forward(blitz::Array<std::complex<DataT>,Dim>& in,
508  blitz::Array<std::complex<DataT>,Dim>& out) const;
509 
510 
511 
512  /*======================================================================*/
525  /*======================================================================*/
526  template<int Dim>
527  void backward(blitz::Array<std::complex<DataT>,Dim>& in,
528  blitz::Array<DataT,Dim>& out,
529  const DataPreservePolicy policy = PRESERVE) const;
530 
531 
532  /*======================================================================*/
546  /*======================================================================*/
547  template<int Dim>
548  void backward(blitz::Array<std::complex<DataT>,Dim>& in,
549  blitz::Array<std::complex<DataT>,Dim>& out,
550  const DataPreservePolicy policy = PRESERVE) const;
551 
552  /*---------------------------------------------------------------------
553  * (guru interface) executes pre_computet plan with different data
554  * use get_plan_X to precompute plans.
555  * useful mainly for multithreading :-)
556  * THREAD SAVE!
557  *--------------------------------------------------------------------*/
558  template<int Dim>
559  void exec_guru_plan(blitz::Array<std::complex<DataT>,Dim>& in,
560  blitz::Array<std::complex<DataT>,Dim>& out,
561  blitz_fftw_plan plan,
562  const DataPreservePolicy policy = PRESERVE) const;
563 
564 
565  template<int Dim>
566  void exec_guru_plan_r2c(blitz::Array<DataT,Dim>& in,
567  blitz::Array<std::complex<DataT>,Dim>& out,
568  blitz_fftw_plan plan,
569  const DataPreservePolicy policy = PRESERVE) const;
570 
571  template<int Dim>
572  void exec_guru_plan_c2r(blitz::Array<std::complex<DataT>,Dim>& in,
573  blitz::Array<DataT,Dim>& out,
574  blitz_fftw_plan plan,
575  const DataPreservePolicy policy = PRESERVE) const;
576 
577 
578  /*======================================================================*/
587  /*======================================================================*/
588  template<int Dim>
589  void unShuffle(const blitz::Array<DataT,Dim>& in,
590  blitz::Array<DataT,Dim>& out) const;
591 
592 
593  /*======================================================================*/
601  /*======================================================================*/
602  static size_t nextBestFFTSize(const size_t size);
603  static size_t prevBestFFTSize(const size_t size);
604  static const std::set<size_t>& nextBestFFTSizes();
605 
606  template<int Dim>
607  void translate(const blitz::Array<DataT,Dim>& data,
608  blitz::Array<DataT,Dim>& dataTrans,
609  const BlitzIndexT t,
610  const int d) const;
611 
612  template<int Dim>
613  void translate(const blitz::Array<DataT,Dim>& data,
614  blitz::Array<DataT,Dim>& dataTrans,
615  const blitz::TinyVector<BlitzIndexT,Dim>& t) const;
616 
617 private:
618 
619  BlitzFFTW();
620  BlitzFFTW(const BlitzFFTW<DataT>& original);
621  ~BlitzFFTW();
622 
623  class BlitzFFTWDestructor
624  {
625  public:
626  ~BlitzFFTWDestructor()
627  {
628  if (BlitzFFTW::p_instance != 0) {
629  delete BlitzFFTW::p_instance;
630  BlitzFFTW::p_instance = 0;
631  }
632  }
633  void init()
634  {}
635  };
636  friend class BlitzFFTWDestructor;
637 
638  static const size_t maxPrepareFFTSize = 65535;
639  static void prepareFFTSizes();
640  static std::set<size_t> _bestFFTSizes;
641  static BlitzFFTW* p_instance;
642 
643 
644 
645  // These are the function pointers to the fftw library. They are needed
646  // because fftw has name mangeling depending on the datatype:
647  // fftwf for loat, fftw for double and fftwl for long double.
648  typedef DataT blitz_fftw_complex[2];
649 
650  void (*blitz_fftw_execute)(const blitz_fftw_plan p);
651  blitz_fftw_plan (*blitz_fftw_plan_dft)(int rank, const int *n, blitz_fftw_complex *in, blitz_fftw_complex *out, int sign, unsigned flags);
652  void (*blitz_fftw_execute_dft)(const blitz_fftw_plan p, blitz_fftw_complex *in, blitz_fftw_complex *out);
653  blitz_fftw_plan (*blitz_fftw_plan_dft_r2c)(int rank, const int *n, DataT *in, blitz_fftw_complex *out, unsigned flags);
654  blitz_fftw_plan (*blitz_fftw_plan_dft_c2r)(int rank, const int *n, blitz_fftw_complex *in, DataT *out, unsigned flags);
655  void (*blitz_fftw_execute_dft_r2c)(const blitz_fftw_plan p, DataT *in, blitz_fftw_complex *out);
656  void (*blitz_fftw_execute_dft_c2r)(const blitz_fftw_plan p, blitz_fftw_complex *in, DataT *out);
657  void (*blitz_fftw_destroy_plan)(blitz_fftw_plan p);
658  void (*blitz_fftw_cleanup)(void);
659  void *(*blitz_fftw_malloc)(size_t n);
660 
661 };
662 
663 // Template specializations
664 
665 template<>
668 
669 template<>
672 
673 #ifndef BLITZFFTW_HH_NO_INCLUDE_ICC
674 #include "BlitzFFTW.icc"
675 #endif
676 
677 #endif
678 
static BlitzFFTW * instance()
Get a handle to the Singleton BlitzFFTW Object.
fftwf_plan real_fftw_plan
Definition: BlitzFFTW.hh:70
DataPreservePolicy
Definition: BlitzFFTW.hh:81
int BlitzIndexT
Definition: BlitzFFTW.hh:54
BlitzFFTWPlan< DataT >::real_fftw_plan blitz_fftw_plan
Definition: BlitzFFTW.hh:78
fftw_plan real_fftw_plan
Definition: BlitzFFTW.hh:64