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;