Chris@366
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@366
|
2
|
Chris@366
|
3 #include "dsp/FFT.h"
|
Chris@366
|
4
|
Chris@366
|
5 #define BOOST_TEST_DYN_LINK
|
Chris@366
|
6 #define BOOST_TEST_MAIN
|
Chris@366
|
7
|
Chris@366
|
8 #include <boost/test/unit_test.hpp>
|
Chris@366
|
9
|
Chris@366
|
10 #include <stdexcept>
|
Chris@366
|
11
|
Chris@366
|
12 BOOST_AUTO_TEST_SUITE(TestFFT)
|
Chris@366
|
13
|
Chris@366
|
14 #define COMPARE_CONST(a, n) \
|
Chris@366
|
15 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
Chris@366
|
16 BOOST_CHECK_SMALL(a[cmp_i] - n, 1e-14); \
|
Chris@366
|
17 }
|
Chris@366
|
18
|
Chris@366
|
19 #define COMPARE_ARRAY(a, b) \
|
Chris@366
|
20 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
Chris@366
|
21 BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14); \
|
Chris@366
|
22 }
|
Chris@366
|
23
|
Chris@366
|
24 //!!! need at least one test with complex time-domain signal
|
Chris@366
|
25
|
Chris@366
|
26 BOOST_AUTO_TEST_CASE(forwardArrayBounds)
|
Chris@366
|
27 {
|
Chris@366
|
28 // initialise bins to something recognisable, so we can tell if
|
Chris@366
|
29 // they haven't been written; and allocate the inputs on the heap
|
Chris@366
|
30 // so that, if running under valgrind, we get warnings about
|
Chris@366
|
31 // overruns
|
Chris@366
|
32 double *in = new double[4];
|
Chris@366
|
33 in[0] = 1;
|
Chris@366
|
34 in[1] = 1;
|
Chris@366
|
35 in[2] = -1;
|
Chris@366
|
36 in[3] = -1;
|
Chris@366
|
37 double re[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
38 double im[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
39 FFT(4).process(false, in, 0, re+1, im+1);
|
Chris@366
|
40 // And check we haven't overrun the arrays
|
Chris@366
|
41 BOOST_CHECK_EQUAL(re[0], 999.0);
|
Chris@366
|
42 BOOST_CHECK_EQUAL(im[0], 999.0);
|
Chris@366
|
43 BOOST_CHECK_EQUAL(re[5], 999.0);
|
Chris@366
|
44 BOOST_CHECK_EQUAL(im[5], 999.0);
|
Chris@366
|
45 delete[] in;
|
Chris@366
|
46 }
|
Chris@366
|
47
|
Chris@366
|
48 BOOST_AUTO_TEST_CASE(r_forwardArrayBounds)
|
Chris@366
|
49 {
|
Chris@366
|
50 // initialise bins to something recognisable, so we can tell if
|
Chris@366
|
51 // they haven't been written; and allocate the inputs on the heap
|
Chris@366
|
52 // so that, if running under valgrind, we get warnings about
|
Chris@366
|
53 // overruns
|
Chris@366
|
54 double *in = new double[4];
|
Chris@366
|
55 in[0] = 1;
|
Chris@366
|
56 in[1] = 1;
|
Chris@366
|
57 in[2] = -1;
|
Chris@366
|
58 in[3] = -1;
|
Chris@366
|
59 double re[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
60 double im[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
61 FFTReal(4).forward(in, re+1, im+1);
|
Chris@366
|
62 // And check we haven't overrun the arrays
|
Chris@366
|
63 BOOST_CHECK_EQUAL(re[0], 999.0);
|
Chris@366
|
64 BOOST_CHECK_EQUAL(im[0], 999.0);
|
Chris@366
|
65 BOOST_CHECK_EQUAL(re[5], 999.0);
|
Chris@366
|
66 BOOST_CHECK_EQUAL(im[5], 999.0);
|
Chris@366
|
67 delete[] in;
|
Chris@366
|
68 }
|
Chris@366
|
69
|
Chris@366
|
70 BOOST_AUTO_TEST_CASE(inverseArrayBounds)
|
Chris@366
|
71 {
|
Chris@366
|
72 // initialise bins to something recognisable, so we can tell if
|
Chris@366
|
73 // they haven't been written; and allocate the inputs on the heap
|
Chris@366
|
74 // so that, if running under valgrind, we get warnings about
|
Chris@366
|
75 // overruns
|
Chris@366
|
76 double *re = new double[4];
|
Chris@366
|
77 double *im = new double[4];
|
Chris@366
|
78 re[0] = 0;
|
Chris@366
|
79 re[1] = 1;
|
Chris@366
|
80 re[2] = 0;
|
Chris@366
|
81 re[3] = 1;
|
Chris@366
|
82 im[0] = 0;
|
Chris@366
|
83 im[1] = -2;
|
Chris@366
|
84 im[2] = 0;
|
Chris@366
|
85 im[3] = 2;
|
Chris@366
|
86 double outre[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
87 double outim[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
88 FFT(4).process(true, re, im, outre+1, outim+1);
|
Chris@366
|
89 // And check we haven't overrun the arrays
|
Chris@366
|
90 BOOST_CHECK_EQUAL(outre[0], 999.0);
|
Chris@366
|
91 BOOST_CHECK_EQUAL(outim[0], 999.0);
|
Chris@366
|
92 BOOST_CHECK_EQUAL(outre[5], 999.0);
|
Chris@366
|
93 BOOST_CHECK_EQUAL(outim[5], 999.0);
|
Chris@366
|
94 delete[] re;
|
Chris@366
|
95 delete[] im;
|
Chris@366
|
96 }
|
Chris@366
|
97
|
Chris@366
|
98 BOOST_AUTO_TEST_CASE(r_inverseArrayBounds)
|
Chris@366
|
99 {
|
Chris@366
|
100 // initialise bins to something recognisable, so we can tell if
|
Chris@366
|
101 // they haven't been written; and allocate the inputs on the heap
|
Chris@366
|
102 // so that, if running under valgrind, we get warnings about
|
Chris@366
|
103 // overruns
|
Chris@366
|
104 double *re = new double[3];
|
Chris@366
|
105 double *im = new double[3];
|
Chris@366
|
106 re[0] = 0;
|
Chris@366
|
107 re[1] = 1;
|
Chris@366
|
108 re[2] = 0;
|
Chris@366
|
109 im[0] = 0;
|
Chris@366
|
110 im[1] = -2;
|
Chris@366
|
111 im[2] = 0;
|
Chris@366
|
112 double outre[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
113 FFTReal(4).inverse(re, im, outre+1);
|
Chris@366
|
114 // And check we haven't overrun the arrays
|
Chris@366
|
115 BOOST_CHECK_EQUAL(outre[0], 999.0);
|
Chris@366
|
116 BOOST_CHECK_EQUAL(outre[5], 999.0);
|
Chris@366
|
117 delete[] re;
|
Chris@366
|
118 delete[] im;
|
Chris@366
|
119 }
|
Chris@366
|
120
|
Chris@366
|
121 BOOST_AUTO_TEST_CASE(dc)
|
Chris@366
|
122 {
|
Chris@366
|
123 // DC-only signal. The DC bin is purely real
|
Chris@366
|
124 double in[] = { 1, 1, 1, 1 };
|
Chris@366
|
125 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
126 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
127 FFT(4).process(false, in, 0, re, im);
|
Chris@366
|
128 BOOST_CHECK_EQUAL(re[0], 4.0);
|
Chris@366
|
129 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@366
|
130 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
131 BOOST_CHECK_EQUAL(re[3], 0.0);
|
Chris@366
|
132 COMPARE_CONST(im, 0.0);
|
Chris@366
|
133 double back[4];
|
Chris@366
|
134 double backim[4];
|
Chris@366
|
135 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
136 COMPARE_ARRAY(back, in);
|
Chris@366
|
137 COMPARE_CONST(backim, 0.0);
|
Chris@366
|
138 }
|
Chris@366
|
139
|
Chris@366
|
140 BOOST_AUTO_TEST_CASE(r_dc)
|
Chris@366
|
141 {
|
Chris@366
|
142 // DC-only signal. The DC bin is purely real
|
Chris@366
|
143 double in[] = { 1, 1, 1, 1 };
|
Chris@366
|
144 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
145 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
146 FFTReal(4).forward(in, re, im);
|
Chris@366
|
147 BOOST_CHECK_EQUAL(re[0], 4.0);
|
Chris@366
|
148 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@366
|
149 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
150 BOOST_CHECK_EQUAL(re[3], 0.0);
|
Chris@366
|
151 COMPARE_CONST(im, 0.0);
|
Chris@366
|
152 double back[4];
|
Chris@366
|
153 // check conjugates are reconstructed
|
Chris@366
|
154 re[3] = 999;
|
Chris@366
|
155 im[3] = 999;
|
Chris@366
|
156 FFTReal(4).inverse(re, im, back);
|
Chris@366
|
157 COMPARE_ARRAY(back, in);
|
Chris@366
|
158 }
|
Chris@366
|
159
|
Chris@366
|
160 BOOST_AUTO_TEST_CASE(c_dc)
|
Chris@366
|
161 {
|
Chris@366
|
162 // DC-only signal. The DC bin is purely real
|
Chris@366
|
163 double rin[] = { 1, 1, 1, 1 };
|
Chris@366
|
164 double iin[] = { 1, 1, 1, 1 };
|
Chris@366
|
165 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
166 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
167 FFT(4).process(false, rin, iin, re, im);
|
Chris@366
|
168 BOOST_CHECK_EQUAL(re[0], 4.0);
|
Chris@366
|
169 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@366
|
170 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
171 BOOST_CHECK_EQUAL(re[3], 0.0);
|
Chris@366
|
172 BOOST_CHECK_EQUAL(im[0], 4.0);
|
Chris@366
|
173 BOOST_CHECK_EQUAL(im[1], 0.0);
|
Chris@366
|
174 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@366
|
175 BOOST_CHECK_EQUAL(im[3], 0.0);
|
Chris@366
|
176 double back[4];
|
Chris@366
|
177 double backim[4];
|
Chris@366
|
178 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
179 COMPARE_ARRAY(back, rin);
|
Chris@366
|
180 COMPARE_ARRAY(backim, iin);
|
Chris@366
|
181 }
|
Chris@366
|
182
|
Chris@366
|
183 BOOST_AUTO_TEST_CASE(sine)
|
Chris@366
|
184 {
|
Chris@366
|
185 // Sine. Output is purely imaginary
|
Chris@366
|
186 double in[] = { 0, 1, 0, -1 };
|
Chris@366
|
187 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
188 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
189 FFT(4).process(false, in, 0, re, im);
|
Chris@366
|
190 COMPARE_CONST(re, 0.0);
|
Chris@366
|
191 BOOST_CHECK_EQUAL(im[0], 0.0);
|
Chris@366
|
192 BOOST_CHECK_EQUAL(im[1], -2.0);
|
Chris@366
|
193 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@366
|
194 BOOST_CHECK_EQUAL(im[3], 2.0);
|
Chris@366
|
195 double back[4];
|
Chris@366
|
196 double backim[4];
|
Chris@366
|
197 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
198 COMPARE_ARRAY(back, in);
|
Chris@366
|
199 COMPARE_CONST(backim, 0.0);
|
Chris@366
|
200 }
|
Chris@366
|
201
|
Chris@366
|
202 BOOST_AUTO_TEST_CASE(r_sine)
|
Chris@366
|
203 {
|
Chris@366
|
204 // Sine. Output is purely imaginary
|
Chris@366
|
205 double in[] = { 0, 1, 0, -1 };
|
Chris@366
|
206 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
207 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
208 FFTReal(4).forward(in, re, im);
|
Chris@366
|
209 COMPARE_CONST(re, 0.0);
|
Chris@366
|
210 BOOST_CHECK_EQUAL(im[0], 0.0);
|
Chris@366
|
211 BOOST_CHECK_EQUAL(im[1], -2.0);
|
Chris@366
|
212 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@366
|
213 BOOST_CHECK_EQUAL(im[3], 2.0);
|
Chris@366
|
214 double back[4];
|
Chris@366
|
215 // check conjugates are reconstructed
|
Chris@366
|
216 re[3] = 999;
|
Chris@366
|
217 im[3] = 999;
|
Chris@366
|
218 FFTReal(4).inverse(re, im, back);
|
Chris@366
|
219 COMPARE_ARRAY(back, in);
|
Chris@366
|
220 }
|
Chris@366
|
221
|
Chris@366
|
222 BOOST_AUTO_TEST_CASE(cosine)
|
Chris@366
|
223 {
|
Chris@366
|
224 // Cosine. Output is purely real
|
Chris@366
|
225 double in[] = { 1, 0, -1, 0 };
|
Chris@366
|
226 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
227 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
228 FFT(4).process(false, in, 0, re, im);
|
Chris@366
|
229 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
230 BOOST_CHECK_EQUAL(re[1], 2.0);
|
Chris@366
|
231 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
232 BOOST_CHECK_EQUAL(re[3], 2.0);
|
Chris@366
|
233 COMPARE_CONST(im, 0.0);
|
Chris@366
|
234 double back[4];
|
Chris@366
|
235 double backim[4];
|
Chris@366
|
236 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
237 COMPARE_ARRAY(back, in);
|
Chris@366
|
238 COMPARE_CONST(backim, 0.0);
|
Chris@366
|
239 }
|
Chris@366
|
240
|
Chris@366
|
241 BOOST_AUTO_TEST_CASE(r_cosine)
|
Chris@366
|
242 {
|
Chris@366
|
243 // Cosine. Output is purely real
|
Chris@366
|
244 double in[] = { 1, 0, -1, 0 };
|
Chris@366
|
245 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
246 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
247 FFTReal(4).forward(in, re, im);
|
Chris@366
|
248 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
249 BOOST_CHECK_EQUAL(re[1], 2.0);
|
Chris@366
|
250 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
251 BOOST_CHECK_EQUAL(re[3], 2.0);
|
Chris@366
|
252 COMPARE_CONST(im, 0.0);
|
Chris@366
|
253 double back[4];
|
Chris@366
|
254 // check conjugates are reconstructed
|
Chris@366
|
255 re[3] = 999;
|
Chris@366
|
256 im[3] = 999;
|
Chris@366
|
257 FFTReal(4).inverse(re, im, back);
|
Chris@366
|
258 COMPARE_ARRAY(back, in);
|
Chris@366
|
259 }
|
Chris@366
|
260
|
Chris@366
|
261 BOOST_AUTO_TEST_CASE(c_cosine)
|
Chris@366
|
262 {
|
Chris@366
|
263 // Cosine. Output is purely real
|
Chris@366
|
264 double rin[] = { 1, 0, -1, 0 };
|
Chris@366
|
265 double iin[] = { 1, 0, -1, 0 };
|
Chris@366
|
266 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
267 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
268 FFT(4).process(false, rin, iin, re, im);
|
Chris@366
|
269 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
270 BOOST_CHECK_EQUAL(re[1], 2.0);
|
Chris@366
|
271 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
272 BOOST_CHECK_EQUAL(re[3], 2.0);
|
Chris@366
|
273 BOOST_CHECK_EQUAL(im[0], 0.0);
|
Chris@366
|
274 BOOST_CHECK_EQUAL(im[1], 2.0);
|
Chris@366
|
275 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@366
|
276 BOOST_CHECK_EQUAL(im[3], 2.0);
|
Chris@366
|
277 double back[4];
|
Chris@366
|
278 double backim[4];
|
Chris@366
|
279 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
280 COMPARE_ARRAY(back, rin);
|
Chris@366
|
281 COMPARE_ARRAY(backim, iin);
|
Chris@366
|
282 }
|
Chris@366
|
283
|
Chris@366
|
284 BOOST_AUTO_TEST_CASE(sineCosine)
|
Chris@366
|
285 {
|
Chris@366
|
286 // Sine and cosine mixed
|
Chris@366
|
287 double in[] = { 0.5, 1, -0.5, -1 };
|
Chris@366
|
288 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
289 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
290 FFT(4).process(false, in, 0, re, im);
|
Chris@366
|
291 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
292 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
|
Chris@366
|
293 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
294 BOOST_CHECK_CLOSE(re[3], 1.0, 1e-12);
|
Chris@366
|
295 BOOST_CHECK_EQUAL(im[0], 0.0);
|
Chris@366
|
296 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
|
Chris@366
|
297 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@366
|
298 BOOST_CHECK_CLOSE(im[3], 2.0, 1e-12);
|
Chris@366
|
299 double back[4];
|
Chris@366
|
300 double backim[4];
|
Chris@366
|
301 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
302 COMPARE_ARRAY(back, in);
|
Chris@366
|
303 COMPARE_CONST(backim, 0.0);
|
Chris@366
|
304 }
|
Chris@366
|
305
|
Chris@366
|
306 BOOST_AUTO_TEST_CASE(r_sineCosine)
|
Chris@366
|
307 {
|
Chris@366
|
308 // Sine and cosine mixed
|
Chris@366
|
309 double in[] = { 0.5, 1, -0.5, -1 };
|
Chris@366
|
310 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
311 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
312 FFTReal(4).forward(in, re, im);
|
Chris@366
|
313 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
314 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
|
Chris@366
|
315 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
316 BOOST_CHECK_CLOSE(re[3], 1.0, 1e-12);
|
Chris@366
|
317 BOOST_CHECK_EQUAL(im[0], 0.0);
|
Chris@366
|
318 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
|
Chris@366
|
319 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@366
|
320 BOOST_CHECK_CLOSE(im[3], 2.0, 1e-12);
|
Chris@366
|
321 double back[4];
|
Chris@366
|
322 // check conjugates are reconstructed
|
Chris@366
|
323 re[3] = 999;
|
Chris@366
|
324 im[3] = 999;
|
Chris@366
|
325 FFTReal(4).inverse(re, im, back);
|
Chris@366
|
326 COMPARE_ARRAY(back, in);
|
Chris@366
|
327 }
|
Chris@366
|
328
|
Chris@366
|
329 BOOST_AUTO_TEST_CASE(c_sineCosine)
|
Chris@366
|
330 {
|
Chris@366
|
331 double rin[] = { 1, 0, -1, 0 };
|
Chris@366
|
332 double iin[] = { 0, 1, 0, -1 };
|
Chris@366
|
333 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
334 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
335 FFT(4).process(false, rin, iin, re, im);
|
Chris@366
|
336 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
337 BOOST_CHECK_EQUAL(re[1], 4.0);
|
Chris@366
|
338 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
339 BOOST_CHECK_EQUAL(re[3], 0.0);
|
Chris@366
|
340 COMPARE_CONST(im, 0.0);
|
Chris@366
|
341 double back[4];
|
Chris@366
|
342 double backim[4];
|
Chris@366
|
343 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
344 COMPARE_ARRAY(back, rin);
|
Chris@366
|
345 COMPARE_ARRAY(backim, iin);
|
Chris@366
|
346 }
|
Chris@366
|
347
|
Chris@366
|
348 BOOST_AUTO_TEST_CASE(nyquist)
|
Chris@366
|
349 {
|
Chris@366
|
350 double in[] = { 1, -1, 1, -1 };
|
Chris@366
|
351 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
352 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
353 FFT(4).process(false, in, 0, re, im);
|
Chris@366
|
354 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
355 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@366
|
356 BOOST_CHECK_EQUAL(re[2], 4.0);
|
Chris@366
|
357 BOOST_CHECK_EQUAL(re[3], 0.0);
|
Chris@366
|
358 COMPARE_CONST(im, 0.0);
|
Chris@366
|
359 double back[4];
|
Chris@366
|
360 double backim[4];
|
Chris@366
|
361 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
362 COMPARE_ARRAY(back, in);
|
Chris@366
|
363 COMPARE_CONST(backim, 0.0);
|
Chris@366
|
364 }
|
Chris@366
|
365
|
Chris@366
|
366 BOOST_AUTO_TEST_CASE(r_nyquist)
|
Chris@366
|
367 {
|
Chris@366
|
368 double in[] = { 1, -1, 1, -1 };
|
Chris@366
|
369 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
370 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
371 FFTReal(4).forward(in, re, im);
|
Chris@366
|
372 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@366
|
373 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@366
|
374 BOOST_CHECK_EQUAL(re[2], 4.0);
|
Chris@366
|
375 BOOST_CHECK_EQUAL(re[3], 0.0);
|
Chris@366
|
376 COMPARE_CONST(im, 0.0);
|
Chris@366
|
377 double back[4];
|
Chris@366
|
378 // check conjugates are reconstructed
|
Chris@366
|
379 re[3] = 999;
|
Chris@366
|
380 im[3] = 999;
|
Chris@366
|
381 FFTReal(4).inverse(re, im, back);
|
Chris@366
|
382 COMPARE_ARRAY(back, in);
|
Chris@366
|
383 }
|
Chris@366
|
384
|
Chris@366
|
385 BOOST_AUTO_TEST_CASE(dirac)
|
Chris@366
|
386 {
|
Chris@366
|
387 double in[] = { 1, 0, 0, 0 };
|
Chris@366
|
388 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
389 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
390 FFT(4).process(false, in, 0, re, im);
|
Chris@366
|
391 BOOST_CHECK_EQUAL(re[0], 1.0);
|
Chris@366
|
392 BOOST_CHECK_EQUAL(re[1], 1.0);
|
Chris@366
|
393 BOOST_CHECK_EQUAL(re[2], 1.0);
|
Chris@366
|
394 BOOST_CHECK_EQUAL(re[3], 1.0);
|
Chris@366
|
395 COMPARE_CONST(im, 0.0);
|
Chris@366
|
396 double back[4];
|
Chris@366
|
397 double backim[4];
|
Chris@366
|
398 FFT(4).process(true, re, im, back, backim);
|
Chris@366
|
399 COMPARE_ARRAY(back, in);
|
Chris@366
|
400 COMPARE_CONST(backim, 0.0);
|
Chris@366
|
401 }
|
Chris@366
|
402
|
Chris@366
|
403 BOOST_AUTO_TEST_CASE(r_dirac)
|
Chris@366
|
404 {
|
Chris@366
|
405 double in[] = { 1, 0, 0, 0 };
|
Chris@366
|
406 double re[] = { 999, 999, 999, 999 };
|
Chris@366
|
407 double im[] = { 999, 999, 999, 999 };
|
Chris@366
|
408 FFTReal(4).forward(in, re, im);
|
Chris@366
|
409 BOOST_CHECK_EQUAL(re[0], 1.0);
|
Chris@366
|
410 BOOST_CHECK_EQUAL(re[1], 1.0);
|
Chris@366
|
411 BOOST_CHECK_EQUAL(re[2], 1.0);
|
Chris@366
|
412 BOOST_CHECK_EQUAL(re[3], 1.0);
|
Chris@366
|
413 COMPARE_CONST(im, 0.0);
|
Chris@366
|
414 double back[4];
|
Chris@366
|
415 // check conjugates are reconstructed
|
Chris@366
|
416 re[3] = 999;
|
Chris@366
|
417 im[3] = 999;
|
Chris@366
|
418 FFTReal(4).inverse(re, im, back);
|
Chris@366
|
419 COMPARE_ARRAY(back, in);
|
Chris@366
|
420 }
|
Chris@366
|
421
|
Chris@366
|
422 BOOST_AUTO_TEST_CASE(sizes)
|
Chris@366
|
423 {
|
Chris@366
|
424 // Complex supports any size. A single test with an odd size
|
Chris@366
|
425 // will do here, without getting too much into our expectations
|
Chris@366
|
426 // about supported butterflies etc
|
Chris@366
|
427
|
Chris@366
|
428 double in[] = { 1, 1, 1 };
|
Chris@366
|
429 double re[] = { 999, 999, 999 };
|
Chris@366
|
430 double im[] = { 999, 999, 999 };
|
Chris@366
|
431 FFT(3).process(false, in, 0, re, im);
|
Chris@366
|
432 BOOST_CHECK_EQUAL(re[0], 3.0);
|
Chris@366
|
433 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@366
|
434 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
435 COMPARE_CONST(im, 0.0);
|
Chris@366
|
436 double back[3];
|
Chris@366
|
437 double backim[3];
|
Chris@366
|
438 FFT(3).process(true, re, im, back, backim);
|
Chris@366
|
439 COMPARE_ARRAY(back, in);
|
Chris@366
|
440 COMPARE_CONST(backim, 0.0);
|
Chris@366
|
441 }
|
Chris@366
|
442
|
Chris@366
|
443 BOOST_AUTO_TEST_CASE(r_sizes)
|
Chris@366
|
444 {
|
Chris@366
|
445 // Real supports any even size, but not odd ones
|
Chris@366
|
446
|
Chris@366
|
447 BOOST_CHECK_THROW(FFTReal r(3), std::invalid_argument);
|
Chris@366
|
448
|
Chris@366
|
449 double in[] = { 1, 1, 1, 1, 1, 1 };
|
Chris@366
|
450 double re[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
451 double im[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@366
|
452 FFTReal(6).forward(in, re, im);
|
Chris@366
|
453 BOOST_CHECK_EQUAL(re[0], 6.0);
|
Chris@366
|
454 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@366
|
455 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@366
|
456 BOOST_CHECK_EQUAL(re[3], 0.0);
|
Chris@366
|
457 BOOST_CHECK_EQUAL(re[4], 0.0);
|
Chris@366
|
458 BOOST_CHECK_EQUAL(re[5], 0.0);
|
Chris@366
|
459 COMPARE_CONST(im, 0.0);
|
Chris@366
|
460 double back[6];
|
Chris@366
|
461 FFTReal(6).inverse(re, im, back);
|
Chris@366
|
462 COMPARE_ARRAY(back, in);
|
Chris@366
|
463 }
|
Chris@366
|
464
|
Chris@366
|
465 BOOST_AUTO_TEST_SUITE_END()
|
Chris@366
|
466
|