29#if defined(RealFFT_RECURSES)
30#error Recursive header files inclusion detected in RealFFT.h
33#define RealFFT_RECURSES
40 #error You need to have activated FFTW3 (WITH_FFTW3) to include this file.
51#include <boost/math/constants/constants.hpp>
53#include "DGtal/kernel/domains/HyperRectDomain.h"
54#include "DGtal/images/ArrayImageAdapter.h"
55#include "DGtal/kernel/PointVector.h"
65template <
typename TFFTW>
69 typename TFFTW::complex*
apply(
typename TFFTW::complex* ptr ) {
return ptr; }
72 typename TFFTW::complex*
apply( std::complex<typename TFFTW::real>* ptr ) {
return reinterpret_cast<typename TFFTW::complex*
>(ptr); }
82#define FFTW_WRAPPER_GEN(suffix) \
83 using size_t = std::size_t; \
84 using complex = fftw ## suffix ## _complex; \
85 using plan = fftw ## suffix ## _plan; \
86 using self = FFTWWrapper<real>; \
88 static inline void* malloc( size_t n ) noexcept { return fftw ## suffix ## _malloc(n); } \
89 static inline void free( void* p ) noexcept { fftw ## suffix ## _free(p); } \
90 static inline void execute( const plan p ) noexcept { fftw ## suffix ## _execute(p); } \
91 static inline void destroy_plan( plan p ) noexcept { fftw ## suffix ## _destroy_plan(p); } \
93 template < typename C > \
95 plan plan_dft_r2c( int rank, const int* n, real* in, C* out, unsigned flags ) noexcept \
97 return fftw ## suffix ## _plan_dft_r2c(rank, n, in, FFTWComplexCast<self>::apply(out), flags); \
100 template < typename C > \
102 plan plan_dft_c2r( int rank, const int* n, C* in, real* out, unsigned flags ) noexcept \
104 return fftw ## suffix ## _plan_dft_c2r(rank, n, FFTWComplexCast<self>::apply(in), out, flags); \
107 template < typename C > \
109 void execute_dft_r2c( const plan p, real* in, C* out ) noexcept \
111 fftw ## suffix ## _execute_dft_r2c(p, in, FFTWComplexCast<self>::apply(out)); \
114 template < typename C > \
116 void execute_dft_c2r( const plan p, C* in, real* out ) noexcept \
118 fftw ## suffix ## _execute_dft_c2r(p, FFTWComplexCast<self>::apply(in), out); \
125 template < typename C > \
127 plan plan_dft( int rank, const int* n, real* in, C* out, int way, unsigned flags ) noexcept \
129 if ( way == FFTW_FORWARD ) \
130 return plan_dft_r2c( rank, n, in, out, flags ); \
132 return plan_dft_c2r( rank, n, out, in, flags ); \
139 template < typename C > \
141 void execute_dft( const plan p, real* in, C* out, int way ) noexcept \
143 if ( way == FFTW_FORWARD ) \
144 execute_dft_r2c( p, in, out ); \
146 execute_dft_c2r( p, out, in ); \
150template <
typename Real =
double>
154 static_assert( ! std::is_same<Real, float>::value,
"[DGtal::RealFFT] The FFTW3 library for float precision (libfftw3f) has not been found." );
155 static_assert( ! std::is_same<Real, double>::value,
"[DGtal::RealFFT] The FFTW3 library for double precision (libfftw3) has not been found." );
156 static_assert( ! std::is_same<Real, long double>::value,
"[DGtal::RealFFT] The FFTW3 library for long double precision (libfftw3l) has not been found." );
157 static_assert( ! std::is_same<Real, Real>::value,
"[DGtal::RealFFT] Value type not supported." );
160#ifdef WITH_FFTW3_DOUBLE
172#ifdef WITH_FFTW3_FLOAT
184#ifdef WITH_FFTW3_LONG
191 using real =
long double;
216template <
typename TSpace,
typename T>
231 using Self = RealFFT< Domain, T >;
233 using SpatialImage = ArrayImageAdapter< Real*, Domain >;
235 using FreqImage = ArrayImageAdapter< Complex*, Domain >;
236 using ConstFreqImage = ArrayImageAdapter< const Complex*, Domain >;
238 static const constexpr Dimension dimension = Domain::dimension;
252 RealFFT(
Domain const& aDomain );
266 RealFFT(
Self const & ) =
delete;
275 Self & operator= (
Self && ) =
delete;
294 std::size_t getPadding() const noexcept;
305 Real* getSpatialStorage() noexcept;
307 const
Real* getSpatialStorage() const noexcept;
330 Domain const& getSpatialDomain() const noexcept;
333 Point const& getSpatialExtent() const noexcept;
348 Complex* getFreqStorage() noexcept;
350 const
Complex* getFreqStorage() const noexcept;
381 Domain const& getFreqDomain() const noexcept;
388 Point const& getFreqExtent() const noexcept;
414 void createPlan(
unsigned flags,
int way );
442 void doFFT(
unsigned flags = FFTW_ESTIMATE,
int way = FFTW_FORWARD,
bool normalized = false );
459 void forwardFFT(
unsigned flags = FFTW_ESTIMATE );
484 void backwardFFT(
unsigned flags = FFTW_ESTIMATE,
bool normalized = true );
494 RealPoint getScaledSpatialExtent() const noexcept;
499 void setScaledSpatialExtent(
RealPoint const& anExtent ) noexcept;
504 RealPoint getScaledSpatialLowerBound() const noexcept;
566 Point calcNativeSpatialCoords(
RealPoint const& aScaledPoint ) const noexcept;
583 Point calcNativeFreqCoords(
RealPoint const& aScaledPoint,
bool & applyConj ) const noexcept;
612 Real getScaledSpatialValue(
RealPoint const& aScaledPoint ) const noexcept
614 return getSpatialImage()( getNativeSpatialCoords( aScaledPoint ) );
624 void setScaledSpatialValue(
RealPoint const& aScaledPoint, Real aValue )
noexcept
626 getSpatialImage().setValue( getNativeSpatialCoords( aScaledPoint ), aValue );
640 Complex getScaledFreqValue(
RealPoint const& aScaledPoint )
const noexcept
643 const auto aPoint = calcNativeFreqCoords( aScaledPoint, apply_conj );
644 const Complex aScaledValue = calcScaledFreqValue( aScaledPoint, getFreqImage()(
aPoint ) );
645 return apply_conj ? std::conj( aScaledValue ) : aScaledValue;
656 void setScaledFreqValue(
RealPoint const& aScaledPoint, Complex aScaledValue )
noexcept
659 const auto aPoint = calcNativeFreqCoords( aScaledPoint, apply_conj );
660 const Complex aValue = calcNativeFreqValue( aScaledPoint, aScaledValue );
663 getFreqImage().setValue(
aPoint, std::conj( aValue ) );
665 getFreqImage().setValue(
aPoint, aValue );
678 bool isValid() const noexcept;
684 void selfDisplay (
std::ostream & out ) const;
697 const
Domain myFreqDomain;
698 const
Domain myFullSpatialDomain;
702 Real myScaledFreqMag;
717 operator<< (
std::ostream & out, const RealFFT<TDomain,T> &
object );
723#include "DGtal/math/RealFFT.ih"
730#undef RealFFT_RECURSES
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
ArrayImageAdapter< const Real *, Domain > ConstSpatialImage
Constant spatial image type.
RealFFT< Domain, T > Self
Self type.
typename Space::Point Point
Point type.
typename Space::Dimension Dimension
Space dimension type.
ArrayImageAdapter< Real *, Domain > SpatialImage
Mutable spatial image type.
std::complex< Real > Complex
Complex value type.
RealFFT(Self &&)=delete
Move constructor. Deleted.
ArrayImageAdapter< const Complex *, Domain > ConstFreqImage
Constant frequency image type.
ArrayImageAdapter< Complex *, Domain > FreqImage
Mutable frequency image type.
PointVector< dim, Integer > Point
Points in DGtal::SpaceND.
DGtal::Dimension Dimension
Copy of the type used for the dimension.
DGtal is the top-level namespace which contains all DGtal functions and types.
Facility to cast to the complex type used by fftw.
static TFFTW::complex * apply(std::complex< typename TFFTW::real > *ptr)
static TFFTW::complex * apply(typename TFFTW::complex *ptr)
Wrapper to fftw functions depending on value type.