69 using FFT = RealFFT< TDomain, TValue >;
71 INFO(
"Initializing RealFFT." );
72 FFT fft( anImage.
domain() );
74 INFO(
"Copying data from the image." );
75 auto spatial_image = fft.getSpatialImage();
76 std::copy( anImage.cbegin(), anImage.cend(), spatial_image.begin() );
78 INFO(
"Forward transformation." );
79 fft.forwardFFT( FFTW_ESTIMATE );
81 INFO(
"Checking modification of the input image." );
82 REQUIRE( ! std::equal( anImage.cbegin(), anImage.cend(), spatial_image.cbegin() ) );
84 INFO(
"Backward transformation." );
85 fft.backwardFFT( FFTW_ESTIMATE );
87 INFO(
"Comparing result with original image." );
88 const auto eps = 100 * std::numeric_limits<TValue>::epsilon() * std::log( anImage.
domain().size() );
91 for (
auto it = spatial_image.cbegin(); it != spatial_image.cend(); ++it )
93 if ( std::abs( *it - anImage( it.getPoint() ) ) > eps * std::max( *it, TValue(1) ) )
94 FAIL(
"Approximation failed: " << *it <<
" - " << anImage( it.getPoint() ) <<
" = " << (*it - anImage( it.getPoint() ) ) );
131 typedef RealFFT< TDomain, TValue > FFT;
132 using RealPoint =
typename FFT::RealPoint;
134 const TValue pi = boost::math::constants::pi<TValue>();
135 const TValue freq = 5;
136 const TValue phase = pi/4;
138 INFO(
"Checking image size." );
139 REQUIRE( anImage.
extent()[ TDomain::dimension-1 ] >= 2*std::abs(freq) );
141 INFO(
"Initializing RealFFT." );
144 INFO(
"Initializing spatial data." );
145 auto spatial_image = fft.getSpatialImage();
146 for (
auto it = spatial_image.begin(); it != spatial_image.end(); ++it )
148 const auto pt = fft.calcScaledSpatialCoords( it.getPoint() );
149 REQUIRE( fft.calcNativeSpatialCoords( pt ) == it.getPoint() );
151 *it = std::cos( 2*pi * freq * pt[ TDomain::dimension - 1 ] + phase );
154 INFO(
"Forward transformation." );
155 fft.forwardFFT( FFTW_ESTIMATE );
157 INFO(
"Finding maximal frequency..." );
158 const auto freq_image = fft.getFreqImage();
159 const auto it_max =
findMaxNorm( freq_image.cbegin(), freq_image.cend() );
160 const auto pt_max = it_max.getPoint();
161 INFO(
"\tat " << pt_max <<
" with value " << *it_max );
163 INFO(
"Checks maximal frequency on unit domain." );
165 auto freq_pt = fft.calcScaledFreqCoords( it_max.getPoint() );
166 auto freq_val = fft.calcScaledFreqValue( freq_pt, *it_max );
169 REQUIRE( fft.calcNativeFreqCoords( freq_pt, applyConj ) == it_max.getPoint() );
171 REQUIRE( std::norm( fft.calcNativeFreqValue( freq_pt, freq_val ) - *it_max ) == Approx(0.).scale(std::norm(*it_max)) );
172 REQUIRE( std::norm( fft.getScaledFreqValue( freq_pt ) - freq_val ) == Approx(0.).scale(std::norm(freq_val)) );
174 if ( freq_pt[ TDomain::dimension-1 ] * freq < 0 )
177 freq_val = std::conj( freq_val );
180 REQUIRE( ( freq_pt -
RealPoint::base( TDomain::dimension-1, freq ) ).norm() == Approx( 0 ).scale(freq_pt.norm()) );
181 REQUIRE( ( std::fmod( std::fmod( std::arg( freq_val ) - phase, 2*pi ) + 3*pi, 2*pi ) - pi ) == Approx( 0 ).scale(pi) );
185 INFO(
"Checks maximal frequency on translated unit domain." );
189 auto freq_pt = fft.calcScaledFreqCoords( it_max.getPoint() );
190 auto freq_val = fft.calcScaledFreqValue( freq_pt, *it_max );
193 REQUIRE( fft.calcNativeFreqCoords( freq_pt, applyConj ) == it_max.getPoint() );
195 REQUIRE( std::norm( fft.calcNativeFreqValue( freq_pt, freq_val ) - *it_max ) == Approx(0.).scale(std::norm(*it_max)) );
196 REQUIRE( std::norm( fft.getScaledFreqValue( freq_pt ) - freq_val ) == Approx(0.).scale(std::norm(freq_val)) );
198 if ( freq_pt[ TDomain::dimension-1 ] * freq < 0 )
201 freq_val = std::conj( freq_val );
204 REQUIRE( ( freq_pt -
RealPoint::base( TDomain::dimension-1, freq ) ).norm() == Approx( 0 ).scale(freq_pt.norm()) );
205 REQUIRE( ( std::fmod( std::fmod( std::arg( freq_val ) - phase + pi/2, 2*pi) + 3*pi, 2*pi ) - pi ) == Approx( 0 ).scale(pi) );
208 INFO(
"Checks maximal frequency on translated initial domain." );
212 fft.setScaledSpatialExtent( anImage.
extent() );
213 fft.setScaledSpatialLowerBound( shift );
215 auto freq_pt = fft.calcScaledFreqCoords( it_max.getPoint() );
216 auto freq_val = fft.calcScaledFreqValue( freq_pt, *it_max );
219 REQUIRE( fft.calcNativeFreqCoords( freq_pt, applyConj ) == it_max.getPoint() );
221 REQUIRE( std::norm( fft.calcNativeFreqValue( freq_pt, freq_val ) - *it_max ) == Approx(0.).scale(std::norm(*it_max)) );
222 REQUIRE( std::norm( fft.getScaledFreqValue( freq_pt ) - freq_val ) == Approx(0.).scale(std::norm(freq_val)) );
224 if ( freq_pt[ TDomain::dimension-1 ] * freq < 0 )
227 freq_val = std::conj( freq_val );
230 const auto scaled_factor = freq/anImage.
extent()[ TDomain::dimension-1 ];
231 REQUIRE( ( freq_pt -
RealPoint::base( TDomain::dimension-1, scaled_factor ) ).norm() == Approx( 0 ).scale(freq_pt.norm()) );
232 REQUIRE( ( std::fmod( std::fmod( std::arg( freq_val ) - phase + 2*pi*scaled_factor*shift[TDomain::dimension-1], 2*pi ) + 3*pi, 2*pi ) - pi ) == Approx( 0 ).scale(pi) );
247 using FFT = RealFFT< TDomain, TValue >;
248 using Point =
typename TDomain::Point;
254 INFO(
"Initializing RealFFT." );
257 FFT shifted_fft( shifted_domain );
259 INFO(
"Pre-creating plan." );
260 fft.createPlan( FFTW_MEASURE, FFTW_FORWARD );
262 INFO(
"Copying data from the image." );
263 auto spatial_image = fft.getSpatialImage();
264 std::copy( anImage.cbegin(), anImage.cend(), spatial_image.begin() );
266 auto shifted_spatial_image = shifted_fft.getSpatialImage();
267 const auto spatial_extent = shifted_fft.getSpatialExtent();
268 for (
auto it = shifted_spatial_image.begin(); it != shifted_spatial_image.end(); ++it )
271 Point pt = it.getPoint();
272 for (
typename Point::Dimension i = 0; i < Point::dimension; ++i )
274 pt[ i ] -= anImage.
extent()[ i ];
279 INFO(
"Forward transformation (forcing plan re-use)." );
280 fft.forwardFFT( FFTW_MEASURE | FFTW_WISDOM_ONLY );
281 shifted_fft.forwardFFT( FFTW_MEASURE | FFTW_WISDOM_ONLY );
283 INFO(
"Comparing results." );
284 auto freq_image = fft.getFreqImage();
285 auto shifted_freq_image = shifted_fft.getFreqImage();
286 const TValue eps = 100 * std::numeric_limits<TValue>::epsilon();
288 for (
auto it = freq_image.cbegin(), shifted_it = shifted_freq_image.cbegin(); it != freq_image.cend(); ++it, ++shifted_it )
291 fft.calcScaledFreqValue( fft.calcScaledFreqCoords( it.getPoint() ), *it )
292 - shifted_fft.calcScaledFreqValue( shifted_fft.calcScaledFreqCoords( shifted_it.getPoint() ), *shifted_it ) )
293 > eps * std::max( std::norm(*it), TValue(1) ) )
294 FAIL(
"Approximation failed at point " << it.getPoint()
295 <<
" between " << *it
296 <<
" and " << shifted_fft.calcScaledFreqValue( shifted_fft.calcScaledFreqCoords( shifted_it.getPoint() ), *shifted_it )
297 <<
" (scaled from " << *shifted_it <<
")" );
const Point & lowerBound() const
const Point & upperBound() const