libsdr  0.1.0
A simple SDR library
fftplan_native.hh
1 #ifndef __SDR_FFTPLAN_NATIVE_HH__
2 #define __SDR_FFTPLAN_NATIVE_HH__
3 
4 #include "traits.hh"
5 #include "fftplan.hh"
6 
7 namespace sdr {
8 
10 template <class Scalar>
11 class FFTPlan
12 {
13 public:
16 
17 public:
19  FFTPlan(const Buffer< std::complex<Scalar> > &in, const Buffer< std::complex<Scalar> > &out,
20  FFT::Direction dir)
21  : _N(in.size()), _in(in), _out(out)
22  {
23  // Check dimensions
24  if (_in.size() != _out.size()) {
25  ConfigError err;
26  err << "Can not construct FFT plan: input & output buffers are of different size!";
27  throw err;
28  }
29  if (_in.isEmpty() || _out.isEmpty()) {
30  ConfigError err;
31  err << "Can not construct FFT plan: input or output buffer is empty!";
32  throw err;
33  }
34  // Check if N is power of two
35  if (_N != std::pow(2.0, std::log2(_N))) {
36  err << "Can not construct FFT plan: input and output buffer length must be a power of 2!";
37  throw err;
38  }
39 
40  // Assemble lookuptable
41  int dir_fac = (dir==FFT::FORWARD) ? 1 : -1;
42  for (size_t i=0; i<_N; i++) {
43  _lut[i] = (std::exp(std::complex<double>(0,(-2*M_PI*i*dir_fac)/N)) * (1<<Traits<Scalar>::shift));
44  }
45  }
46 
48  virtual ~FFTPlan() {
49  _lut.unref();
50  }
51 
53  void operator() () {
54  _calc(reinterpret_cast< std::complex<Scalar> >(_in.data()),
55  reinterpret_cast< std::complex<Scalar> >(_out.data()), _N, 1);
56  }
57 
58 protected:
60  void _calc(std::complex<Scalar> *a, std::complex<Scalar> *b, size_t N, size_t stride) {
61  // Recursion exit
62  if (1 == N) { b[0] = a[0]; return; }
63  // Calc FFT recursive
64  _calc(a, b, N/2, 2*stride);
65  _calc(a+stride, b+N/2, N/2, 2*stride);
66  // Radix-2...
67  for (size_t i=0; i<N/2; i++) {
68  std::complex<SScalar> tmp = b[i];
69  // I hope that the compiler will turn the (x/(1<<L)) into a (x >> L) if x is an integer...
70  b[i] = tmp + (_lut[i]*std::complex<SScalar>(b[i+N/2])) / (1<<Traits<Scalar>::shift);
71  b[i+N/2] = tmp - (_lut[i]*std::complex<SScalar>(b[i+N/2])) / (1<<Traits<Scalar>::shift);
72  }
73  }
74 
75 protected:
77  size_t _N;
84 };
85 
86 }
87 
88 #endif // __SDR_FFTPLAN_NATIVE_HH__
virtual ~FFTPlan()
Destructor.
Definition: fftplan_native.hh:48
void operator()()
Performs the FFT.
Definition: fftplan_native.hh:53
Direction
Direction type.
Definition: fftplan.hh:17
Definition: autocast.hh:8
bool isEmpty() const
Returns true if the buffer is invalid/empty.
Definition: buffer.hh:77
Buffer< std::complex< Scalar > > _in
The input buffer.
Definition: fftplan_native.hh:79
size_t size() const
Returns the number of elements of type T in this buffer.
Definition: buffer.hh:166
char * data() const
Returns the pointer to the data of the buffer view.
Definition: buffer.hh:69
Buffer< std::complex< Scalar > > _out
The output buffer.
Definition: fftplan_native.hh:81
void _calc(std::complex< Scalar > *a, std::complex< Scalar > *b, size_t N, size_t stride)
Actual FFT implmenetation.
Definition: fftplan_native.hh:60
Buffer< std::complex< SScalar > > _lut
The exp(-i 2 pi k / N) look-up table.
Definition: fftplan_native.hh:83
The configuration error class.
Definition: exception.hh:24
Traits< Scalar >::SScalar SScalar
The super-scalar of the input type.
Definition: fftplan_native.hh:15
void unref()
Dereferences the buffer.
Definition: buffer.cc:63
FFTPlan(const Buffer< std::complex< Scalar > > &in, const Buffer< std::complex< Scalar > > &out, FFT::Direction dir)
Constructs a FFT plan for the input and output buffers.
Definition: fftplan_native.hh:19
Forward declaration of type tratis template.
Definition: traits.hh:20
A typed buffer.
Definition: buffer.hh:111
size_t _N
FFT size, needs to be a power of 2.
Definition: fftplan_native.hh:77