bugfixes and new helper functions for retrospection and allocation
* bugfix test_pffft.cpp: missing free
* bugfix test_pffft.cpp: normalization of inverse() was on wrong index or variable
* retrospection
- wrapper class with typedef to initial template type
- static helpers: isComplexTransform(), isFloatScalar() and isDoubleScalar()
* allocation helpers:
- member helpers: getSpectrumSize(), getInternalLayoutSize() and
allocateOrigin(), allocateSpectrum() and allocateInternalLayout()
* test_pffft float/double/cpp:
float/double: use/test unordered pffft_transform() for inverse
cpp: use/test inverseInternalLayout() when not useOrdered
Signed-off-by: hayati ayguen <h_ayguen@web.de>
diff --git a/pffft.hpp b/pffft.hpp
index 9f0fa7b..3e08644 100644
--- a/pffft.hpp
+++ b/pffft.hpp
@@ -56,6 +56,7 @@
{
public:
typedef typename Setup<T>::Scalar Scalar;
+ typedef T TType;
Fft(int length, int stackThresholdLen = 4096);
@@ -88,6 +89,25 @@
Scalar* dft_ab,
const Scalar scaling);
+
+ int getSpectrumSize() const { return isComplexTransform() ? length : ( length / 2 ); }
+
+ int getInternalLayoutSize() const { return isComplexTransform() ? ( 2 * length ) : length; }
+
+
+ T* allocateOrigin() const { return alignedAllocType(length); }
+
+ std::complex<Scalar>* allocateSpectrum() const { return alignedAllocComplex( getSpectrumSize() ); }
+
+ Scalar* allocateInternalLayout() const { return alignedAllocScalar( getInternalLayoutSize() ); }
+
+
+ static bool isComplexTransform() { return sizeof(T) != sizeof(Scalar); }
+
+ static bool isFloatScalar() { return sizeof(Scalar) == sizeof(float); }
+
+ static bool isDoubleScalar() { return sizeof(Scalar) == sizeof(double); }
+
static void alignedFree(void* ptr);
static T * alignedAllocType(int length);
diff --git a/test_pffft.c b/test_pffft.c
index 64e0ba7..9b52932 100644
--- a/test_pffft.c
+++ b/test_pffft.c
@@ -62,6 +62,7 @@
int Nfloat = (cplx ? N*2 : N);
float *X = pffft_aligned_malloc((unsigned)Nfloat * sizeof(float));
float *Y = pffft_aligned_malloc((unsigned)Nfloat * sizeof(float));
+ float *R = pffft_aligned_malloc((unsigned)Nfloat * sizeof(float));
float *Z = pffft_aligned_malloc((unsigned)Nfloat * sizeof(float));
float *W = pffft_aligned_malloc((unsigned)Nfloat * sizeof(float));
int k, j, m, iter, kmaxOther, retError = 0;
@@ -116,8 +117,8 @@
pffft_transform_ordered(s, X, Y, W, PFFFT_FORWARD );
else
{
- pffft_transform(s, X, Z, W, PFFFT_FORWARD ); /* temporarily use Z for reordering */
- pffft_zreorder(s, Z, Y, PFFFT_FORWARD );
+ pffft_transform(s, X, R, W, PFFFT_FORWARD ); /* use R for reordering */
+ pffft_zreorder(s, R, Y, PFFFT_FORWARD ); /* reorder into Y[] for power calculations */
}
pwrOther = -1.0;
@@ -176,7 +177,10 @@
/* now convert spectrum back */
- pffft_transform_ordered(s, Y, Z, W, PFFFT_BACKWARD);
+ if (useOrdered)
+ pffft_transform_ordered(s, Y, Z, W, PFFFT_BACKWARD);
+ else
+ pffft_transform(s, R, Z, W, PFFFT_BACKWARD);
errSum = 0.0;
for ( j = 0; j < (cplx ? (2*N) : N); ++j )
@@ -202,6 +206,7 @@
pffft_aligned_free(X);
pffft_aligned_free(Y);
pffft_aligned_free(Z);
+ pffft_aligned_free(R);
pffft_aligned_free(W);
return retError;
diff --git a/test_pffft.cpp b/test_pffft.cpp
index a544870..0601654 100644
--- a/test_pffft.cpp
+++ b/test_pffft.cpp
@@ -63,16 +63,10 @@
typedef typename pffft::Fft<T> Fft;
typedef typename Fft::Scalar Scalar;
- bool cplx = ( sizeof(T) == sizeof(std::complex<Scalar>) );
+ const bool cplx = Fft::isComplexTransform();
- double EXPECTED_DYN_RANGE = ( sizeof(double) == sizeof(Scalar) ) ? 215.0 : 140.0;
+ const double EXPECTED_DYN_RANGE = Fft::isDoubleScalar() ? 215.0 : 140.0;
- int Nsca = (cplx ? N * 2 : N);
- int Ncplx = (cplx ? N : N / 2);
- T* X = Fft::alignedAllocType(Nsca);
- T* Z = Fft::alignedAllocType(Nsca);
- Scalar* R = Fft::alignedAllocScalar(Nsca);
- std::complex<Scalar>* Y = Fft::alignedAllocComplex(Nsca);
int k, j, m, iter, kmaxOther;
bool retError = false;
double freq, dPhi, phi, phi0;
@@ -81,11 +75,18 @@
assert(pffft::isPowerOfTwo(N));
- Fft fft = Fft(N);
+ Fft fft = Fft(N); // instantiate and prepareLength() for length N
- Scalar* Xs = reinterpret_cast<Scalar*>(X);
- Scalar* Ys = reinterpret_cast<Scalar*>(Y);
- Scalar* Zs = reinterpret_cast<Scalar*>(Z);
+ T* X = fft.allocateOrigin(); // for X = input vector
+ std::complex<Scalar>* Y = fft.allocateSpectrum(); // for Y = forward(X)
+ Scalar* R = fft.allocateInternalLayout(); // for R = forwardInternalLayout(X)
+ T* Z = fft.allocateOrigin(); // for Z = inverse(Y) = inverse( forward(X) )
+ // or Z = inverseInternalLayout(R)
+
+ // work with complex - without the capabilities of a higher c++ standard
+ Scalar* Xs = reinterpret_cast<Scalar*>(X); // for X = input vector
+ Scalar* Ys = reinterpret_cast<Scalar*>(Y); // for Y = forward(X)
+ Scalar* Zs = reinterpret_cast<Scalar*>(Z); // for Z = inverse(Y) = inverse( forward(X) )
for (k = m = 0; k < (cplx ? N : (1 + N / 2)); k += N / 16, ++m) {
amp = ((m % 3) == 0) ? 1.0F : 1.1F;
@@ -122,7 +123,7 @@
fft.forward(X, Y);
else {
fft.forwardInternalLayout(X, R); /* temporarily use R for reordering */
- fft.reorderSpectrum(R, Y, PFFFT_FORWARD);
+ fft.reorderSpectrum(R, Y, PFFFT_FORWARD); /* reorder into Y[] for power calculations */
}
pwrOther = -1.0;
@@ -204,12 +205,15 @@
}
/* now convert spectrum back */
- fft.inverse(Y, Z);
+ if (useOrdered)
+ fft.inverse(Y, Z);
+ else
+ fft.inverseInternalLayout(R, Z); /* inverse() from internal Layout */
errSum = 0.0;
for (j = 0; j < (cplx ? (2 * N) : N); ++j) {
/* scale back */
- Z[j] /= N;
+ Zs[j] /= N;
/* square sum errors over real (and imag parts) */
err = (Xs[j] - Zs[j]) * (Xs[j] - Zs[j]);
errSum += err;
@@ -232,6 +236,7 @@
pffft::alignedFree(X);
pffft::alignedFree(Y);
pffft::alignedFree(Z);
+ pffft::alignedFree(R);
return retError;
}
diff --git a/test_pffft_double.c b/test_pffft_double.c
index 4a702ec..2451e91 100644
--- a/test_pffft_double.c
+++ b/test_pffft_double.c
@@ -61,6 +61,7 @@
int Ndouble = (cplx ? N*2 : N);
double *X = pffftd_aligned_malloc((unsigned)Ndouble * sizeof(double));
double *Y = pffftd_aligned_malloc((unsigned)Ndouble * sizeof(double));
+ double *R = pffftd_aligned_malloc((unsigned)Ndouble * sizeof(double));
double *Z = pffftd_aligned_malloc((unsigned)Ndouble * sizeof(double));
double *W = pffftd_aligned_malloc((unsigned)Ndouble * sizeof(double));
int k, j, m, iter, kmaxOther, retError = 0;
@@ -115,8 +116,8 @@
pffftd_transform_ordered(s, X, Y, W, PFFFT_FORWARD );
else
{
- pffftd_transform(s, X, Z, W, PFFFT_FORWARD ); /* temporarily use Z for reordering */
- pffftd_zreorder(s, Z, Y, PFFFT_FORWARD );
+ pffftd_transform(s, X, R, W, PFFFT_FORWARD ); /* use R for reordering */
+ pffftd_zreorder(s, R, Y, PFFFT_FORWARD ); /* reorder into Y[] for power calculations */
}
pwrOther = -1.0;
@@ -175,7 +176,10 @@
/* now convert spectrum back */
- pffftd_transform_ordered(s, Y, Z, W, PFFFT_BACKWARD);
+ if (useOrdered)
+ pffftd_transform_ordered(s, Y, Z, W, PFFFT_BACKWARD);
+ else
+ pffftd_transform(s, R, Z, W, PFFFT_BACKWARD);
errSum = 0.0;
for ( j = 0; j < (cplx ? (2*N) : N); ++j )
@@ -201,6 +205,7 @@
pffftd_aligned_free(X);
pffftd_aligned_free(Y);
pffftd_aligned_free(Z);
+ pffftd_aligned_free(R);
pffftd_aligned_free(W);
return retError;