mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
fftT_test.cpp
Go to the documentation of this file.
1/** \file fftT_test.cpp
2 * \brief Tests CPU FFT transforms.
3 */
4#include "../../../catch2/catch.hpp"
5
6#define MX_NO_ERROR_REPORTS
7
8#include <iostream>
9
12
13/// 1D FFT with FFTW
14/**
15 * \ingroup fftT_unit_tests
16 */
17TEST_CASE( "1D c2c FFT with FFTW, float", "[math::ft]" )
18{
19 srand( 1 );
20
21 SECTION( "out-of-place, forward, default constructed, raw interface" )
22 {
23 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft;
24
25 fft.plan( 1024 );
26
27 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
28 in.setRandom();
29
30 fft( out.data(), in.data() );
31
32 float sin = in.abs2().sum();
33 float sout = out.abs2().sum() / out.rows();
34
35 // Test by Parsevals
36 REQUIRE_THAT( sin, Catch::Matchers::WithinRel( sout, 5e-6f ) );
37 }
38
39 SECTION( "out-of-place, forward, default constructed, eigen interface" )
40 {
41 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft;
42
43 fft.plan( 1024 );
44
45 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
46 in.setRandom();
47
48 fft( out, in );
49
50 float sin = in.abs2().sum();
51 float sout = out.abs2().sum() / out.rows();
52
53 // Test by Parsevals
54 REQUIRE_THAT( sin, Catch::Matchers::WithinRel( sout, 5e-6f ) );
55 }
56
57 SECTION( "out-of-place, forward, plan constructor" )
58 {
59 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024 );
60
61 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
62 in.setRandom();
63
64 fft( out, in );
65
66 float sin = in.abs2().sum();
67 float sout = out.abs2().sum() / out.rows();
68
69 // Test by Parsevals
70 REQUIRE_THAT( sin, Catch::Matchers::WithinRel( sout, 5e-6f ) );
71 }
72
73 SECTION( "out-of-place, backward" )
74 {
75 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024, mx::math::ft::dir::backward );
76
77 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
78 out.setRandom();
79
80 fft( in, out );
81
82 float sin = in.abs2().sum() / in.rows();
83 float sout = out.abs2().sum();
84
85 // Test by Parsevals
86 REQUIRE_THAT( sin, Catch::Matchers::WithinRel( sout, 5e-6f ) );
87 }
88
89 SECTION( "in-place, forward" )
90 {
91 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024, mx::math::ft::dir::forward, true );
92
94 in.setRandom();
96 float sin = in.abs2().sum();
97
98 fft( in, in );
99
100 float sout = in.abs2().sum() / in.rows();
101
102 float rmsdiff = ( in - incheck ).abs2().sum();
103
104 // Make sure it isn't ident
105 REQUIRE( rmsdiff > 0 );
106
107 // Test by Parsevals
108 REQUIRE_THAT( sin, Catch::Matchers::WithinRel( sout, 5e-6f ) );
109 }
110
111 SECTION( "in-place, backward" )
112 {
113 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024, mx::math::ft::dir::backward, true );
114
116 in.setRandom();
117
119
120 float sin = in.abs2().sum();
121
122 fft( in, in );
123
124 float sout = in.abs2().sum() / in.rows();
125
126 float rmsdiff = ( in - incheck ).abs2().sum();
127
128 // Make sure it isn't ident
129 REQUIRE( rmsdiff > 0 );
130
131 // Test by Parsevals
132 REQUIRE_THAT( sin, Catch::Matchers::WithinRel( sout, 5e-6f ) );
133 }
134}
135
136/// 2D FFT with FFTW
137/**
138 * \ingroup fftT_unit_tests
139 */
140TEST_CASE( "2D c2c FFT with FFTW, float", "[math::ft]" )
141{
142 srand( 1 );
143
144 SECTION( "out-of-place, forward, default constructed, raw interface" )
145 {
146 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft;
147
148 fft.plan( 128, 128 );
149
150 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
151 in.setRandom();
152
153 fft( out.data(), in.data() );
154
155 float sin = in.abs2().sum() * ( out.rows() * out.cols() );
156 float sout = out.abs2().sum();
157
158 // Test by Parsevals
159 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
160 }
161
162 SECTION( "out-of-place, forward, default constructed, eigen interface" )
163 {
164 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft;
165
166 fft.plan( 128, 128 );
167
168 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
169 in.setRandom();
170
171 fft( out, in );
172
173 float sin = in.abs2().sum();
174 float sout = out.abs2().sum() / ( out.rows() * out.cols() );
175
176 // Test by Parsevals
177 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
178 }
179
180 SECTION( "out-of-place, forward, plan constructor" )
181 {
182 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft( 128, 128 );
183
184 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
185 ;
186 in.setRandom();
187
188 fft( out, in );
189
190 float sin = in.abs2().sum();
191 float sout = out.abs2().sum() / ( in.rows() * out.cols() );
192
193 // Test by Parsevals
194 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
195 }
196
197 SECTION( "out-of-place, backward" )
198 {
199 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft( 128, 128, mx::math::ft::dir::backward );
200
201 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
202 out.setRandom();
203
204 fft( in, out );
205
206 float sin = in.abs2().sum() / ( in.rows() * in.cols() );
207 float sout = out.abs2().sum();
208
209 // Test by Parsevals
210 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
211 }
212
213 SECTION( "in-place, forward" )
214 {
215 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft( 128,
216 128,
218 true );
219
221 in.setRandom();
223 float sin = in.abs2().sum();
224
225 fft( in, in );
226
227 float sout = in.abs2().sum() / ( in.rows() * in.cols() );
228
229 float rmsdiff = ( in - incheck ).abs2().sum();
230
231 // Make sure it isn't ident
232 REQUIRE( rmsdiff > 0 );
233
234 // Test by Parsevals
235 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
236 }
237
238 SECTION( "in-place, backward" )
239 {
240 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft( 128,
241 128,
243 true );
244
246 in.setRandom();
247
249
250 float sin = in.abs2().sum();
251
252 fft( in, in );
253
254 float sout = in.abs2().sum() / ( in.rows() * in.cols() );
255
256 float rmsdiff = ( in - incheck ).abs2().sum();
257
258 // Make sure it isn't ident
259 REQUIRE( rmsdiff > 0 );
260
261 // Test by Parsevals
262 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
263 }
264}
265#ifdef HASQUAD
266
267SECTION( "quad" )
268{
269}
270
271#endif // HASQUD
Tools for using the eigen library for image processing.
The Fast Fourier Transform interface.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
TEST_CASE("1D c2c FFT with FFTW, float", "[math::ft]")
1D FFT with FFTW
Definition fftT_test.cpp:17
@ backward
Specifies the backward transform.
Definition ftTypes.hpp:42
@ forward
Specifies the forward transform.
Definition ftTypes.hpp:41