diff bqvec/test/TestVectorOps.cpp @ 372:af71cbdab621 tip

Update bqvec code
author Chris Cannam
date Tue, 19 Nov 2019 10:13:32 +0000
parents 5d0a2ebb4d17
children
line wrap: on
line diff
--- a/bqvec/test/TestVectorOps.cpp	Sat Nov 12 09:59:34 2016 +0000
+++ b/bqvec/test/TestVectorOps.cpp	Tue Nov 19 10:13:32 2019 +0000
@@ -1,254 +1,487 @@
 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
 
-#include "VectorOpsComplex.h"
+#include "bqvec/VectorOps.h"
 
-#include <iostream>
-#include <cstdlib>
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MAIN
 
-#include <time.h>
+#include <boost/test/unit_test.hpp>
 
-using namespace std;
+#include <stdexcept>
+#include <vector>
 
-namespace breakfastquay {
+using namespace breakfastquay;
 
-namespace Test {
+BOOST_AUTO_TEST_SUITE(TestVectorOps)
 
-#ifdef _WIN32
-#define drand48() (-1+2*((float)rand())/RAND_MAX)
-#endif
-
-bool
-testMultiply()
-{
-    cerr << "testVectorOps: testing v_multiply complex" << endl;
-
-    const int N = 1024;
-    turbot_complex_sample_t target[N];
-    turbot_complex_sample_t src1[N];
-    turbot_complex_sample_t src2[N];
-
-    for (int i = 0; i < N; ++i) {
-	src1[i].re = drand48();
-	src1[i].im = drand48();
-	src2[i].re = drand48();
-	src2[i].im = drand48();
+#define COMPARE_ARRAY(a, b)						\
+    for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
+        BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14);			\
     }
 
-    turbot_sample_t mean, first, last, total = 0;
-    for (int i = 0; i < N; ++i) {
-        turbot_complex_sample_t result;
-        c_multiply(result, src1[i], src2[i]);
-	if (i == 0) first = result.re;
-	if (i == N-1) last = result.im;
-	total += result.re;
-	total += result.im;
+#define COMPARE_N(a, b, n)						\
+    for (int cmp_i = 0; cmp_i < n; ++cmp_i) { \
+        BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14);			\
     }
-    mean = total / (N*2);
-    cerr << "Naive method: mean = " << mean << ", first = " << first
-	 << ", last = " << last << endl;
 
-    v_multiply(target, src1, src2, N);
-    total = 0;
-
-    for (int i = 0; i < N; ++i) {
-	if (i == 0) first = target[i].re;
-	if (i == N-1) last = target[i].im;
-	total += target[i].re;
-	total += target[i].im;
-    }
-    mean = total / (N*2);
-    cerr << "v_multiply: mean = " << mean << ", first = " << first
-	 << ", last = " << last << endl;
-
-    int iterations = 50000;
-    cerr << "Iterations: " << iterations << endl;
-	
-    cerr << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << endl;
-    float divisor = float(CLOCKS_PER_SEC) / 1000.f;
-
-    clock_t start = clock();
-
-    for (int j = 0; j < iterations; ++j) {
-	for (int i = 0; i < N; ++i) {
-            c_multiply(target[i], src1[i], src2[i]);
-	}
-    }
-    
-    clock_t end = clock();
-
-    cerr << "Time for naive method: " << float(end - start)/divisor << endl;
-
-    start = clock();
-
-    for (int j = 0; j < iterations; ++j) {
-        v_multiply(target, src1, src2, N);
-    }
-    
-    end = clock();
-
-    cerr << "Time for v_multiply: " << float(end - start)/divisor << endl;
-
-    return true;
+BOOST_AUTO_TEST_CASE(add)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { -1.0, 3.0, -4.5 };
+    double expected[] = { 0.0, 5.0, -1.5 };
+    v_add(a, b, 3);
+    COMPARE_N(a, expected, 3);
 }
 
-bool
-testPolarToCart()
+BOOST_AUTO_TEST_CASE(add_with_gain)
 {
-    cerr << "testVectorOps: testing v_polar_to_cartesian" << endl;
-
-    const int N = 1024;
-    turbot_complex_sample_t target[N];
-    turbot_sample_t mag[N];
-    turbot_sample_t phase[N];
-
-    for (int i = 0; i < N; ++i) {
-	mag[i] = drand48();
-	phase[i] = (drand48() * M_PI * 2) - M_PI;
-    }
-
-    turbot_sample_t mean, first, last, total = 0;
-    for (int i = 0; i < N; ++i) {
-	turbot_sample_t real = mag[i] * cos(phase[i]);
-	turbot_sample_t imag = mag[i] * sin(phase[i]);
-	if (i == 0) first = real;
-	if (i == N-1) last = imag;
-	total += real;
-	total += imag;
-    }
-    mean = total / (N*2);
-    cerr << "Naive method: mean = " << mean << ", first = " << first
-	 << ", last = " << last << endl;
-
-    v_polar_to_cartesian(target, mag, phase, N);
-
-    total = 0;
-
-    for (int i = 0; i < N; ++i) {
-	if (i == 0) first = target[i].re;
-	if (i == N-1) last = target[i].im;
-	total += target[i].re;
-	total += target[i].im;
-    }
-    mean = total / (N*2);
-    cerr << "v_polar_to_cartesian: mean = " << mean << ", first = " << first
-	 << ", last = " << last << endl;
-
-    int iterations = 10000;
-    cerr << "Iterations: " << iterations << endl;
-	
-    cerr << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << endl;
-    float divisor = float(CLOCKS_PER_SEC) / 1000.f;
-
-    clock_t start = clock();
-
-    for (int j = 0; j < iterations; ++j) {
-	for (int i = 0; i < N; ++i) {
-	    target[i].re = mag[i] * cos(phase[i]);
-	    target[i].im = mag[i] * sin(phase[i]);
-	}
-    }
-    
-    clock_t end = clock();
-
-    cerr << "Time for naive method: " << float(end - start)/divisor << endl;
-
-    start = clock();
-
-    for (int j = 0; j < iterations; ++j) {
-	v_polar_to_cartesian(target, mag, phase, N);
-    }
-    
-    end = clock();
-
-    cerr << "Time for v_polar_to_cartesian: " << float(end - start)/divisor << endl;
-
-    return true;
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { -1.0, 3.0, -4.5 };
+    double expected[] = { -0.5, 6.5, -3.75 };
+    v_add_with_gain(a, b, 1.5, 3);
+    COMPARE_N(a, expected, 3);
 }
 
-bool
-testPolarToCartInterleaved()
+BOOST_AUTO_TEST_CASE(subtract)
 {
-    cerr << "testVectorOps: testing v_polar_interleaved_to_cartesian" << endl;
-
-    const int N = 1024;
-    turbot_complex_sample_t target[N];
-    turbot_sample_t source[N*2];
-
-    for (int i = 0; i < N; ++i) {
-	source[i*2] = drand48();
-	source[i*2+1] = (drand48() * M_PI * 2) - M_PI;
-    }
-
-    turbot_sample_t mean, first, last, total = 0;
-    for (int i = 0; i < N; ++i) {
-	turbot_sample_t real = source[i*2] * cos(source[i*2+1]);
-	turbot_sample_t imag = source[i*2] * sin(source[i*2+1]);
-	if (i == 0) first = real;
-	if (i == N-1) last = imag;
-	total += real;
-	total += imag;
-    }
-    mean = total / (N*2);
-    cerr << "Naive method: mean = " << mean << ", first = " << first
-	 << ", last = " << last << endl;
-
-    v_polar_interleaved_to_cartesian(target, source, N);
-
-    total = 0;
-
-    for (int i = 0; i < N; ++i) {
-	if (i == 0) first = target[i].re;
-	if (i == N-1) last = target[i].im;
-	total += target[i].re;
-	total += target[i].im;
-    }
-    mean = total / (N*2);
-    cerr << "v_polar_interleaved_to_cartesian: mean = " << mean << ", first = " << first
-	 << ", last = " << last << endl;
-
-    int iterations = 10000;
-    cerr << "Iterations: " << iterations << endl;
-	
-    cerr << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << endl;
-    float divisor = float(CLOCKS_PER_SEC) / 1000.f;
-
-    clock_t start = clock();
-
-    for (int j = 0; j < iterations; ++j) {
-	for (int i = 0; i < N; ++i) {
-	    target[i].re = source[i*2] * cos(source[i*2+1]);
-	    target[i].im = source[i*2] * sin(source[i*2+1]);
-	}
-    }
-    
-    clock_t end = clock();
-
-    cerr << "Time for naive method: " << float(end - start)/divisor << endl;
-
-    start = clock();
-
-    for (int j = 0; j < iterations; ++j) {
-	v_polar_interleaved_to_cartesian(target, source, N);
-    }
-    
-    end = clock();
-
-    cerr << "Time for v_polar_interleaved_to_cartesian: " << float(end - start)/divisor << endl;
-
-    return true;
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { -1.0, 3.0, -4.5 };
+    double expected[] = { 2.0, -1.0, 7.5 };
+    v_subtract(a, b, 3);
+    COMPARE_N(a, expected, 3);
 }
 
-bool
-testVectorOps()
+BOOST_AUTO_TEST_CASE(increment)
 {
-    if (!testMultiply()) return false;
-    if (!testPolarToCart()) return false;
-    if (!testPolarToCartInterleaved()) return false;
-    
-    return true;
+    double a[] = { -1.0, 3.0, -4.5 };
+    double incr = -0.5;
+    double expected[] = { -1.5, 2.5, -5.0 };
+    v_increment(a, incr, 3);
+    COMPARE_N(a, expected, 3);
 }
 
+BOOST_AUTO_TEST_CASE(scale)
+{
+    double a[] = { -1.0, 3.0, -4.5 };
+    double scale = -0.5;
+    double expected[] = { 0.5, -1.5, 2.25 };
+    v_scale(a, scale, 3);
+    COMPARE_N(a, expected, 3);
 }
 
+BOOST_AUTO_TEST_CASE(multiply)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { -1.0, 3.0, -4.5 };
+    double expected[] = { -1.0, 6.0, -13.5 };
+    v_multiply(a, b, 3);
+    COMPARE_N(a, expected, 3);
 }
 
