[beast/devel: 3/6] BSE: Adapted FFT tests to new gslfft/FFTW compatible results.
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast/devel: 3/6] BSE: Adapted FFT tests to new gslfft/FFTW compatible results.
- Date: Sun, 16 Dec 2012 01:59:35 +0000 (UTC)
commit 240a47a7c802f2ee34ee727da5cbf9f4189b7fe5
Author: Stefan Westerfeld <stefan space twc de>
Date: Wed Oct 13 11:23:50 2010 +0200
BSE: Adapted FFT tests to new gslfft/FFTW compatible results.
Added DFT test from #491577, which now passes due to new style gslfft results.
bse/tests/testfft.cc | 183 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 169 insertions(+), 14 deletions(-)
---
diff --git a/bse/tests/testfft.cc b/bse/tests/testfft.cc
index 4eb6793..86b1dc3 100644
--- a/bse/tests/testfft.cc
+++ b/bse/tests/testfft.cc
@@ -24,23 +24,37 @@
#include <stdlib.h>
#include <string.h>
-
#define MAX_FFT_SIZE (65536 * 2) // * 8 * 8
+#define MAX_DFT_SIZE (1024 * 2) // * 8 * 8
#define EPSILON (4.8e-6)
+#define REF_ANALYSIS (-1)
+#define REF_SYNTHESIS (1)
/* --- prototypes --- */
static void reference_power2_fftc (unsigned int n_values,
const double *rivalues_in,
double *rivalues_out,
int esign);
+static void reference_dftc (unsigned int n_values,
+ const double *rivalues_in,
+ double *rivalues_out);
static void fill_rand (guint n,
double *a);
+static void scale_block (guint n,
+ double *a,
+ double factor);
static double diff (guint m,
guint p,
double *a1,
double *a2,
const gchar *str);
+static void make_real (guint n,
+ double *a);
+static void extract_real (guint n,
+ const double *a,
+ double *b);
+
/* --- functions --- */
@@ -58,17 +72,18 @@ main (int argc,
gettimeofday (&tv, NULL);
srand (tv.tv_sec ^ tv.tv_usec);
- double ref_fft_in[MAX_FFT_SIZE] = { 0, };
- double ref_fft_aout[MAX_FFT_SIZE] = { 0, };
- double ref_fft_sout[MAX_FFT_SIZE] = { 0, };
- double ref_fft_back[MAX_FFT_SIZE] = { 0, };
- double work_fft_in[MAX_FFT_SIZE] = { 0, };
- double work_fft_aout[MAX_FFT_SIZE] = { 0, };
- double work_fft_sout[MAX_FFT_SIZE] = { 0, };
- double work_fft_back[MAX_FFT_SIZE] = { 0, };
+ static double ref_fft_in[MAX_FFT_SIZE] = { 0, };
+ static double ref_fft_aout[MAX_FFT_SIZE] = { 0, };
+ static double ref_fft_sout[MAX_FFT_SIZE] = { 0, };
+ static double ref_fft_back[MAX_FFT_SIZE] = { 0, };
+ static double work_fft_in[MAX_FFT_SIZE] = { 0, };
+ static double work_fft_aout[MAX_FFT_SIZE] = { 0, };
+ static double work_fft_sout[MAX_FFT_SIZE] = { 0, };
+ static double work_fft_back[MAX_FFT_SIZE] = { 0, };
+ static double scaled_fft_back[MAX_FFT_SIZE] = { 0, };
/* run tests */
- for (i = 2; i <= MAX_FFT_SIZE >> 1; i <<= 1)
+ for (i = 8; i <= MAX_FFT_SIZE >> 1; i <<= 1)
{
double d;
@@ -83,14 +98,17 @@ main (int argc,
// memset (work_fft_aout, 0, MAX_FFT_SIZE * sizeof (work_fft_aout[0]));
// memset (work_fft_sout, 0, MAX_FFT_SIZE * sizeof (work_fft_sout[0]));
// memset (work_fft_back, 0, MAX_FFT_SIZE * sizeof (work_fft_sout[0]));
- reference_power2_fftc (i, ref_fft_in, ref_fft_aout, +1);
- reference_power2_fftc (i, ref_fft_in, ref_fft_sout, -1);
- reference_power2_fftc (i, ref_fft_aout, ref_fft_back, -1);
+ reference_power2_fftc (i, ref_fft_in, ref_fft_aout, REF_ANALYSIS);
+ reference_power2_fftc (i, ref_fft_in, ref_fft_sout, REF_SYNTHESIS);
+ reference_power2_fftc (i, ref_fft_aout, ref_fft_back, REF_SYNTHESIS);
+ scale_block (i << 1, ref_fft_back, 1.0 / i);
/* perform fft test */
gsl_power2_fftac (i, work_fft_in, work_fft_aout);
gsl_power2_fftsc (i, work_fft_in, work_fft_sout);
gsl_power2_fftsc (i, work_fft_aout, work_fft_back);
+ scale_block (i << 1, work_fft_back, 1.0 / i);
+ gsl_power2_fftsc_scale (i, work_fft_aout, scaled_fft_back);
/* check differences */
d = diff (i << 1, 0, ref_fft_in, work_fft_in, "Checking input record");
@@ -118,11 +136,86 @@ main (int argc,
TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
else
TOK();
+ d = diff (i << 1, 0, work_fft_in, scaled_fft_back, "GSL analysis and scaled re-synthesis");
+ if (fabs (d) > EPSILON)
+ TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ else
+ TOK();
d = diff (i << 1, 0, ref_fft_back, work_fft_back, "Reference re-synthesis vs. GSL");
if (fabs (d) > EPSILON)
TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
else
TOK();
+ d = diff (i << 1, 0, ref_fft_back, scaled_fft_back, "Reference re-synthesis vs. scaled GSL");
+ if (fabs (d) > EPSILON)
+ TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ else
+ TOK();
+
+ /* test with real data */
+ make_real (i << 1, ref_fft_in);
+ extract_real (i << 1, ref_fft_in, work_fft_in);
+ reference_power2_fftc (i, ref_fft_in, ref_fft_aout, REF_ANALYSIS);
+ ref_fft_aout[1] = ref_fft_aout[i]; /* special packing for purely real FFTs */
+
+ /* perform real fft test */
+ gsl_power2_fftar (i, work_fft_in, work_fft_aout);
+ gsl_power2_fftsr (i, work_fft_aout, work_fft_back);
+ scale_block (i, work_fft_back, 1.0 / i);
+ gsl_power2_fftsr_scale (i, work_fft_aout, scaled_fft_back);
+
+ d = diff (i, 0, ref_fft_aout, work_fft_aout, "Reference real analysis vs. real GSL");
+ if (fabs (d) > EPSILON)
+ TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ else
+ TOK();
+
+ d = diff (i, 0, work_fft_in, scaled_fft_back, "Real input vs. scaled real GSL resynthesis");
+ if (fabs (d) > EPSILON)
+ TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ else
+ TOK();
+
+ d = diff (i, 0, work_fft_in, work_fft_back, "Real input vs. real GSL resynthesis");
+ if (fabs (d) > EPSILON)
+ TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ else
+ TOK();
+
+ TDONE();
+ }
+
+ static double dft_in[MAX_DFT_SIZE] = { 0, };
+ static double dft_aout[MAX_DFT_SIZE] = { 0, };
+
+ /* test reference fft against reference dft */
+ for (i = 2; i <= MAX_DFT_SIZE >> 1; i <<= 1)
+ {
+ double d;
+
+ TSTART ("Checking reference fft for size %u", i);
+
+ /* setup reference and work fft records */
+ fill_rand (i << 1, ref_fft_in);
+ memcpy (dft_in, ref_fft_in, MAX_FFT_SIZE * sizeof (dft_in[0]));
+
+ reference_power2_fftc (i, ref_fft_in, ref_fft_aout, REF_ANALYSIS);
+ reference_dftc (i, dft_in, dft_aout);
+
+
+ /* check differences */
+ d = diff (i << 1, 0, ref_fft_in, dft_in, "Checking input record");
+ if (d)
+ TERROR ("Input record was modified");
+ else
+ TOK();
+
+ d = diff (i << 1, 0, ref_fft_aout, dft_aout, "Reference FFT analysis against reference DFT analysis");
+ if (fabs (d) > EPSILON)
+ TERROR ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ else
+ TOK();
+
TDONE();
}
@@ -137,6 +230,35 @@ fill_rand (guint n,
a[n] = -1. + 2. * rand() / (RAND_MAX + 1.0);
}
+static void
+make_real (guint n,
+ double *a)
+{
+ guint x;
+ for (x = 1; x < n; x += 2)
+ a[x] = 0; /* eliminate complex part */
+}
+
+static void
+extract_real (guint n,
+ const double *a,
+ double *b)
+{
+ guint x;
+ for (x = 0; x < n; x += 2)
+ *b++ = a[x]; /* extract real part */
+}
+
+
+static void
+scale_block (guint n,
+ double *a,
+ double factor)
+{
+ while (n--)
+ a[n] *= factor;
+}
+
static double
diff (guint m,
guint p,
@@ -296,7 +418,7 @@ reference_bitreverse_fft2synthesis (const unsigned int n,
unsigned int i, r;
double scale = n;
- scale = 1.0 / scale;
+ scale = 1; /* set to 1.0 / scale to get scaled synthesis */
BUTTERFLY_10scale (X[0], X[1],
X[n], X[n + 1],
Y[0], Y[1],
@@ -459,3 +581,36 @@ reference_power2_fftc (unsigned int n_values,
}
while (block_size <= n_values);
}
+
+/*--------------- reference DFT -----------------*/
+
+static BseComplex
+complex_exp (BseComplex z)
+{
+ /* also found in g++-4.2 C++ complex numbers */
+ return bse_complex_polar (exp(z.re), z.im);
+}
+
+void
+reference_dftc (unsigned int n_values,
+ const double *rivalues_in,
+ double *rivalues_out)
+{
+ /* http://en.wikipedia.org/wiki/Discrete_Fourier_transform says:
+ *
+ * out[k] = SUM{n=0..N-1} (in[n] * exp (-2 * pi * j / N * k * n))
+ */
+ guint k, n;
+ for (k = 0; k < n_values; k++)
+ {
+ BseComplex result = { 0, 0 };
+
+ for (n = 0; n < n_values; n++)
+ result = bse_complex_add (result,
+ bse_complex_mul (bse_complex (rivalues_in[n * 2], rivalues_in[n * 2 + 1]),
+ complex_exp (bse_complex (0, -2 * PI / n_values * ((k * n) % n_values)))));
+
+ rivalues_out[k * 2] = result.re;
+ rivalues_out[k * 2 + 1] = result.im;
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]