JASPL  0.2
Just Another Signal Processing Library
jfft.tpp
1 template < typename T >
2 JFFT<T>::JFFT( bool use_threading ) : threading( use_threading ) {
3  static_assert( is_stdlib_container<T>::value, "JFFT::Input must be a container-like object.");
4 }
5 
6 template < typename T >
7 JFFT<T>::~JFFT() {
8  TearDown();
9 }
10 
11 template < typename T >
12 void JFFT<T>::SetUp( uint size ) {
13 
14  if( set_up ) {
15  return;
16  }
17 
18  set_up = true;
19 
20  N = size;
21  fft_size = ( size%2 == 0 )?( size / 2 ):( ( size - 1 ) / 2 );
22 
23  norm_factor = static_cast< typename T::value_type >( N );
24 
25  //Setup multi-threading
26  if ( threading ) {
27 
28  int val = fftwf_init_threads();
29 
30  //if val is equal to zero multithreading cannot be setup
31  if( val == 0 ) {
32  std::string err_mesg = __func__;
33  err_mesg += "Could not setup multithreading.";
34  throw std::runtime_error(err_mesg);
35  }
36  //set plans to use what OpenMP has decided is a good number of
37  //threads (usually the number of processor cores)
38  fftwf_plan_with_nthreads(omp_get_max_threads());
39 
40  }
41 
42  if( in != NULL ) {
43  fftwf_free( in );
44  std::string err_mesg = __func__;
45  err_mesg += "Could not allocate memory for FFT input buffer.";
46  throw std::runtime_error(err_mesg);
47  }
48 
49  in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * N);
50 
51  if( out != NULL ) {
52  fftwf_free( out );
53  std::string err_mesg = __func__;
54  err_mesg += "Could not allocate memory for FFT output buffer.";
55  throw std::runtime_error(err_mesg);
56  }
57 
58  out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * N);
59 
60  fftwf_make_planner_thread_safe();
61  p = fftwf_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
62 
63 }
64 
65 template < typename T >
66 void JFFT<T>::TearDown() {
67 
68  fftwf_destroy_plan(p);
69 
70  fftwf_free(in);
71  fftwf_free(out);
72 }
73 
74 inline double abs_sqr( const fftwf_complex& z ) {
75  return z[0]*z[0] + z[1]*z[1];
76 }
77 
78 template < typename T >
79 T JFFT<T>::PowerSpectrum( const T& input ) {
80 
81  if( set_up == false ) {
82  std::string err_mesg = __func__;
83  err_mesg += "JFFT has not been set-up properly --";
84  err_mesg += " you must call JFFT::SetUp( uint size ) first.";
85  throw std::runtime_error(err_mesg);
86  }
87 
88  // get upgradable access
89  boost::upgrade_lock<boost::shared_mutex> lock( monitor );
90  // get exclusive access
91  boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
92 
93  std::cout << "N " << N << std::endl;
94 
95  for ( uint i = 0; i < N ; i++ ) {
96  in[i][0] = input.at(i); //Real Part
97  in[i][1] = 0.0; //Imaginary part
98  }
99 
100  fftwf_execute( p );
101 
102  T output;
103  output.reserve( fft_size );
104 
105  auto N_sqr = norm_factor * norm_factor;
106 
107  // Explicitly compute first element
108  auto C_0 = abs_sqr( out[0] );
109  C_0 /= N_sqr;
110 
111  output.push_back( C_0 );
112 
113  for ( uint i = 1; i < fft_size - 1; i++ ) {
114 
115  auto C_i = abs_sqr( out[i] ) + abs_sqr( out[N-i] );;
116  C_i /= N_sqr;
117 
118  output.push_back( C_i );
119 
120  }
121 
122  // Explicitly compute last element
123  auto C_N_half = abs_sqr( out[ fft_size - 1 ] );
124  C_N_half /= N_sqr;
125 
126  output.push_back( C_N_half );
127 
128  return output;
129 
130 }