+BOOST_AUTO_TEST_CASE(multiply_to)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { -1.0, 3.0, -4.5 };
+    double o[3];
+    double expected[] = { -1.0, 6.0, -13.5 };
+    v_multiply_to(o, a, b, 3);
+    COMPARE_N(o, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(multiply_and_add)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { -1.0, 3.0, -4.5 };
+    double c[] = { 3.0, -1.0, 4.0 };
+    double expected[] = { 2.0, 5.0, -9.5 };
+    v_multiply_and_add(c, a, b, 3);
+    COMPARE_N(c, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(divide)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { -1.0, 3.0, -4.5 };
+    double expected[] = { -1.0, 2.0/3.0, 3.0/-4.5 };
+    v_divide(a, b, 3);
+    COMPARE_N(a, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(sum)
+{
+    double a[] = { 1.0, 2.0, -3.5 };
+    double s = v_sum(a, 3);
+    BOOST_CHECK_EQUAL(s, -0.5);
+}
+
+BOOST_AUTO_TEST_CASE(multiply_and_sum)
+{
+    double a[] = { 2.0, 0.0, -1.5 };
+    double b[] = { 3.0, 4.0, 5.0 };
+    double s = v_multiply_and_sum(a, b, 3);
+    BOOST_CHECK_EQUAL(s, -1.5);
+}
+
+BOOST_AUTO_TEST_CASE(log)
+{
+    double a[] = { 1.0, 1.0 / M_E, M_E };
+    double expected[] = { 0.0, -1.0, 1.0 };
+    v_log(a, 3);
+    COMPARE_N(a, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(exp)
+{
+    double a[] = { 0.0, -1.0, 2.0 };
+    double expected[] = { 1.0, 1.0 / M_E, M_E * M_E };
+    v_exp(a, 3);
+    COMPARE_N(a, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(sqrt)
+{
+    double a[] = { 0.0, 1.0, 4.0 };
+    double expected[] = { 0.0, 1.0, 2.0 };
+    v_sqrt(a, 3);
+    COMPARE_N(a, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(square)
+{
+    double a[] = { 0.0, 1.5, -2.0 };
+    double expected[] = { 0.0, 2.25, 4.0 };
+    v_square(a, 3);
+    COMPARE_N(a, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(abs)
+{
+    double a[] = { -1.9, 0.0, 0.01, -0.0 };
+    double expected[] = { 1.9, 0.0, 0.01, 0.0 };
+    v_abs(a, 4);
+    COMPARE_N(a, expected, 4);
+}
+
+BOOST_AUTO_TEST_CASE(mean)
+{
+    double a[] = { -1.0, 1.6, 3.0 };
+    double s = v_mean(a, 3);
+    BOOST_CHECK_EQUAL(s, 1.2);
+}
+
+BOOST_AUTO_TEST_CASE(interleave_1)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double *ch[] = { a };
+    double o[3];
+    double expected[] = { 1.0, 2.0, 3.0 };
+    v_interleave(o, ch, 1, 3);
+    COMPARE_N(o, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(interleave_2)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { 4.0, 5.0, 6.0 };
+    double *ch[] = { a, b };
+    double o[6];
+    double expected[] = { 1.0, 4.0, 2.0, 5.0, 3.0, 6.0 };
+    v_interleave(o, ch, 2, 3);
+    COMPARE_N(o, expected, 6);
+}
+
+BOOST_AUTO_TEST_CASE(interleave_3)
+{
+    double a[] = { 1.0, 2.0 };
+    double b[] = { 3.0, 4.0 };
+    double c[] = { 5.0, 6.0 };
+    double *ch[] = { a, b, c };
+    double o[6];
+    double expected[] = { 1.0, 3.0, 5.0, 2.0, 4.0, 6.0 };
+    v_interleave(o, ch, 3, 2);
+    COMPARE_N(o, expected, 6);
+}
+
+BOOST_AUTO_TEST_CASE(deinterleave_1)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double o[3];
+    double *oo[] = { o };
+    double *expected[] = { a };
+    v_deinterleave(oo, a, 1, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+}
+
+BOOST_AUTO_TEST_CASE(deinterleave_2)
+{
+    double a[] = { 1.0, 4.0, 2.0, 5.0, 3.0, 6.0 };
+    double o1[3], o2[3];
+    double *oo[] = { o1, o2 };
+    double e1[] = { 1.0, 2.0, 3.0 }, e2[] = { 4.0, 5.0, 6.0 };
+    double *expected[] = { e1, e2 };
+    v_deinterleave(oo, a, 2, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+    COMPARE_N(oo[1], expected[1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(deinterleave_3)
+{
+    double a[] = { 1.0, 3.0, 5.0, 2.0, 4.0, 6.0 };
+    double o1[2], o2[2], o3[2];
+    double *oo[] = { o1, o2, o3 };
+    double e1[] = { 1.0, 2.0 }, e2[] = { 3.0, 4.0 }, e3[] = { 5.0, 6.0 };
+    double *expected[] = { e1, e2, e3 };
+    v_deinterleave(oo, a, 3, 2);
+    COMPARE_N(oo[0], expected[0], 2);
+    COMPARE_N(oo[1], expected[1], 2);
+    COMPARE_N(oo[2], expected[2], 2);
+}
+
+BOOST_AUTO_TEST_CASE(mix_1)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double *ch[] = { a };
+    double o[3];
+    double expected[] = { 1.0, 2.0, 3.0 };
+    v_mix(o, ch, 1, 3);
+    COMPARE_N(o, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(mix_2)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double b[] = { 4.0, 5.0, 6.0 };
+    double *ch[] = { a, b };
+    double o[6];
+    double expected[] = { 2.5, 3.5, 4.5 };
+    v_mix(o, ch, 2, 3);
+    COMPARE_N(o, expected, 3);
+}
+
+BOOST_AUTO_TEST_CASE(mix_3)
+{
+    double a[] = { 1.0, 2.0 };
+    double b[] = { 3.0, 4.0 };
+    double c[] = { 5.0, 6.0 };
+    double *ch[] = { a, b, c };
+    double o[6];
+    double expected[] = { 3.0, 4.0 };
+    v_mix(o, ch, 3, 2);
+    COMPARE_N(o, expected, 2);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_1_2)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double *aa[] = { a };
+    double o1[3], o2[3];
+    double *oo[] = { o1, o2 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 1.0, 2.0, 3.0 };
+    double *expected[] = { e1, e2 };
+    v_reconfigure_channels(oo, 2, aa, 1, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+    COMPARE_N(oo[1], expected[1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_2_1)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double *aa[] = { a1, a2 };
+    double o1[3];
+    double *oo[] = { o1 };
+    double e1[] = { 2.5, 3.5, 4.5 };
+    double *expected[] = { e1 };
+    v_reconfigure_channels(oo, 1, aa, 2, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_3_1)
+{
+    double a1[] = { 1.0, 2.0 };
+    double a2[] = { 3.0, 4.0 };
+    double a3[] = { 5.0, 6.0 };
+    double *aa[] = { a1, a2, a3 };
+    double o1[2];
+    double *oo[] = { o1 };
+    double e1[] = { 3.0, 4.0 };
+    double *expected[] = { e1 };
+    v_reconfigure_channels(oo, 1, aa, 3, 2);
+    COMPARE_N(oo[0], expected[0], 2);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_1_3)
+{
+    double a[] = { 1.0, 2.0, 3.0 };
+    double *aa[] = { a };
+    double o1[3], o2[3], o3[3];
+    double *oo[] = { o1, o2, o3 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 1.0, 2.0, 3.0 };
+    double e3[] = { 1.0, 2.0, 3.0 };
+    double *expected[] = { e1, e2, e3 };
+    v_reconfigure_channels(oo, 3, aa, 1, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+    COMPARE_N(oo[1], expected[1], 3);
+    COMPARE_N(oo[2], expected[2], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_2_3)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double *aa[] = { a1, a2 };
+    double o1[3], o2[3], o3[3];
+    double *oo[] = { o1, o2, o3 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 0.0, 0.0, 0.0 };
+    double e3[] = { 4.0, 5.0, 6.0 };
+    double *expected[] = { e1, e2, e3 };
+    v_reconfigure_channels(oo, 3, aa, 2, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+    COMPARE_N(oo[1], expected[1], 3);
+    COMPARE_N(oo[2], expected[2], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_3_2)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double a3[] = { 7.0, 8.0, 9.0 };
+    double *aa[] = { a1, a2, a3 };
+    double o1[3], o2[3];
+    double *oo[] = { o1, o2 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 7.0, 8.0, 9.0 };
+    double *expected[] = { e1, e2 };
+    v_reconfigure_channels(oo, 2, aa, 3, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+    COMPARE_N(oo[1], expected[1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_3_3)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double a3[] = { 7.0, 8.0, 9.0 };
+    double *aa[] = { a1, a2, a3 };
+    double o1[3], o2[3], o3[3];
+    double *oo[] = { o1, o2, o3 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 4.0, 5.0, 6.0 };
+    double e3[] = { 7.0, 8.0, 9.0 };
+    double *expected[] = { e1, e2, e3 };
+    v_reconfigure_channels(oo, 3, aa, 3, 3);
+    COMPARE_N(oo[0], expected[0], 3);
+    COMPARE_N(oo[1], expected[1], 3);
+    COMPARE_N(oo[2], expected[2], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_1_2_inplace)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[3];
+    double *aa[] = { a1, a2 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 1.0, 2.0, 3.0 };
+    double *expected[] = { e1, e2 };
+    v_reconfigure_channels_inplace(aa, 2, 1, 3);
+    COMPARE_N(aa[0], expected[0], 3);
+    COMPARE_N(aa[1], expected[1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_2_1_inplace)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double *aa[] = { a1, a2 };
+    double e1[] = { 2.5, 3.5, 4.5 };
+    double *expected[] = { e1 };
+    v_reconfigure_channels_inplace(aa, 1, 2, 3);
+    COMPARE_N(aa[0], expected[0], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_3_1_inplace)
+{
+    double a1[] = { 1.0, 2.0 };
+    double a2[] = { 3.0, 4.0 };
+    double a3[] = { 5.0, 6.0 };
+    double *aa[] = { a1, a2, a3 };
+    double e1[] = { 3.0, 4.0 };
+    double *expected[] = { e1 };
+    v_reconfigure_channels_inplace(aa, 1, 3, 2);
+    COMPARE_N(aa[0], expected[0], 2);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_1_3_inplace)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[3], a3[3];
+    double *aa[] = { a1, a2, a3 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 1.0, 2.0, 3.0 };
+    double e3[] = { 1.0, 2.0, 3.0 };
+    double *expected[] = { e1, e2, e3 };
+    v_reconfigure_channels_inplace(aa, 3, 1, 3);
+    COMPARE_N(aa[0], expected[0], 3);
+    COMPARE_N(aa[1], expected[1], 3);
+    COMPARE_N(aa[2], expected[2], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_2_3_inplace)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double a3[3];
+    double *aa[] = { a1, a2, a3 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 4.0, 5.0, 6.0 };
+    double e3[] = { 0.0, 0.0, 0.0 };
+    double *expected[] = { e1, e2, e3 };
+    v_reconfigure_channels_inplace(aa, 3, 2, 3);
+    COMPARE_N(aa[0], expected[0], 3);
+    COMPARE_N(aa[1], expected[1], 3);
+    COMPARE_N(aa[2], expected[2], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_3_2_inplace)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double a3[] = { 7.0, 8.0, 9.0 };
+    double *aa[] = { a1, a2, a3 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 4.0, 5.0, 6.0 };
+    double *expected[] = { e1, e2 };
+    v_reconfigure_channels_inplace(aa, 2, 3, 3);
+    COMPARE_N(aa[0], expected[0], 3);
+    COMPARE_N(aa[1], expected[1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(reconfigure_3_3_inplace)
+{
+    double a1[] = { 1.0, 2.0, 3.0 };
+    double a2[] = { 4.0, 5.0, 6.0 };
+    double a3[] = { 7.0, 8.0, 9.0 };
+    double *aa[] = { a1, a2, a3 };
+    double e1[] = { 1.0, 2.0, 3.0 };
+    double e2[] = { 4.0, 5.0, 6.0 };
+    double e3[] = { 7.0, 8.0, 9.0 };
+    double *expected[] = { e1, e2, e3 };
+    v_reconfigure_channels_inplace(aa, 3, 3, 3);
+    COMPARE_N(aa[0], expected[0], 3);
+    COMPARE_N(aa[1], expected[1], 3);
+    COMPARE_N(aa[2], expected[2], 3);
+}
+
+BOOST_AUTO_TEST_CASE(fftshift)
+{
+    double a[] = { 0.1, 2.0, -0.3, 4.0 };
+    double e[] = { -0.3, 4.0, 0.1, 2.0 };
+    v_fftshift(a, 4);
+    COMPARE_N(a, e, 4);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+