annotate tests/TestMedianFilter.cpp @ 515:08bcc06c38ec tip master

Remove fast-math
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 28 Jan 2020 15:27:37 +0000
parents 2de6184b2ce0
children
rev   line source
c@391 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@391 2
c@391 3 #include "maths/MedianFilter.h"
c@391 4
c@391 5 #include <cmath>
c@407 6 #include <cstdlib>
c@391 7
c@391 8 #define BOOST_TEST_DYN_LINK
c@391 9 #define BOOST_TEST_MAIN
c@391 10
c@391 11 #include <boost/test/unit_test.hpp>
c@391 12
c@391 13 BOOST_AUTO_TEST_SUITE(TestMedianFilter)
c@391 14
c@391 15 BOOST_AUTO_TEST_CASE(odd)
c@391 16 {
c@391 17 // A median filter of size N always retains a pool of N elements,
c@391 18 // which start out all-zero. So the output median will remain zero
c@391 19 // until N/2 elements have been pushed.
c@391 20 MedianFilter<double> f(3);
cannam@476 21 f.push(1); // 0 0 1
c@391 22 BOOST_CHECK_EQUAL(f.get(), 0);
c@391 23 BOOST_CHECK_EQUAL(f.get(), 0);
cannam@476 24 f.push(-3); // 0 1 -3
c@391 25 BOOST_CHECK_EQUAL(f.get(), 0);
cannam@476 26 f.push(5); // 1 -3 5
c@391 27 BOOST_CHECK_EQUAL(f.get(), 1);
cannam@476 28 f.push(7); // -3 5 7
c@391 29 BOOST_CHECK_EQUAL(f.get(), 5);
c@391 30 BOOST_CHECK_EQUAL(f.get(), 5);
cannam@476 31 f.push(3); // 5 7 3
c@391 32 BOOST_CHECK_EQUAL(f.get(), 5);
cannam@476 33 f.push(3); // 7 3 3
c@391 34 BOOST_CHECK_EQUAL(f.get(), 3);
c@391 35 }
c@391 36
c@391 37 BOOST_AUTO_TEST_CASE(even)
c@391 38 {
c@391 39 // Our median does not halve the difference (should it??), it just
c@391 40 // returns the next element from the input set
c@391 41 MedianFilter<double> f(4);
cannam@476 42 f.push(1); // 0 0 0 1
c@391 43 BOOST_CHECK_EQUAL(f.get(), 0);
c@391 44 BOOST_CHECK_EQUAL(f.get(), 0);
cannam@476 45 f.push(-3); // 0 0 1 -3
c@391 46 BOOST_CHECK_EQUAL(f.get(), 0);
cannam@476 47 f.push(5); // 0 1 -3 5
c@391 48 BOOST_CHECK_EQUAL(f.get(), 1);
cannam@476 49 f.push(7); // 1 -3 5 7
c@391 50 BOOST_CHECK_EQUAL(f.get(), 5);
c@391 51 BOOST_CHECK_EQUAL(f.get(), 5);
cannam@476 52 f.push(3); // -3 5 7 3
c@391 53 BOOST_CHECK_EQUAL(f.get(), 5);
cannam@476 54 f.push(3); // 5 7 3 3
c@391 55 BOOST_CHECK_EQUAL(f.get(), 5);
c@391 56 }
c@391 57
c@391 58 BOOST_AUTO_TEST_CASE(odd75)
c@391 59 {
c@391 60 MedianFilter<double> f(5, 75.f);
cannam@476 61 f.push(1); // 0 0 0 0 1
c@391 62 BOOST_CHECK_EQUAL(f.get(), 0);
c@391 63 BOOST_CHECK_EQUAL(f.get(), 0);
cannam@476 64 f.push(-3); // 0 0 0 1 -3
c@391 65 BOOST_CHECK_EQUAL(f.get(), 0);
cannam@476 66 f.push(5); // 0 0 1 -3 5
c@391 67 BOOST_CHECK_EQUAL(f.get(), 1);
cannam@476 68 f.push(7); // 0 1 -3 5 7
c@391 69 BOOST_CHECK_EQUAL(f.get(), 5);
c@391 70 BOOST_CHECK_EQUAL(f.get(), 5);
cannam@476 71 f.push(3); // 0 -3 5 7 3
c@391 72 BOOST_CHECK_EQUAL(f.get(), 5);
cannam@476 73 f.push(3); // 0 5 7 3 3
c@391 74 BOOST_CHECK_EQUAL(f.get(), 5);
c@391 75 }
c@391 76
c@391 77 BOOST_AUTO_TEST_CASE(even75)
c@391 78 {
c@391 79 MedianFilter<double> f(4, 75.f);
cannam@476 80 f.push(1); // 0 0 0 1
c@391 81 BOOST_CHECK_EQUAL(f.get(), 1);
c@391 82 BOOST_CHECK_EQUAL(f.get(), 1);
cannam@476 83 f.push(-3); // 0 0 1 -3
c@391 84 BOOST_CHECK_EQUAL(f.get(), 1);
cannam@476 85 f.push(5); // 0 1 -3 5
c@391 86 BOOST_CHECK_EQUAL(f.get(), 5);
cannam@476 87 f.push(7); // 1 -3 5 7
c@391 88 BOOST_CHECK_EQUAL(f.get(), 7);
c@391 89 BOOST_CHECK_EQUAL(f.get(), 7);
cannam@476 90 f.push(3); // -3 5 7 3
c@391 91 BOOST_CHECK_EQUAL(f.get(), 7);
cannam@476 92 f.push(3); // 5 7 3 3
c@391 93 BOOST_CHECK_EQUAL(f.get(), 7);
c@391 94 }
c@391 95
c@392 96 BOOST_AUTO_TEST_CASE(oddStandalone)
c@392 97 {
c@392 98 // The standalone (static filter() method) function is intended to
c@392 99 // match e.g. MATLAB median filter, filtering a row at once
c@392 100 // assuming the values beyond its edges are zeroes. This basically
c@392 101 // just means it needs to compensate for the latency in the raw
c@392 102 // filter:
c@392 103 //
c@392 104 // Raw filter
c@392 105 // 1 3 5 7 -> 0 1 3 5 (N=3)
c@392 106 // (because at each step only the values up to that step are
c@392 107 // available)
c@392 108 //
c@392 109 // Standalone function:
c@392 110 // 1 3 5 7 -> 1 3 5 5 (N=3)
c@392 111
c@392 112 std::vector<double> in;
c@392 113 in.push_back(1);
c@392 114 in.push_back(3);
c@392 115 in.push_back(5);
c@392 116 in.push_back(7);
c@392 117
c@392 118 std::vector<double> out = MedianFilter<double>::filter(3, in);
c@392 119 BOOST_CHECK_EQUAL(out[0], 1);
c@392 120 BOOST_CHECK_EQUAL(out[1], 3);
c@392 121 BOOST_CHECK_EQUAL(out[2], 5);
c@392 122 BOOST_CHECK_EQUAL(out[3], 5);
c@392 123 }
c@392 124
c@392 125 BOOST_AUTO_TEST_CASE(evenStandalone)
c@392 126 {
c@392 127 // See above. But note that the even length does not match the
c@392 128 // MATLAB because it doesn't halve the middle, as MATLAB does
c@392 129
c@392 130 std::vector<double> in;
c@392 131 in.push_back(1);
c@392 132 in.push_back(3);
c@392 133 in.push_back(5);
c@392 134 in.push_back(7);
c@392 135
c@392 136 std::vector<double> out = MedianFilter<double>::filter(4, in);
c@392 137 BOOST_CHECK_EQUAL(out[0], 3);
c@392 138 BOOST_CHECK_EQUAL(out[1], 5);
c@392 139 BOOST_CHECK_EQUAL(out[2], 5);
c@392 140 BOOST_CHECK_EQUAL(out[3], 5);
c@392 141 }
c@392 142
c@392 143 BOOST_AUTO_TEST_CASE(standaloneEmpty)
c@392 144 {
c@392 145 std::vector<double> in;
c@392 146 std::vector<double> out1 = MedianFilter<double>::filter(3, in);
c@392 147 BOOST_CHECK_EQUAL(out1.size(), 0);
c@392 148 std::vector<double> out2 = MedianFilter<double>::filter(4, in);
c@392 149 BOOST_CHECK_EQUAL(out2.size(), 0);
c@392 150 }
c@392 151
c@392 152 BOOST_AUTO_TEST_CASE(types)
c@392 153 {
c@392 154 MedianFilter<double> dfilt(3);
c@392 155 dfilt.push(1.2);
c@392 156 BOOST_CHECK_EQUAL(dfilt.get(), 0.0);
c@392 157 dfilt.push(2.4);
c@392 158 BOOST_CHECK_EQUAL(dfilt.get(), 1.2);
c@392 159 dfilt.push(1e-6);
c@392 160 BOOST_CHECK_EQUAL(dfilt.get(), 1.2);
c@392 161 dfilt.push(1e6);
c@392 162 BOOST_CHECK_EQUAL(dfilt.get(), 2.4);
c@392 163
c@392 164 MedianFilter<int> ifilt(3);
c@392 165 ifilt.push(1);
c@392 166 BOOST_CHECK_EQUAL(ifilt.get(), 0);
c@392 167 ifilt.push(2);
c@392 168 BOOST_CHECK_EQUAL(ifilt.get(), 1);
c@392 169 ifilt.push(0);
c@392 170 BOOST_CHECK_EQUAL(ifilt.get(), 1);
c@392 171 ifilt.push(1000);
c@392 172 BOOST_CHECK_EQUAL(ifilt.get(), 2);
c@392 173 }
c@392 174
c@407 175 BOOST_AUTO_TEST_CASE(inf)
c@407 176 {
c@407 177 // Inf and -Inf should behave normally
c@407 178 double pinf = strtod("Inf", 0);
c@407 179 double ninf = strtod("-Inf", 0);
c@407 180 MedianFilter<double> dfilt(3);
c@407 181 dfilt.push(1.0);
c@407 182 dfilt.push(2.0);
c@407 183 dfilt.push(pinf);
c@407 184 BOOST_CHECK_EQUAL(dfilt.get(), 2.0);
c@407 185 dfilt.push(pinf);
c@407 186 BOOST_CHECK_EQUAL(dfilt.get(), pinf);
c@407 187 dfilt.push(pinf);
c@407 188 BOOST_CHECK_EQUAL(dfilt.get(), pinf);
c@407 189 dfilt.push(2.0);
c@407 190 BOOST_CHECK_EQUAL(dfilt.get(), pinf);
c@407 191 dfilt.push(1.0);
c@407 192 BOOST_CHECK_EQUAL(dfilt.get(), 2.0);
c@407 193 dfilt.push(ninf);
c@407 194 BOOST_CHECK_EQUAL(dfilt.get(), 1.0);
c@407 195 dfilt.push(pinf);
c@407 196 BOOST_CHECK_EQUAL(dfilt.get(), 1.0);
c@407 197 dfilt.push(ninf);
c@407 198 BOOST_CHECK_EQUAL(dfilt.get(), ninf);
c@407 199 }
c@407 200
c@407 201 BOOST_AUTO_TEST_CASE(nan)
c@407 202 {
c@407 203 // The filter should never accept a NaN, because it breaks sorting
c@407 204 // and comparison and that will break the filter. Instead it
c@407 205 // should insert 0.
c@407 206 double nan = strtod("NaN", 0);
c@407 207 MedianFilter<double> dfilt(3);
c@407 208 dfilt.push(1.0);
c@407 209 dfilt.push(2.0);
c@407 210 dfilt.push(nan);
c@407 211 BOOST_CHECK_EQUAL(dfilt.get(), 1.0);
c@407 212 dfilt.push(nan);
c@407 213 BOOST_CHECK_EQUAL(dfilt.get(), 0.0);
c@407 214 dfilt.push(-11.0);
c@407 215 BOOST_CHECK_EQUAL(dfilt.get(), 0.0);
c@407 216 dfilt.push(-1.0);
c@407 217 BOOST_CHECK_EQUAL(dfilt.get(), -1.0);
c@407 218 }
c@407 219
c@391 220 BOOST_AUTO_TEST_SUITE_END()
c@391 221
c@391 222