mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
fftTcuda_test.cpp
Go to the documentation of this file.
1/** \file fftTcuda_test.cpp
2 * \brief Tests CUDA FFT transforms.
3 */
4#include "../../../catch2/catch.hpp"
5#include "../../../cudaTestUtils.hpp"
6
7#define MX_NO_ERROR_REPORTS
8
9#include <iostream>
10
13
14#if 0
15/// 1D FFT with FFTW
16/**
17 * \ingroup fftT_unit_tests
18 */
19TEST_CASE( "1D c2c FFT with FFTW, float", "[math::ft]" )
20{
21
22 srand( time( 0 ) );
23
24 SECTION( "out-of-place, forward, default constructed, raw interface" )
25 {
26 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft;
27
28 fft.plan( 1024 );
29
30 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
31 in.setRandom();
32
33 fft( out.data(), in.data() );
34
35 float sin = in.abs2().sum();
36 float sout = out.abs2().sum() / out.rows();
37
38 // Test by Parsevals
39 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, 1e-3 ) );
40 }
41
42 SECTION( "out-of-place, forward, default constructed, eigen interface" )
43 {
44 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft;
45
46 fft.plan( 1024 );
47
48 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
49 in.setRandom();
50
51 fft( out, in );
52
53 float sin = in.abs2().sum();
54 float sout = out.abs2().sum() / out.rows();
55
56 // Test by Parsevals
57 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, 1e-3 ) );
58 }
59
60 SECTION( "out-of-place, forward, plan constructor" )
61 {
62 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024 );
63
64 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
65 in.setRandom();
66
67 fft( out, in );
68
69 float sin = in.abs2().sum();
70 float sout = out.abs2().sum() / out.rows();
71
72 // Test by Parsevals
73 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, 1e-3 ) );
74 }
75
76 SECTION( "out-of-place, backward" )
77 {
78 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024, mx::math::ft::dir::backward );
79
80 mx::improc::eigenImage<std::complex<float>> in( 1024, 1 ), out( 1024, 1 );
81 out.setRandom();
82
83 fft( in, out );
84
85 float sin = in.abs2().sum() / in.rows();
86 float sout = out.abs2().sum();
87
88 // Test by Parsevals
89 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, 1e-3 ) );
90 }
91
92 SECTION( "in-place, forward" )
93 {
94 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024, mx::math::ft::dir::forward, true );
95
97 in.setRandom();
99 float sin = in.abs2().sum();
100
101 fft( in, in );
102
103 float sout = in.abs2().sum() / in.rows();
104
105 float rmsdiff = (in-incheck).abs2().sum();
106
107 //Make sure it isn't ident
108 REQUIRE(rmsdiff > 0);
109
110 // Test by Parsevals
111 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, 1e-3 ) );
112 }
113
114 SECTION( "in-place, backward" )
115 {
116 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 1> fft( 1024, mx::math::ft::dir::backward, true );
117
119 in.setRandom();
120
122
123 float sin = in.abs2().sum();
124
125 fft( in, in );
126
127 float sout = in.abs2().sum()/in.rows();
128
129 float rmsdiff = (in-incheck).abs2().sum();
130
131 //Make sure it isn't ident
132 REQUIRE(rmsdiff > 0);
133
134 // Test by Parsevals
135 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, 1e-3 ) );
136 }
137}
138#endif
139
140namespace unitTest::math::ft::fftTcudaTest
141{
142
143/// 2D c2c FFT with cuFFT
144/**
145 * \ingroup fftT_unit_tests
146 */
147TEST_CASE( "2D c2c FFT with cuFFT, float", "[math::ft]" )
148{
149 if( !mxlibTest::cudaDeviceAvailable() )
150 {
151 WARN( "CUDA runtime is available but no CUDA device is present" );
152 return;
153 }
154
155 srand( time( 0 ) );
156
157 SECTION( "out-of-place, forward, default constructed, raw interface" )
158 {
159 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2, 1> fft;
160
161 fft.plan( 128, 128 );
162
163 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
164 in.setRandom();
165 out.setZero();
166
167 mx::cuda::cudaPtr<std::complex<float>> devIn, devOut;
168 devIn.upload( in.data(), in.rows(), in.cols() );
169 devOut.resize( out.rows(), out.cols() );
170
171 cufftResult rv = fft( devOut.data(), devIn.data() );
172
173 REQUIRE( rv == CUFFT_SUCCESS );
174
175 devOut.download( out.data() );
176
177 float sin = in.abs2().sum() * ( out.rows() * out.cols() );
178 float sout = out.abs2().sum();
179
180 // Test by Parsevals
181 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
182 }
183
184 SECTION( "out-of-place, forward, default constructed, eigen interface" )
185 {
186 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2, 1> fft;
187
188 fft.plan( 128, 128 );
189
190 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
191 in.setRandom();
192 out.setZero();
193
194 mx::cuda::cudaPtr<std::complex<float>> devIn, devOut;
195 devIn.upload( in.data(), in.rows(), in.cols() );
196 devOut.resize( out.rows(), out.cols() );
197
198 cufftResult rv = fft( devOut, devIn );
199
200 REQUIRE( rv == CUFFT_SUCCESS );
201
202 devOut.download( out.data() );
203
204 float sin = in.abs2().sum();
205 float sout = out.abs2().sum() / ( out.rows() * out.cols() );
206
207 // Test by Parsevals
208 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
209 }
210
211 SECTION( "out-of-place, forward, plan constructor" )
212 {
213 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2, 1> fft( 128, 128 );
214
215 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
216 ;
217 out.setZero();
218
219 mx::cuda::cudaPtr<std::complex<float>> devIn, devOut;
220 devIn.upload( in.data(), in.rows(), in.cols() );
221 devOut.resize( out.rows(), out.cols() );
222
223 cufftResult rv = fft( devOut, devIn );
224
225 REQUIRE( rv == CUFFT_SUCCESS );
226
227 devOut.download( out.data() );
228
229 float sin = in.abs2().sum();
230 float sout = out.abs2().sum() / ( in.rows() * out.cols() );
231
232 // Test by Parsevals
233 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
234 }
235
236 SECTION( "out-of-place, backward" )
237 {
238 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2, 1> fft( 128, 128, mx::math::ft::dir::backward );
239
240 mx::improc::eigenImage<std::complex<float>> in( 128, 128 ), out( 128, 128 );
241 out.setRandom();
242 in.setZero();
243
244 mx::cuda::cudaPtr<std::complex<float>> devIn, devOut;
245 devIn.upload( in.data(), in.rows(), in.cols() );
246 devOut.resize( out.rows(), out.cols() );
247
248 cufftResult rv = fft( devOut, devIn );
249
250 REQUIRE( rv == CUFFT_SUCCESS );
251
252 devOut.download( out.data() );
253
254 float sin = in.abs2().sum() / ( in.rows() * in.cols() );
255 float sout = out.abs2().sum();
256
257 // Test by Parsevals
258 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, ( sin ) * ( 1e-3 ) ) );
259 }
260 /*
261 SECTION( "in-place, forward" )
262 {
263 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft( 128, 128, mx::math::ft::dir::forward,
264 true );
265
266 mx::improc::eigenImage<std::complex<float>> in( 128, 128 );
267 in.setRandom();
268 mx::improc::eigenImage<std::complex<float>> incheck = in;
269 float sin = in.abs2().sum();
270
271 fft( in, in );
272
273 float sout = in.abs2().sum() / (in.rows()*in.cols());
274
275 float rmsdiff = (in-incheck).abs2().sum();
276
277 //Make sure it isn't ident
278 REQUIRE(rmsdiff > 0);
279
280 // Test by Parsevals
281 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, (sin) * (1e-3) ) );
282 }
283
284 SECTION( "in-place, backward" )
285 {
286 mx::math::ft::fftT<std::complex<float>, std::complex<float>, 2> fft( 128, 128, mx::math::ft::dir::backward,
287 true );
288
289 mx::improc::eigenImage<std::complex<float>> in( 128, 128 );
290 in.setRandom();
291
292 mx::improc::eigenImage<std::complex<float>> incheck = in;
293
294 float sin = in.abs2().sum();
295
296 fft( in, in );
297
298 float sout = in.abs2().sum()/(in.rows()*in.cols());
299
300 float rmsdiff = (in-incheck).abs2().sum();
301
302 //Make sure it isn't ident
303 REQUIRE(rmsdiff > 0);
304
305 // Test by Parsevals
306 REQUIRE_THAT( sin, Catch::Matchers::WithinAbs( sout, (sin) * (1e-3) ) );
307 }
308 */
309}
310
311} // namespace unitTest::math::ft::fftTcudaTest
Tools for using the eigen library for image processing.
The Fast Fourier Transform interface.
TEST_CASE("Loading aoAtmosphere config settings", "[ao::analysis::aoAtmosphere]")
Verify parsing and validation of atmosphere configuration settings.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
TEST_CASE("2D c2c FFT with cuFFT, float", "[math::ft]")
2D c2c FFT with cuFFT
@ backward
Specifies the backward transform.
Definition ftTypes.hpp:42
@ forward
Specifies the forward transform.
Definition ftTypes.hpp:41