annotate base/test/TestMovingMedian.h @ 1874:48f50a4a82ea

Merge from branch csv-import-headers
author Chris Cannam
date Thu, 18 Jun 2020 13:43:20 +0100
parents cfcfec216c21
children
rev   line source
Chris@1573 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1573 2
Chris@1573 3 /*
Chris@1573 4 Sonic Visualiser
Chris@1573 5 An audio file viewer and annotation editor.
Chris@1573 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1573 7
Chris@1573 8 This program is free software; you can redistribute it and/or
Chris@1573 9 modify it under the terms of the GNU General Public License as
Chris@1573 10 published by the Free Software Foundation; either version 2 of the
Chris@1573 11 License, or (at your option) any later version. See the file
Chris@1573 12 COPYING included with this distribution for more information.
Chris@1573 13 */
Chris@1573 14
Chris@1573 15 #ifndef TEST_MOVING_MEDIAN_H
Chris@1573 16 #define TEST_MOVING_MEDIAN_H
Chris@1573 17
Chris@1573 18 #include "../MovingMedian.h"
Chris@1573 19
Chris@1573 20 #include <QObject>
Chris@1573 21 #include <QtTest>
Chris@1573 22 #include <QDir>
Chris@1573 23
Chris@1573 24 #include <iostream>
Chris@1573 25
Chris@1573 26 using namespace std;
Chris@1573 27
Chris@1573 28 class TestMovingMedian : public QObject
Chris@1573 29 {
Chris@1573 30 Q_OBJECT
Chris@1573 31
Chris@1573 32 template <typename T>
Chris@1573 33 void checkExpected(const vector<T> &output,
Chris@1573 34 const vector<T> &expected) {
Chris@1573 35 if (output.size() != expected.size()) {
Chris@1574 36 std::cerr << "ERROR: output array size " << output.size()
Chris@1574 37 << " differs from expected size " << expected.size()
Chris@1574 38 << std::endl;
Chris@1573 39 }
Chris@1573 40 for (int i = 0; i < int(output.size()); ++i) {
Chris@1573 41 if (output[i] != expected[i]) {
Chris@1574 42 std::cerr << "ERROR: Value at index " << i
Chris@1574 43 << " in output array differs from expected"
Chris@1574 44 << std::endl;
Chris@1574 45 std::cerr << "Output: ";
Chris@1574 46 for (auto v: output) std::cerr << v << " ";
Chris@1574 47 std::cerr << "\nExpected: ";
Chris@1574 48 for (auto v: expected) std::cerr << v << " ";
Chris@1574 49 std::cerr << std::endl;
Chris@1573 50 break;
Chris@1573 51 }
Chris@1573 52 }
Chris@1573 53 QCOMPARE(output, expected);
Chris@1573 54 }
Chris@1573 55
Chris@1573 56 template <typename T>
Chris@1573 57 void testFixed(int n,
Chris@1573 58 const vector<T> &input,
Chris@1573 59 const vector<T> &expected,
Chris@1573 60 double percentile = 50.0) {
Chris@1573 61 vector<T> output;
Chris@1573 62 MovingMedian<T> mm(n, percentile);
Chris@1573 63 for (auto v: input) {
Chris@1573 64 mm.push(v);
Chris@1573 65 mm.checkIntegrity();
Chris@1573 66 output.push_back(mm.get());
Chris@1573 67 }
Chris@1573 68 mm.checkIntegrity();
Chris@1573 69 checkExpected<T>(output, expected);
Chris@1573 70 }
Chris@1573 71
Chris@1573 72 private slots:
Chris@1573 73
Chris@1573 74 void empty() {
Chris@1573 75 MovingMedian<double> mm(3);
Chris@1573 76 QCOMPARE(mm.get(), 0.0);
Chris@1573 77 }
Chris@1573 78
Chris@1573 79 void zeros() {
Chris@1573 80 vector<double> input { 0.0, 0.0, 0.0, 0.0, 0.0 };
Chris@1573 81 vector<double> expected { 0.0, 0.0, 0.0, 0.0, 0.0 };
Chris@1573 82 testFixed<double>(3, input, expected);
Chris@1573 83 }
Chris@1573 84
Chris@1573 85 void ascending() {
Chris@1573 86 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 87 vector<double> expected { 0.0, 1.0, 2.0, 3.0, 4.0 };
Chris@1573 88 testFixed<double>(3, input, expected);
Chris@1573 89 }
Chris@1573 90
Chris@1573 91 void ascendingInt() {
Chris@1573 92 vector<int> input { 1, 2, 3, 4, 5 };
Chris@1573 93 vector<int> expected { 0, 1, 2, 3, 4 };
Chris@1573 94 testFixed<int>(3, input, expected);
Chris@1573 95 }
Chris@1573 96
Chris@1573 97 void descending() {
Chris@1573 98 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
Chris@1573 99 vector<double> expected { 0.0, 4.0, 4.0, 3.0, 2.0 };
Chris@1573 100 testFixed<double>(3, input, expected);
Chris@1573 101 }
Chris@1573 102
Chris@1573 103 void descendingInt() {
Chris@1573 104 vector<int> input { 5, 4, 3, 2, 1 };
Chris@1573 105 vector<int> expected { 0, 4, 4, 3, 2 };
Chris@1573 106 testFixed<int>(3, input, expected);
Chris@1573 107 }
Chris@1573 108
Chris@1573 109 void duplicates() {
Chris@1573 110 vector<double> input { 2.0, 2.0, 3.0, 4.0, 3.0 };
Chris@1573 111 vector<double> expected { 0.0, 2.0, 2.0, 3.0, 3.0 };
Chris@1573 112 testFixed<double>(3, input, expected);
Chris@1573 113 }
Chris@1573 114
Chris@1573 115 void percentile10() {
Chris@1573 116 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 117 vector<double> expected { 0.0, 0.0, 1.0, 2.0, 3.0 };
Chris@1573 118 testFixed<double>(3, input, expected, 10);
Chris@1573 119 }
Chris@1573 120
Chris@1573 121 void percentile90() {
Chris@1573 122 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 123 vector<double> expected { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 124 testFixed<double>(3, input, expected, 90);
Chris@1573 125 }
Chris@1573 126
Chris@1573 127 void even() {
Chris@1573 128 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
Chris@1573 129 vector<double> expected { 0.0, 4.0, 4.0, 4.0, 3.0 };
Chris@1573 130 testFixed<double>(4, input, expected);
Chris@1573 131 }
Chris@1573 132
Chris@1573 133 void growing() {
Chris@1573 134 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
Chris@1573 135 vector<double> expected { 2.0, 4.0, 4.0, 3.0, 2.5, 2.5, 2.5, 2.5, 2.0, 1.0 };
Chris@1573 136 vector<double> output;
Chris@1573 137 MovingMedian<double> mm(1);
Chris@1573 138 for (int i = 0; i < int(input.size()); ++i) {
Chris@1573 139 // sizes 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
Chris@1573 140 int sz = i/2 + 1;
Chris@1573 141 mm.resize(sz);
Chris@1573 142 QCOMPARE(mm.size(), sz);
Chris@1573 143 mm.push(input[i]);
Chris@1573 144 mm.checkIntegrity();
Chris@1573 145 output.push_back(mm.get());
Chris@1573 146 }
Chris@1573 147 mm.checkIntegrity();
Chris@1573 148 checkExpected<double>(output, expected);
Chris@1573 149 }
Chris@1573 150
Chris@1573 151 void shrinking() {
Chris@1573 152 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
Chris@1573 153 vector<double> expected { 0.0, 0.0, 3.0, 3.0, 2.5, 2.5, 3.0, 2.0, 1.0, 0.0 };
Chris@1573 154 vector<double> output;
Chris@1573 155 MovingMedian<double> mm(99);
Chris@1573 156 for (int i = 0; i < int(input.size()); ++i) {
Chris@1573 157 // sizes 5, 5, 4, 4, 3, 3, 2, 2, 1, 1
Chris@1573 158 int sz = 5 - i/2;
Chris@1573 159 mm.resize(sz);
Chris@1573 160 QCOMPARE(mm.size(), sz);
Chris@1573 161 mm.push(input[i]);
Chris@1573 162 mm.checkIntegrity();
Chris@1573 163 output.push_back(mm.get());
Chris@1573 164 }
Chris@1573 165 mm.checkIntegrity();
Chris@1573 166 checkExpected<double>(output, expected);
Chris@1573 167 }
Chris@1573 168 };
Chris@1573 169
Chris@1573 170 #endif