1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
#include "../../algorithms/convolutions.h"
#include <boost/test/unit_test.hpp>
#include <cmath>
using algorithms::Convolutions;
BOOST_AUTO_TEST_SUITE(convolutions, *boost::unit_test::label("algorithms"))
BOOST_AUTO_TEST_CASE(one_dimensional_convolution,
*boost::unit_test::tolerance(num_t(1e-5))) {
// Remember that OneDimensionalConvolutionBorderInterp assumes that sumover
// kernel == 1, otherwise we have to multiply the output with sumover kernel.
num_t data1[3] = {0.0, 1.0, 2.0};
num_t kernel1[1] = {1.0};
Convolutions::OneDimensionalConvolutionBorderInterp(data1, 3, kernel1, 1);
BOOST_CHECK_CLOSE(data1[0], 0.0, 1e-6);
BOOST_CHECK_CLOSE(data1[1], 1.0, 1e-6);
BOOST_CHECK_CLOSE(data1[2], 2.0, 1e-6);
num_t kernel2[1] = {0.0};
Convolutions::OneDimensionalConvolutionBorderInterp(data1, 3, kernel2, 1);
num_t data3[4] = {0.0, 1.0, 2.0, 3.0};
num_t kernel3[1] = {2.0};
Convolutions::OneDimensionalConvolutionBorderInterp(data3, 4, kernel3, 1);
BOOST_TEST(data3[0] == 0.0);
BOOST_TEST(data3[1] == 1.0);
BOOST_TEST(data3[2] == 2.0);
BOOST_TEST(data3[3] == 3.0);
num_t kernel4[2] = {0.0, 1.0};
Convolutions::OneDimensionalConvolutionBorderInterp(data3, 4, kernel4, 2);
BOOST_TEST(data3[0] == 0.0);
BOOST_TEST(data3[1] == 1.0);
BOOST_TEST(data3[2] == 2.0);
BOOST_TEST(data3[3] == 3.0);
num_t kernel5[2] = {1.0, 1.0};
Convolutions::OneDimensionalConvolutionBorderInterp(data3, 4, kernel5, 2);
BOOST_TEST(data3[0] == 0.0);
BOOST_TEST(data3[1] == 0.5);
BOOST_TEST(data3[2] == 1.5);
BOOST_TEST(data3[3] == 2.5);
num_t data6[4] = {0.0, 1.0, 2.0, 3.0};
num_t kernel6[3] = {1.0, 1.0, 1.0};
Convolutions::OneDimensionalConvolutionBorderInterp(data6, 4, kernel6, 3);
num_t expected6[4] = {0.5, 1.0, 2.0, 2.5};
BOOST_TEST(data6 == expected6, boost::test_tools::per_element());
num_t data7[6] = {0.0, 0.0, 1.0, 2.0, 3.0, 0.0};
num_t kernel7[3] = {1.0, 1.0, 1.0};
Convolutions::OneDimensionalConvolutionBorderInterp(data7, 6, kernel7, 3);
num_t expected7[6] = {0.0, 1.0 / 3.0, 1.0, 2.0, 5.0 / 3.0, 1.5};
BOOST_TEST(data7 == expected7, boost::test_tools::per_element());
}
BOOST_AUTO_TEST_CASE(one_dimensional_sinc_convolution,
*boost::unit_test::tolerance(num_t(1e-5))) {
num_t data1[1] = {1.0};
Convolutions::OneDimensionalSincConvolution(data1, 1, 1.0);
const num_t expected1[1] = {1.0};
BOOST_TEST(data1[0] == expected1[0]);
Convolutions::OneDimensionalSincConvolution(data1, 0, 1.0);
num_t data2[2] = {1.0, 1.0};
Convolutions::OneDimensionalSincConvolution(data2, 2, 0.25);
// const num_t expected2[2] = { 1.0, 1.0 };
// AssertValues(this, data2, expected2, 2);
BOOST_TEST(data2[0] == data2[1]);
num_t data3[3] = {1.0, 1.0, 1.0};
Convolutions::OneDimensionalSincConvolution(data3, 3, 0.25);
BOOST_TEST(data3[0] == data3[2]);
num_t data4[4] = {1.0, 1.0, 1.0, 1.0};
Convolutions::OneDimensionalSincConvolution(data4, 4, 0.25);
BOOST_TEST(data4[0] == data4[3]);
BOOST_TEST(data4[1] == data4[2]);
const num_t sizes5[6] = {0.01, 0.1, 1.0, 3.14, 10.0 / 3.0, 100.0};
for (unsigned i = 0; i < 6; ++i) {
num_t data5[5] = {0.0, 0.0, 1.0, 0.0, 0.0};
Convolutions::OneDimensionalSincConvolution(data5, 5, sizes5[i]);
BOOST_TEST(data5[0] == data5[4]);
BOOST_TEST(data5[1] == data5[3]);
}
num_t data6[100];
data6[0] = 1;
for (unsigned i = 1; i < 100; ++i) data6[i] = 0;
// Convolution with sinc frequency 0.25 will produce a low-pass filter
// that filters any frequency > 0.25 Hz. The sinc will therefore have
// maxima on index 1, 5, 9, ..., minima on index 3, 7, 11, .. and zero's
// on 2, 4, 6, 8, ... .
Convolutions::OneDimensionalSincConvolution(data6, 100, 0.25);
// Check whether maxima decrease
for (unsigned i = 1; i < 96; i += 4) {
BOOST_CHECK_LT(data6[i + 4], data6[i]);
}
// Check whether minima increase. The border value (i=95) is not tested,
// because of the normalization it is actually larger, which is ok.
for (unsigned i = 3; i < 94; i += 4) {
BOOST_CHECK_GT(data6[i + 4], data6[i]);
}
// Check zero points
for (unsigned i = 2; i < 100; i += 2) {
BOOST_TEST(data6[i] == 0.0f);
}
// Test whether a low-pass filter attenuates a 10.000 sample
// high-frequency chirp signal with various levels.
num_t data7[10000];
for (unsigned i = 0; i < 10000; i += 2) {
data7[i] = -1;
data7[i + 1] = 1;
}
Convolutions::OneDimensionalSincConvolution(data7, 10000, 0.25);
for (unsigned i = 10; i < 9990; ++i) {
BOOST_CHECK_LT(std::abs(data7[i]), 0.1);
}
for (unsigned i = 100; i < 9900; ++i) {
BOOST_CHECK_LT(std::abs(data7[i]), 0.01);
}
for (unsigned i = 1000; i < 9000; ++i) {
BOOST_CHECK_LT(std::abs(data7[i]), 0.001);
}
// Test whether a low-pass filter does not attenuate a 10.000 sample
// low-frequency chirp signal with various levels.
num_t data8[10000];
for (unsigned i = 0; i < 10000; ++i) {
data8[i] = sin((num_t)i / (10.0 * 2 * M_PIn));
}
Convolutions::OneDimensionalSincConvolution(data8, 10000, 0.25);
for (unsigned i = 10; i < 9950; ++i) {
num_t val = sin((num_t)i / (10.0 * 2 * M_PIn));
BOOST_CHECK_LT(std::abs(data8[i] - val), 0.5);
}
for (unsigned i = 100; i < 9900; ++i) {
num_t val = sin((num_t)i / (10.0 * 2 * M_PIn));
BOOST_CHECK_LT(std::abs(data8[i] - val), 0.1);
}
for (unsigned i = 1000; i < 9000; ++i) {
num_t val = sin((num_t)i / (10.0 * 2 * M_PIn));
BOOST_CHECK_LT(std::abs(data8[i] - val), 0.01);
}
}
BOOST_AUTO_TEST_SUITE_END()
|