API Documentation
Loading...
Searching...
No Matches
FFT.h
Go to the documentation of this file.
1#pragma once
2#include <NDEVR/Buffer.h>
3#include <NDEVR/Angle.h>
4#include <iostream>
5#include <iomanip>
6#include <complex>
7
8namespace NDEVR
9{
10 /**--------------------------------------------------------------------------------------------------
11 \brief Logic for implenting Fast Fourier Transform, a mathematical algorithm that converts signals
12 from the time domain to the frequency domain.
13 **/
14 template<class t_type>
16 {
17 protected:
18 // Fast Fourier Transform
19 static void fft(Buffer<std::complex<t_type>>& in_out, Buffer<std::complex<t_type>>& temp, uint04 offset, uint04 size)
20 {
21 // base case
22 if (size == 1)
23 return;
24 if (size % 2 != 0)// Fallback to Basic Discrete Fourier Transform
25 {
26 for (uint04 k = 0; k < size; k++)
27 temp[k + offset] = in_out[k + offset];
28 dft(temp.begin(offset), in_out.begin(offset), size, 1);
29 return;
30 }
31 lib_assert(size % 2 == 0, "Bad FFT");
32
33 uint04 even_offset = offset;
34 uint04 odd_offset = offset + size / 2;
35
36 // compute FFT of even terms
37 for (uint04 k = 0; k < size / 2; k++)
38 temp[k + even_offset] = in_out[2 * k + offset];
39
40 // compute FFT of odd terms
41 for (uint04 k = 0; k < size / 2; k++)
42 temp[k + odd_offset] = in_out[2 * k + 1 + offset];
43
44 fft(temp, in_out, even_offset, size / 2);
45 fft(temp, in_out, odd_offset, size / 2);
46
47 // combine
48 for (uint04 k = 0; k < size / 2; k++)
49 {
50 fltp08 kth = -2.0 * cast<fltp08>(k) * PI<fltp08>() / size;
51 std::complex<t_type> wk(std::cos(kth), std::sin(kth));
52 in_out[k + even_offset] = temp[k + even_offset] + (wk * temp[k + odd_offset]);
53 in_out[k + odd_offset] = temp[k + even_offset] - (wk * temp[k + odd_offset]);
54 }
55 }
56 // Basic Discrete Fourier Transform
57 static void dft(const std::complex<t_type> f[], std::complex<t_type> ftilde[], uint04 N, uint04 step)
58 {
59 std::complex<t_type> w = std::polar(1.0, -2.0 * PI<t_type>() / N);
60 std::complex<t_type> wn = 1.0;
61 for (uint04 n = 0; n < N; n++)
62 {
63 if (n > 0) wn *= w;
64 std::complex<t_type> wm = 1.0;
65 ftilde[n] = 0.0;
66 for (uint04 m = 0, mpos = 0; m < N; m++, mpos += step)
67 {
68 if (m > 0) wm *= wn;
69 ftilde[n] += f[mpos] * wm;
70 }
71 }
72 }
73
74 // compute the inverse FFT of x[], assuming its length n is a power of 2
75 static void ifft(Buffer<std::complex<t_type>>& in_out, Buffer<std::complex<t_type>>& temp, uint04 offset, uint04 size)
76 {
77 // take conjugate
78 for (uint04 i = 0; i < size; i++)
79 in_out[i + offset] = std::conj(in_out[i + offset]);
80
81 // compute forward FFT
82 fft(in_out, temp, offset, size);
83
84 // take conjugate again
85 t_type factor = 1.0 / size;
86 for (uint04 i = 0; i < size; i++)
87 in_out[i + offset] = std::conj(in_out[i + offset]) * factor;
88
89 }
90
91
92
93 //======================================================================
94
95 static void iFFT(const std::complex<t_type> ftilde[], std::complex<t_type> f[], uint04 N) // Inverse Fast Fourier Transform
96 {
97 Buffer<std::complex<t_type>> ftildeConjugate;
98 ftildeConjugate.setSize(N);
99
100 for (uint04 m = 0; m < N; m++)
101 ftildeConjugate[m] = std::conj(ftilde[m]);
102
103 fft(ftildeConjugate, f, N, 1);
104
105 t_type factor = 1.0 / N;
106 for (uint04 m = 0; m < N; m++)
107 f[m] = std::conj(f[m]) * factor;
108
109 }
110 public:
111 static void FT(Buffer<std::complex<t_type>>& in_out)
112 {
114 temp.setSize(in_out.size());
115 fft(in_out, temp, 0, temp.size());
116 }
117 static void IFT(Buffer<std::complex<t_type>>& in_out)
118 {
120 temp.setSize(in_out.size());
121 ifft(in_out, temp, 0, temp.size());
122 }
123 };
124
125 /*static Buffer<std::complex<t_type>> fft(const Buffer<std::complex<t_type>>& f) // Fast Fourier Transform
126 {
127 // base case
128 if (f.size() == 1)
129 {
130 return { f[0] };
131 }
132 lib_assert(f.size() % 2 == 0, "Bad FFT");
133
134 Buffer<std::complex<t_type>> buffer;
135 buffer.setSize(f.size() / 2);
136 // compute FFT of even terms
137 for (uint04 k = 0; k < f.size() / 2; k++)
138 buffer[k] = f[2 * k];
139 Buffer<std::complex<t_type>> even_fft = fft(buffer);
140
141 // compute FFT of odd terms
142 for (uint04 k = 0; k < f.size() / 2; k++)
143 buffer[k] = f[2 * k + 1];
144 Buffer<std::complex<t_type>> odd_fft = fft(buffer);
145
146 // combine
147 Buffer<std::complex<t_type>> y;
148 y.setSize(f.size());
149 for (uint04 k = 0; k < f.size() / 2; k++)
150 {
151 fltp08 kth = -2.0 * cast<fltp08>(k) * Angle::PI<fltp08>() / f.size();
152 std::complex<t_type> wk(std::cos(kth), std::sin(kth));
153 y[k ] = even_fft[k] + (wk * odd_fft[k]);
154 y[k + f.size() / 2] = even_fft[k] - (wk * odd_fft[k]);
155 }
156 return y;
157 }
158
159 // compute the inverse FFT of x[], assuming its length n is a power of 2
160 static Buffer<std::complex<t_type>> ifft(const Buffer<std::complex<t_type>>& x)
161 {
162 Buffer<std::complex<t_type>> y;
163 y.setSize(x.size());
164
165 // take conjugate
166 for (uint04 i = 0; i < x.size(); i++)
167 y[i] = std::conj(x[i]);
168
169 // compute forward FFT
170 y = fft(y);
171
172 // take conjugate again
173 t_type factor = 1.0 / x.size();
174 for (uint04 i = 0; i < x.size(); i++)
175 y[i] = std::conj(y[i]) * factor;
176 return y;
177
178 }
179
180 //======================================================================
181
182 static void DFT(const std::complex<t_type> f[], std::complex<t_type> ftilde[], uint04 N, uint04 step) // Basic Discrete Fourier Transform
183 {
184 std::complex<t_type> w = std::polar(1.0, -2.0 * Angle::PI<t_type>() / N);
185 std::complex<t_type> wn = 1.0;
186 for (uint04 n = 0; n < N; n++)
187 {
188 if (n > 0) wn *= w;
189 std::complex<t_type> wm = 1.0;
190 ftilde[n] = 0.0;
191 for (uint04 m = 0, mpos = 0; m < N; m++, mpos += step)
192 {
193 if (m > 0) wm *= wn;
194 ftilde[n] += f[mpos] * wm;
195 }
196 }
197 }
198
199 //======================================================================
200
201 static void iFFT(const std::complex<t_type> ftilde[], std::complex<t_type> f[], uint04 N) // Inverse Fast Fourier Transform
202 {
203 Buffer<std::complex<t_type>> ftildeConjugate;
204 ftildeConjugate.setSize(N);
205
206 for (uint04 m = 0; m < N; m++)
207 ftildeConjugate[m] = std::conj(ftilde[m]);
208
209 FFT(ftildeConjugate, f, N, 1);
210
211 t_type factor = 1.0 / N;
212 for (uint04 m = 0; m < N; m++)
213 f[m] = std::conj(f[m]) * factor;
214
215 }
216 public:
217 static Buffer<std::complex<t_type>> FFT(const Buffer<std::complex<t_type>>& complex, uint04 step = 1)
218 {
219 Buffer<std::complex<t_type>> output;
220 output.setSize(complex.size());
221 FFT(complex.ptr(), output.ptr(), complex.size(), step);
222 return output;
223 }
224 static Buffer<std::complex<t_type>> IFFT(const Buffer<std::complex<t_type>>& complex)
225 {
226 return ifft(complex);
227 }
228 };*/
229}
#define lib_assert(expression, message)
Definition LibAssert.h:61
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:56
constexpr t_index_type size() const
Definition Buffer.hpp:823
void setSize(t_index_type new_size)
Definition Buffer.hpp:803
Logic for implenting Fast Fourier Transform, a mathematical algorithm that converts signals from the ...
Definition FFT.h:16
static void iFFT(const std::complex< t_type > ftilde[], std::complex< t_type > f[], uint04 N)
Definition FFT.h:95
static void fft(Buffer< std::complex< t_type > > &in_out, Buffer< std::complex< t_type > > &temp, uint04 offset, uint04 size)
Definition FFT.h:19
static void IFT(Buffer< std::complex< t_type > > &in_out)
Definition FFT.h:117
static void dft(const std::complex< t_type > f[], std::complex< t_type > ftilde[], uint04 N, uint04 step)
Definition FFT.h:57
static void ifft(Buffer< std::complex< t_type > > &in_out, Buffer< std::complex< t_type > > &temp, uint04 offset, uint04 size)
Definition FFT.h:75
static void FT(Buffer< std::complex< t_type > > &in_out)
Definition FFT.h:111
Definition ACIColor.h:37
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:375
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149