diff options
author | hayati ayguen <h_ayguen@web.de> | 2020-04-02 23:11:14 +0200 |
---|---|---|
committer | hayati ayguen <h_ayguen@web.de> | 2020-04-02 23:11:14 +0200 |
commit | 5553119edd8b4fbdcdd7770aea45246c32f97e26 (patch) | |
tree | 7795547312989d980cb32091f3041664c2846f02 | |
parent | 2a5336ab689ab95a7fb3eebbbbbecae3a1db1c57 (diff) | |
download | pffft-5553119edd8b4fbdcdd7770aea45246c32f97e26.tar.gz |
define/use pffft::AlignedVector<> with example use in test_pffft.cpp
* examples: see test_pffft.cpp at begin of template function Ttest()
* added typedef pffft::Fft<>::Complex besides Scalar
Signed-off-by: hayati ayguen <h_ayguen@web.de>
-rw-r--r-- | pffft.hpp | 116 | ||||
-rw-r--r-- | test_pffft.cpp | 50 |
2 files changed, 84 insertions, 82 deletions
@@ -44,18 +44,32 @@ namespace pffft { // enum { PFFFT_REAL, PFFFT_COMPLEX } typedef pffft_transform_t TransformType; -template<typename T> -class PFAlloc; +// helper to define 'Scalar' and 'Complex' (in namespace pffft) +template<typename T> struct Types {}; +template<> struct Types<float> { typedef float Scalar; typedef std::complex<Scalar> Complex; }; +template<> struct Types<double> { typedef double Scalar; typedef std::complex<Scalar> Complex; }; +template<> struct Types< std::complex<float> > { typedef float Scalar; typedef std::complex<float> Complex; }; +template<> struct Types< std::complex<double> > { typedef double Scalar; typedef std::complex<double> Complex; }; + +// Allocator +template<typename T> class PFAlloc; namespace { -template<typename T> -class Setup; + template<typename T> class Setup; } -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +#if (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)) template<typename T> -using AlignedVector = typename std::vector< T, PFAlloc<T> > ; +using AlignedVector = typename std::vector< T, PFAlloc<T> >; + +#else + +template <typename T> +struct AlignedVector : public std::vector< T, PFAlloc<T> > { + AlignedVector() : std::vector< T, PFAlloc<T> >() { } + AlignedVector(int N) : std::vector< T, PFAlloc<T> >(N) { } +}; #endif @@ -64,23 +78,9 @@ template<typename T> class Fft { public: - typedef typename Setup<T>::Scalar Scalar; typedef T value_type; - -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) - - using ValueVector = AlignedVector<T>; - using ComplexVector = AlignedVector<std::complex<Scalar>>; - using InternalLayoutVector = AlignedVector<Scalar>; - -#else - - typedef std::vector< T, PFAlloc<T> > ValueVector; - typedef std::vector< std::complex<Scalar>, PFAlloc< std::complex<Scalar> > > ComplexVector; - typedef std::vector< Scalar, PFAlloc<Scalar> > InternalLayoutVector; - -#endif - + typedef typename Types<T>::Scalar Scalar; + typedef typename Types<T>::Complex Complex; // static retrospection functions @@ -117,11 +117,11 @@ public: //// //////////////////////////////////////////// - ValueVector valueVector() const { return ValueVector(length); } + AlignedVector<T> valueVector() const { return AlignedVector<T>(length); } - ComplexVector spectrumVector() const { return ComplexVector( getSpectrumSize() ); } + AlignedVector<Complex> spectrumVector() const { return AlignedVector<Complex>( getSpectrumSize() ); } - InternalLayoutVector internalLayoutVector() const { return InternalLayoutVector( getInternalLayoutSize() ); } + AlignedVector<Scalar> internalLayoutVector() const { return AlignedVector<Scalar>( getInternalLayoutSize() ); } //////////////////////////////////////////// // although using Vectors for output .. @@ -129,10 +129,10 @@ public: // core API, having the spectrum in canonical order - ComplexVector& forward(const ValueVector& input, ComplexVector& spectrum) + AlignedVector<Complex> & forward(const AlignedVector<T> & input, AlignedVector<Complex> & spectrum) { forward( input.data(), spectrum.data() ); return spectrum; } - ValueVector& inverse(const ComplexVector& spectrum, ValueVector& output) + AlignedVector<T> & inverse(const AlignedVector<Complex> & spectrum, AlignedVector<T> & output) { inverse( spectrum.data(), output.data() ); return output; } // provide additional functions with spectrum in some internal Layout. @@ -140,36 +140,36 @@ public: // these are useful in special applications, like fast convolution, // where inverse() is following anyway .. - InternalLayoutVector& forwardToInternalLayout( - const ValueVector& input, - InternalLayoutVector& spectrum_internal_layout + AlignedVector<Scalar> & forwardToInternalLayout( + const AlignedVector<T> & input, + AlignedVector<Scalar> & spectrum_internal_layout ) { forwardToInternalLayout( input.data(), spectrum_internal_layout.data() ); return spectrum_internal_layout; } - ValueVector& inverseFromInternalLayout( - const InternalLayoutVector& spectrum_internal_layout, - ValueVector& output + AlignedVector<T> & inverseFromInternalLayout( + const AlignedVector<Scalar> & spectrum_internal_layout, + AlignedVector<T> & output ) { inverseFromInternalLayout( spectrum_internal_layout.data(), output.data() ); return output; } void reorderSpectrum( - const InternalLayoutVector& input, - ComplexVector &output + const AlignedVector<Scalar> & input, + AlignedVector<Complex> & output ) { reorderSpectrum( input.data(), output.data() ); } - InternalLayoutVector& convolveAccumulate( - const InternalLayoutVector& spectrum_internal_a, - const InternalLayoutVector& spectrum_internal_b, - InternalLayoutVector& spectrum_internal_ab, + AlignedVector<Scalar> & convolveAccumulate( + const AlignedVector<Scalar> & spectrum_internal_a, + const AlignedVector<Scalar> & spectrum_internal_b, + AlignedVector<Scalar> & spectrum_internal_ab, const Scalar scaling ) { convolveAccumulate( spectrum_internal_a.data(), spectrum_internal_b.data(), spectrum_internal_ab.data(), scaling ); return spectrum_internal_ab; } - InternalLayoutVector& convolve( - const InternalLayoutVector& spectrum_internal_a, - const InternalLayoutVector& spectrum_internal_b, - InternalLayoutVector& spectrum_internal_ab, + AlignedVector<Scalar> & convolve( + const AlignedVector<Scalar> & spectrum_internal_a, + const AlignedVector<Scalar> & spectrum_internal_b, + AlignedVector<Scalar> & spectrum_internal_ab, const Scalar scaling ) { convolve( spectrum_internal_a.data(), spectrum_internal_b.data(), spectrum_internal_ab.data(), scaling ); return spectrum_internal_ab; } @@ -193,13 +193,13 @@ public: static Scalar* alignedAllocScalar(int length); - static std::complex<Scalar>* alignedAllocComplex(int length); + static Complex* alignedAllocComplex(int length); // core API, having the spectrum in canonical order - std::complex<Scalar>* forward(const T* input, std::complex<Scalar>* spectrum); + Complex* forward(const T* input, Complex* spectrum); - T* inverse(const std::complex<Scalar>* spectrum, T* output); + T* inverse(const Complex* spectrum, T* output); // provide additional functions with spectrum in some internal Layout. @@ -212,7 +212,7 @@ public: T* inverseFromInternalLayout(const Scalar* spectrum_internal_layout, T* output); - void reorderSpectrum(const Scalar* input, std::complex<Scalar>* output ); + void reorderSpectrum(const Scalar* input, Complex* output ); Scalar* convolveAccumulate(const Scalar* spectrum_internal_a, const Scalar* spectrum_internal_b, @@ -276,7 +276,7 @@ alignedFree(void* ptr) namespace { template<typename T> -struct Setup +class Setup {}; template<> @@ -285,8 +285,8 @@ class Setup<float> PFFFT_Setup* self; public: - typedef float Scalar; typedef float value_type; + typedef Types< value_type >::Scalar Scalar; Setup() : self(NULL) @@ -358,8 +358,8 @@ class Setup< std::complex<float> > PFFFT_Setup* self; public: - typedef float Scalar; typedef std::complex<float> value_type; + typedef Types< value_type >::Scalar Scalar; Setup() : self(NULL) @@ -423,8 +423,8 @@ class Setup<double> PFFFTD_Setup* self; public: - typedef double Scalar; typedef double value_type; + typedef Types< value_type >::Scalar Scalar; Setup() : self(NULL) @@ -499,8 +499,8 @@ class Setup< std::complex<double> > PFFFTD_Setup* self; public: - typedef double Scalar; typedef std::complex<double> value_type; + typedef Types< value_type >::Scalar Scalar; Setup() : self(NULL) @@ -611,8 +611,8 @@ Fft<T>::prepareLength(int newLength) } template<typename T> -inline std::complex<typename Fft<T>::Scalar>* -Fft<T>::forward(const T* input, std::complex<Scalar>* spectrum) +inline typename Fft<T>::Complex * +Fft<T>::forward(const T* input, Complex * spectrum) { setup.transform_ordered(reinterpret_cast<const Scalar*>(input), reinterpret_cast<Scalar*>(spectrum), @@ -623,7 +623,7 @@ Fft<T>::forward(const T* input, std::complex<Scalar>* spectrum) template<typename T> inline T* -Fft<T>::inverse(std::complex<Scalar> const* spectrum, T* output) +Fft<T>::inverse(Complex const* spectrum, T* output) { setup.transform_ordered(reinterpret_cast<const Scalar*>(spectrum), reinterpret_cast<Scalar*>(output), @@ -656,7 +656,7 @@ Fft<T>::inverseFromInternalLayout(const Scalar* spectrum_internal_layout, T* out template<typename T> inline void -Fft<T>::reorderSpectrum( const Scalar* input, std::complex<Scalar>* output ) +Fft<T>::reorderSpectrum( const Scalar* input, Complex* output ) { setup.reorder(input, reinterpret_cast<Scalar*>(output), PFFFT_FORWARD); } @@ -706,10 +706,10 @@ pffft::Fft<T>::alignedAllocScalar(int length) } template<typename T> -inline std::complex<typename pffft::Fft<T>::Scalar>* +inline typename Fft<T>::Complex * Fft<T>::alignedAllocComplex(int length) { - return reinterpret_cast< std::complex<Scalar>* >( Setup<T>::allocate(2 * length) ); + return reinterpret_cast< Complex* >( Setup<T>::allocate(2 * length) ); } diff --git a/test_pffft.cpp b/test_pffft.cpp index 08dbdaf..f245a1f 100644 --- a/test_pffft.cpp +++ b/test_pffft.cpp @@ -60,44 +60,46 @@ template<typename T> bool Ttest(int N, bool useOrdered) { - typedef typename pffft::Fft<T> Fft; - typedef typename Fft::Scalar Scalar; - - const bool cplx = Fft::isComplexTransform(); + typedef pffft::Fft<T> Fft; + typedef typename pffft::Fft<T>::Scalar FftScalar; + typedef typename Fft::Complex FftComplex; + const bool cplx = pffft::Fft<T>::isComplexTransform(); const double EXPECTED_DYN_RANGE = Fft::isDoubleScalar() ? 215.0 : 140.0; - int k, j, m, iter, kmaxOther; - bool retError = false; - double freq, dPhi, phi, phi0; - double pwr, pwrCar, pwrOther, err, errSum, mag, expextedMag; - double amp = 1.0; - assert(pffft::isPowerOfTwo(N)); Fft fft = Fft(N); // instantiate and prepareLength() for length N #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) - pffft::AlignedVector<T> X = fft.valueVector(); // for X = input vector - pffft::AlignedVector<std::complex<Scalar>> Y = fft.spectrumVector(); // for Y = forward(X) - pffft::AlignedVector<Scalar> R = fft.internalLayoutVector(); // for R = forwardInternalLayout(X) - pffft::AlignedVector<T> Z = fft.valueVector(); // for Z = inverse(Y) = inverse( forward(X) ) - // or Z = inverseInternalLayout(R) + // possible ways to declare/instatiate aligned vectors with C++11 + // some lines require a typedef of above + auto X = fft.valueVector(); // for X = input vector + pffft::AlignedVector<typename Fft::Complex> Y = fft.spectrumVector(); // for Y = forward(X) + pffft::AlignedVector<FftScalar> R = fft.internalLayoutVector(); // for R = forwardInternalLayout(X) + pffft::AlignedVector<T> Z = fft.valueVector(); // for Z = inverse(Y) = inverse( forward(X) ) + // or Z = inverseInternalLayout(R) #else -// with C++11 and auto - this gets a bit easier - typename Fft::ValueVector X = fft.valueVector(); // for X = input vector - typename Fft::ComplexVector Y = fft.spectrumVector(); // for Y = forward(X) - typename Fft::InternalLayoutVector R = fft.internalLayoutVector(); // for R = forwardInternalLayout(X) - typename Fft::ValueVector Z = fft.valueVector(); // for Z = inverse(Y) = inverse( forward(X) ) - // or Z = inverseInternalLayout(R) + // possible ways to declare/instatiate aligned vectors with C++98 + pffft::AlignedVector<T> X = fft.valueVector(); // for X = input vector + pffft::AlignedVector<FftComplex> Y = fft.spectrumVector(); // for Y = forward(X) + pffft::AlignedVector<typename Fft::Scalar> R = fft.internalLayoutVector(); // for R = forwardInternalLayout(X) + pffft::AlignedVector<T> Z = fft.valueVector(); // for Z = inverse(Y) = inverse( forward(X) ) + // or Z = inverseInternalLayout(R) #endif // work with complex - without the capabilities of a higher c++ standard - Scalar* Xs = reinterpret_cast<Scalar*>(X.data()); // for X = input vector - Scalar* Ys = reinterpret_cast<Scalar*>(Y.data()); // for Y = forward(X) - Scalar* Zs = reinterpret_cast<Scalar*>(Z.data()); // for Z = inverse(Y) = inverse( forward(X) ) + FftScalar* Xs = reinterpret_cast<FftScalar*>(X.data()); // for X = input vector + FftScalar* Ys = reinterpret_cast<FftScalar*>(Y.data()); // for Y = forward(X) + FftScalar* Zs = reinterpret_cast<FftScalar*>(Z.data()); // for Z = inverse(Y) = inverse( forward(X) ) + + int k, j, m, iter, kmaxOther; + bool retError = false; + double freq, dPhi, phi, phi0; + double pwr, pwrCar, pwrOther, err, errSum, mag, expextedMag; + double amp = 1.0; for (k = m = 0; k < (cplx ? N : (1 + N / 2)); k += N / 16, ++m) { amp = ((m % 3) == 0) ? 1.0F : 1.1F; |