annotate base/test/TestLogRange.h @ 1427:622d193a00dc

Rework canonicalisation so as to avoid theoretical possibility of integer overflow
author Chris Cannam
date Mon, 11 Dec 2017 09:28:40 +0000
parents 667e369cfeab
children
rev   line source
Chris@1392 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1392 2
Chris@1392 3 /*
Chris@1392 4 Sonic Visualiser
Chris@1392 5 An audio file viewer and annotation editor.
Chris@1392 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1392 7
Chris@1392 8 This program is free software; you can redistribute it and/or
Chris@1392 9 modify it under the terms of the GNU General Public License as
Chris@1392 10 published by the Free Software Foundation; either version 2 of the
Chris@1392 11 License, or (at your option) any later version. See the file
Chris@1392 12 COPYING included with this distribution for more information.
Chris@1392 13 */
Chris@1392 14
Chris@1392 15 #ifndef TEST_LOG_RANGE_H
Chris@1392 16 #define TEST_LOG_RANGE_H
Chris@1392 17
Chris@1392 18 #include "../LogRange.h"
Chris@1392 19
Chris@1392 20 #include <QObject>
Chris@1392 21 #include <QtTest>
Chris@1392 22
Chris@1392 23 #include <iostream>
Chris@1392 24 #include <cmath>
Chris@1392 25
Chris@1392 26 using namespace std;
Chris@1392 27
Chris@1392 28 class TestLogRange : public QObject
Chris@1392 29 {
Chris@1392 30 Q_OBJECT
Chris@1392 31
Chris@1392 32 private slots:
Chris@1392 33
Chris@1392 34 void mapPositiveAboveDefaultThreshold()
Chris@1392 35 {
Chris@1392 36 QCOMPARE(LogRange::map(10.0), 1.0);
Chris@1392 37 QCOMPARE(LogRange::map(100.0), 2.0);
Chris@1392 38 QCOMPARE(LogRange::map(0.1), -1.0);
Chris@1392 39 QCOMPARE(LogRange::map(1.0), 0.0);
Chris@1392 40 QCOMPARE(LogRange::map(0.0000001), -7.0);
Chris@1392 41 QCOMPARE(LogRange::map(20.0), log10(20.0));
Chris@1392 42 }
Chris@1392 43
Chris@1392 44 void mapPositiveAboveSetThreshold()
Chris@1392 45 {
Chris@1392 46 QCOMPARE(LogRange::map(10.0, -10.0), 1.0);
Chris@1392 47 QCOMPARE(LogRange::map(100.0, 1.0), 2.0);
Chris@1392 48 QCOMPARE(LogRange::map(0.1, -5.0), -1.0);
Chris@1392 49 QCOMPARE(LogRange::map(1.0, -0.01), 0.0);
Chris@1392 50 QCOMPARE(LogRange::map(0.0000001, -20.0), -7.0);
Chris@1392 51 QCOMPARE(LogRange::map(20.0, 0.0), log10(20.0));
Chris@1392 52 }
Chris@1392 53
Chris@1392 54 void mapZeroDefaultThreshold()
Chris@1392 55 {
Chris@1392 56 QCOMPARE(LogRange::map(0.0), -10.0);
Chris@1392 57 }
Chris@1392 58
Chris@1392 59 void mapZeroSetThreshold()
Chris@1392 60 {
Chris@1392 61 QCOMPARE(LogRange::map(0.0, 12.0), 12.0);
Chris@1392 62 QCOMPARE(LogRange::map(0.0, -12.0), -12.0);
Chris@1392 63 QCOMPARE(LogRange::map(0.0, 0.0), 0.0);
Chris@1392 64 }
Chris@1392 65
Chris@1392 66 void mapPositiveBelowDefaultThreshold()
Chris@1392 67 {
Chris@1392 68 // The threshold is used only for zero values, not for very
Chris@1392 69 // small ones -- it's arguably a stand-in or replacement value
Chris@1392 70 // rather than a threshold. So this should behave the same as
Chris@1392 71 // for values above the threshold.
Chris@1392 72 QCOMPARE(LogRange::map(1e-10), -10.0);
Chris@1392 73 QCOMPARE(LogRange::map(1e-20), -20.0);
Chris@1392 74 QCOMPARE(LogRange::map(1e-100), -100.0);
Chris@1392 75 }
Chris@1392 76
Chris@1392 77 void mapPositiveBelowSetThreshold()
Chris@1392 78 {
Chris@1392 79 // As above
Chris@1392 80 QCOMPARE(LogRange::map(10.0, 4.0), 1.0);
Chris@1392 81 QCOMPARE(LogRange::map(1e-10, 4.0), -10.0);
Chris@1392 82 QCOMPARE(LogRange::map(1e-20, -15.0), -20.0);
Chris@1392 83 QCOMPARE(LogRange::map(1e-100, -100.0), -100.0);
Chris@1392 84 }
Chris@1392 85
Chris@1392 86 void mapNegative()
Chris@1392 87 {
Chris@1392 88 // Should always return map of absolute value. These are
Chris@1392 89 // picked from vaarious of the above tests.
Chris@1392 90
Chris@1392 91 QCOMPARE(LogRange::map(-10.0), 1.0);
Chris@1392 92 QCOMPARE(LogRange::map(-100.0), 2.0);
Chris@1392 93 QCOMPARE(LogRange::map(-0.1), -1.0);
Chris@1392 94 QCOMPARE(LogRange::map(-1.0), 0.0);
Chris@1392 95 QCOMPARE(LogRange::map(-0.0000001), -7.0);
Chris@1392 96 QCOMPARE(LogRange::map(-20.0), log10(20.0));
Chris@1392 97 QCOMPARE(LogRange::map(-10.0, 4.0), 1.0);
Chris@1392 98 QCOMPARE(LogRange::map(-1e-10, 4.0), -10.0);
Chris@1392 99 QCOMPARE(LogRange::map(-1e-20, -15.0), -20.0);
Chris@1392 100 QCOMPARE(LogRange::map(-1e-100, -100.0), -100.0);
Chris@1392 101 QCOMPARE(LogRange::map(-0.0, 12.0), 12.0);
Chris@1392 102 QCOMPARE(LogRange::map(-0.0, -12.0), -12.0);
Chris@1392 103 QCOMPARE(LogRange::map(-0.0, 0.0), 0.0);
Chris@1392 104 }
Chris@1392 105
Chris@1392 106 void unmap()
Chris@1392 107 {
Chris@1392 108 // Simply pow(10, x)
Chris@1392 109
Chris@1392 110 QCOMPARE(LogRange::unmap(0.0), 1.0);
Chris@1392 111 QCOMPARE(LogRange::unmap(1.0), 10.0);
Chris@1392 112 QCOMPARE(LogRange::unmap(-1.0), 0.1);
Chris@1392 113 QCOMPARE(LogRange::unmap(100.0), 1e+100);
Chris@1392 114 QCOMPARE(LogRange::unmap(-100.0), 1e-100);
Chris@1392 115 }
Chris@1392 116
Chris@1392 117 void mapRangeAllPositiveDefaultThreshold()
Chris@1392 118 {
Chris@1392 119 double min, max;
Chris@1392 120
Chris@1392 121 min = 1.0; max = 10.0;
Chris@1392 122 LogRange::mapRange(min, max);
Chris@1392 123 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 124
Chris@1392 125 min = 10.0; max = 1.0;
Chris@1392 126 LogRange::mapRange(min, max);
Chris@1392 127 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 128
Chris@1392 129 // if equal, the function uses an arbitrary 1.0 range before mapping
Chris@1392 130 min = 10.0; max = 10.0;
Chris@1392 131 LogRange::mapRange(min, max);
Chris@1392 132 QCOMPARE(min, 1.0); QCOMPARE(max, log10(11.0));
Chris@1392 133 }
Chris@1392 134
Chris@1392 135 void mapRangeAllPositiveSetThreshold()
Chris@1392 136 {
Chris@1392 137 double min, max;
Chris@1392 138
Chris@1392 139 min = 1.0; max = 10.0;
Chris@1392 140 LogRange::mapRange(min, max, -4.0);
Chris@1392 141 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 142
Chris@1392 143 min = 10.0; max = 1.0;
Chris@1392 144 LogRange::mapRange(min, max, -4.0);
Chris@1392 145 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 146
Chris@1392 147 // if equal, the function uses an arbitrary 1.0 range before mapping
Chris@1392 148 min = 10.0; max = 10.0;
Chris@1392 149 LogRange::mapRange(min, max, -4.0);
Chris@1392 150 QCOMPARE(min, 1.0); QCOMPARE(max, log10(11.0));
Chris@1392 151 }
Chris@1392 152
Chris@1392 153 void mapRangeAllNegativeDefaultThreshold()
Chris@1392 154 {
Chris@1392 155 double min, max;
Chris@1392 156
Chris@1392 157 min = -1.0; max = -10.0;
Chris@1392 158 LogRange::mapRange(min, max);
Chris@1392 159 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 160
Chris@1392 161 min = -10.0; max = -1.0;
Chris@1392 162 LogRange::mapRange(min, max);
Chris@1392 163 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 164
Chris@1392 165 // if equal, the function uses an arbitrary 1.0 range before mapping
Chris@1392 166 min = -10.0; max = -10.0;
Chris@1392 167 LogRange::mapRange(min, max);
Chris@1392 168 QCOMPARE(min, log10(9.0)); QCOMPARE(max, 1.0);
Chris@1392 169 }
Chris@1392 170
Chris@1392 171 void mapRangeAllNegativeSetThreshold()
Chris@1392 172 {
Chris@1392 173 double min, max;
Chris@1392 174
Chris@1392 175 min = -1.0; max = -10.0;
Chris@1392 176 LogRange::mapRange(min, max, -4.0);
Chris@1392 177 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 178
Chris@1392 179 min = -10.0; max = -1.0;
Chris@1392 180 LogRange::mapRange(min, max, -4.0);
Chris@1392 181 QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
Chris@1392 182
Chris@1392 183 // if equal, the function uses an arbitrary 1.0 range before mapping
Chris@1392 184 min = -10.0; max = -10.0;
Chris@1392 185 LogRange::mapRange(min, max, -4.0);
Chris@1392 186 QCOMPARE(min, log10(9.0)); QCOMPARE(max, 1.0);
Chris@1392 187 }
Chris@1392 188
Chris@1392 189 void mapRangeAllNonNegativeDefaultThreshold()
Chris@1392 190 {
Chris@1392 191 double min, max;
Chris@1392 192
Chris@1392 193 min = 0.0; max = 10.0;
Chris@1392 194 LogRange::mapRange(min, max);
Chris@1392 195 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 196
Chris@1392 197 min = 10.0; max = 0.0;
Chris@1392 198 LogRange::mapRange(min, max);
Chris@1392 199 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 200
Chris@1392 201 // if equal, the function uses an arbitrary 1.0 range before mapping
Chris@1392 202 min = 0.0; max = 0.0;
Chris@1392 203 LogRange::mapRange(min, max);
Chris@1392 204 QCOMPARE(min, -10.0); QCOMPARE(max, 0.0);
Chris@1392 205 }
Chris@1392 206
Chris@1392 207 void mapRangeAllNonNegativeSetThreshold()
Chris@1392 208 {
Chris@1392 209 double min, max;
Chris@1392 210
Chris@1392 211 min = 0.0; max = 10.0;
Chris@1392 212 LogRange::mapRange(min, max, -4.0);
Chris@1392 213 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 214
Chris@1392 215 min = 10.0; max = 0.0;
Chris@1392 216 LogRange::mapRange(min, max, -4.0);
Chris@1392 217 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 218
Chris@1392 219 // if equal, the function uses an arbitrary 1.0 range before mapping
Chris@1392 220 min = 0.0; max = 0.0;
Chris@1392 221 LogRange::mapRange(min, max, -4.0);
Chris@1392 222 QCOMPARE(min, -4.0); QCOMPARE(max, 0.0);
Chris@1392 223 }
Chris@1392 224
Chris@1392 225 void mapRangeAllNonPositiveDefaultThreshold()
Chris@1392 226 {
Chris@1392 227 double min, max;
Chris@1392 228
Chris@1392 229 min = 0.0; max = -10.0;
Chris@1392 230 LogRange::mapRange(min, max);
Chris@1392 231 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 232
Chris@1392 233 min = -10.0; max = 0.0;
Chris@1392 234 LogRange::mapRange(min, max);
Chris@1392 235 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 236 }
Chris@1392 237
Chris@1392 238 void mapRangeAllNonPositiveSetThreshold()
Chris@1392 239 {
Chris@1392 240 double min, max;
Chris@1392 241
Chris@1392 242 min = 0.0; max = -10.0;
Chris@1392 243 LogRange::mapRange(min, max, -4.0);
Chris@1392 244 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 245
Chris@1392 246 min = -10.0; max = 0.0;
Chris@1392 247 LogRange::mapRange(min, max, -4.0);
Chris@1392 248 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 249 }
Chris@1392 250
Chris@1392 251 void mapRangeSpanningZeroDefaultThreshold()
Chris@1392 252 {
Chris@1392 253 double min, max;
Chris@1392 254
Chris@1392 255 min = -1.0; max = 10.0;
Chris@1392 256 LogRange::mapRange(min, max);
Chris@1392 257 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 258
Chris@1392 259 min = -100.0; max = 1.0;
Chris@1392 260 LogRange::mapRange(min, max);
Chris@1392 261 QCOMPARE(min, -10.0); QCOMPARE(max, 2.0);
Chris@1392 262
Chris@1392 263 min = -10.0; max = 1e-200;
Chris@1392 264 LogRange::mapRange(min, max);
Chris@1392 265 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 266
Chris@1392 267 min = 1e-200; max = -10.0;
Chris@1392 268 LogRange::mapRange(min, max);
Chris@1392 269 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 270
Chris@1392 271 min = -1e-200; max = 100.0;
Chris@1392 272 LogRange::mapRange(min, max);
Chris@1392 273 QCOMPARE(min, -10.0); QCOMPARE(max, 2.0);
Chris@1392 274
Chris@1392 275 min = 10.0; max = -1e-200;
Chris@1392 276 LogRange::mapRange(min, max);
Chris@1392 277 QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
Chris@1392 278
Chris@1392 279 // if none of the input range is above the threshold in
Chris@1392 280 // magnitude, but it still spans zero, we use the input max as
Chris@1392 281 // threshold and then add 1 for range
Chris@1392 282 min = -1e-200; max = 1e-300;
Chris@1392 283 LogRange::mapRange(min, max);
Chris@1392 284 QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
Chris@1392 285
Chris@1392 286 min = 1e-200; max = -1e-300;
Chris@1392 287 LogRange::mapRange(min, max);
Chris@1392 288 QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
Chris@1392 289 }
Chris@1392 290
Chris@1392 291 void mapRangeSpanningZeroSetThreshold()
Chris@1392 292 {
Chris@1392 293 double min, max;
Chris@1392 294
Chris@1392 295 min = -1.0; max = 10.0;
Chris@1392 296 LogRange::mapRange(min, max, -4.0);
Chris@1392 297 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 298
Chris@1392 299 min = -100.0; max = 1.0;
Chris@1392 300 LogRange::mapRange(min, max, -4.0);
Chris@1392 301 QCOMPARE(min, -4.0); QCOMPARE(max, 2.0);
Chris@1392 302
Chris@1392 303 min = -10.0; max = 1e-200;
Chris@1392 304 LogRange::mapRange(min, max, -4.0);
Chris@1392 305 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 306
Chris@1392 307 min = 1e-200; max = -10.0;
Chris@1392 308 LogRange::mapRange(min, max, -4.0);
Chris@1392 309 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 310
Chris@1392 311 min = -1e-200; max = 100.0;
Chris@1392 312 LogRange::mapRange(min, max, -4.0);
Chris@1392 313 QCOMPARE(min, -4.0); QCOMPARE(max, 2.0);
Chris@1392 314
Chris@1392 315 min = 10.0; max = -1e-200;
Chris@1392 316 LogRange::mapRange(min, max, -4.0);
Chris@1392 317 QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
Chris@1392 318
Chris@1392 319 // if none of the input range is above the threshold in
Chris@1392 320 // magnitude, but it still spans zero, we use the input max as
Chris@1392 321 // threshold and then add 1 for range
Chris@1392 322 min = -1e-200; max = 1e-300;
Chris@1392 323 LogRange::mapRange(min, max, -4.0);
Chris@1392 324 QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
Chris@1392 325
Chris@1392 326 min = 1e-200; max = -1e-300;
Chris@1392 327 LogRange::mapRange(min, max, -4.0);
Chris@1392 328 QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
Chris@1392 329 }
Chris@1392 330
Chris@1392 331 };
Chris@1392 332
Chris@1392 333 #endif