1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 /* 4 Sonic Visualiser 5 An audio file viewer and annotation editor. 6 Centre for Digital Music, Queen Mary, University of London. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. See the file 12 COPYING included with this distribution for more information. 13 */ 14 15 #ifndef TEST_SCALE_TICK_INTERVALS_H 16 #define TEST_SCALE_TICK_INTERVALS_H 17 18 #include "../ScaleTickIntervals.h" 19 20 #include <QObject> 21 #include <QtTest> 22 #include <QDir> 23 24 #include <iostream> 25 26 using namespace std; 27 28 class TestScaleTickIntervals : public QObject 29 { 30 Q_OBJECT 31 printDiff(vector<ScaleTickIntervals::Tick> ticks,vector<ScaleTickIntervals::Tick> expected)32 void printDiff(vector<ScaleTickIntervals::Tick> ticks, 33 vector<ScaleTickIntervals::Tick> expected) { 34 35 SVCERR << "Have " << ticks.size() << " ticks, expected " 36 << expected.size() << endl; 37 for (int i = 0; i < int(ticks.size()); ++i) { 38 SVCERR << i << ": have " << ticks[i].value << " \"" 39 << ticks[i].label << "\", expected "; 40 if (i < int(expected.size())) { 41 SVCERR << expected[i].value << " \"" << expected[i].label 42 << "\"" << endl; 43 } else { 44 SVCERR << "(n/a)" << endl; 45 } 46 } 47 } 48 49 void compareTicks(ScaleTickIntervals::Ticks ticks, 50 ScaleTickIntervals::Ticks expected, 51 bool fuzzier = false) 52 { 53 for (int i = 0; i < int(expected.size()); ++i) { 54 if (i < int(ticks.size())) { 55 bool pass = true; 56 if (ticks[i].label != expected[i].label) { 57 pass = false; 58 } else { 59 double eps = fuzzier ? 1e-5 : 1e-10; 60 double diff = fabs(ticks[i].value - expected[i].value); 61 double limit = max(eps, fabs(ticks[i].value) * eps); 62 if (diff > limit) { 63 pass = false; 64 } 65 } 66 if (!pass) { 67 printDiff(ticks, expected); 68 } 69 QCOMPARE(ticks[i].label, expected[i].label); 70 QCOMPARE(ticks[i].value, expected[i].value); 71 } 72 } 73 if (ticks.size() != expected.size()) { 74 printDiff(ticks, expected); 75 } 76 QCOMPARE(ticks.size(), expected.size()); 77 } 78 79 private slots: linear_0_1_10()80 void linear_0_1_10() 81 { 82 auto ticks = ScaleTickIntervals::linear({ 0, 1, 10 }); 83 ScaleTickIntervals::Ticks expected { 84 { 0.0, "0.0" }, 85 { 0.1, "0.1" }, 86 { 0.2, "0.2" }, 87 { 0.3, "0.3" }, 88 { 0.4, "0.4" }, 89 { 0.5, "0.5" }, 90 { 0.6, "0.6" }, 91 { 0.7, "0.7" }, 92 { 0.8, "0.8" }, 93 { 0.9, "0.9" }, 94 { 1.0, "1.0" } 95 }; 96 compareTicks(ticks, expected); 97 } 98 linear_0_5_5()99 void linear_0_5_5() 100 { 101 auto ticks = ScaleTickIntervals::linear({ 0, 5, 5 }); 102 ScaleTickIntervals::Ticks expected { 103 { 0, "0" }, 104 { 1, "1" }, 105 { 2, "2" }, 106 { 3, "3" }, 107 { 4, "4" }, 108 { 5, "5" }, 109 }; 110 compareTicks(ticks, expected); 111 } 112 linear_0_10_5()113 void linear_0_10_5() 114 { 115 auto ticks = ScaleTickIntervals::linear({ 0, 10, 5 }); 116 ScaleTickIntervals::Ticks expected { 117 { 0, "0" }, 118 { 2, "2" }, 119 { 4, "4" }, 120 { 6, "6" }, 121 { 8, "8" }, 122 { 10, "10" } 123 }; 124 compareTicks(ticks, expected); 125 } 126 linear_10_0_5()127 void linear_10_0_5() 128 { 129 auto ticks = ScaleTickIntervals::linear({ 10, 0, 5 }); 130 ScaleTickIntervals::Ticks expected { 131 { 0, "0" }, 132 { 2, "2" }, 133 { 4, "4" }, 134 { 6, "6" }, 135 { 8, "8" }, 136 { 10, "10" } 137 }; 138 compareTicks(ticks, expected); 139 } 140 linear_m10_0_5()141 void linear_m10_0_5() 142 { 143 auto ticks = ScaleTickIntervals::linear({ -10, 0, 5 }); 144 ScaleTickIntervals::Ticks expected { 145 { -10, "-10" }, 146 { -8, "-8" }, 147 { -6, "-6" }, 148 { -4, "-4" }, 149 { -2, "-2" }, 150 { 0, "0" } 151 }; 152 compareTicks(ticks, expected); 153 } 154 linear_0_m10_5()155 void linear_0_m10_5() 156 { 157 auto ticks = ScaleTickIntervals::linear({ 0, -10, 5 }); 158 ScaleTickIntervals::Ticks expected { 159 { -10, "-10" }, 160 { -8, "-8" }, 161 { -6, "-6" }, 162 { -4, "-4" }, 163 { -2, "-2" }, 164 { 0, "0" } 165 }; 166 compareTicks(ticks, expected); 167 } 168 linear_0_0p1_5()169 void linear_0_0p1_5() 170 { 171 auto ticks = ScaleTickIntervals::linear({ 0, 0.1, 5 }); 172 ScaleTickIntervals::Ticks expected { 173 { 0.00, "0.00" }, 174 { 0.02, "0.02" }, 175 { 0.04, "0.04" }, 176 { 0.06, "0.06" }, 177 { 0.08, "0.08" }, 178 { 0.10, "0.10" } 179 }; 180 compareTicks(ticks, expected); 181 } 182 linear_0_0p01_5()183 void linear_0_0p01_5() 184 { 185 auto ticks = ScaleTickIntervals::linear({ 0, 0.01, 5 }); 186 ScaleTickIntervals::Ticks expected { 187 { 0.000, "0.000" }, 188 { 0.002, "0.002" }, 189 { 0.004, "0.004" }, 190 { 0.006, "0.006" }, 191 { 0.008, "0.008" }, 192 { 0.010, "0.010" } 193 }; 194 compareTicks(ticks, expected); 195 } 196 linear_0_0p005_5()197 void linear_0_0p005_5() 198 { 199 auto ticks = ScaleTickIntervals::linear({ 0, 0.005, 5 }); 200 ScaleTickIntervals::Ticks expected { 201 { 0.000, "0.000" }, 202 { 0.001, "0.001" }, 203 { 0.002, "0.002" }, 204 { 0.003, "0.003" }, 205 { 0.004, "0.004" }, 206 { 0.005, "0.005" } 207 }; 208 compareTicks(ticks, expected); 209 } 210 linear_0_0p001_5()211 void linear_0_0p001_5() 212 { 213 auto ticks = ScaleTickIntervals::linear({ 0, 0.001, 5 }); 214 ScaleTickIntervals::Ticks expected { 215 { 0.0000, "0.0e+00" }, 216 { 0.0002, "2.0e-04" }, 217 { 0.0004, "4.0e-04" }, 218 { 0.0006, "6.0e-04" }, 219 { 0.0008, "8.0e-04" }, 220 { 0.0010, "1.0e-03" } 221 }; 222 compareTicks(ticks, expected); 223 } 224 linear_1_1p001_5()225 void linear_1_1p001_5() 226 { 227 auto ticks = ScaleTickIntervals::linear({ 1, 1.001, 5 }); 228 ScaleTickIntervals::Ticks expected { 229 { 1.0000, "1.0000" }, 230 { 1.0002, "1.0002" }, 231 { 1.0004, "1.0004" }, 232 { 1.0006, "1.0006" }, 233 { 1.0008, "1.0008" }, 234 { 1.0010, "1.0010" } 235 }; 236 compareTicks(ticks, expected); 237 } 238 linear_0p001_1_5()239 void linear_0p001_1_5() 240 { 241 auto ticks = ScaleTickIntervals::linear({ 0.001, 1, 5 }); 242 ScaleTickIntervals::Ticks expected { 243 { 0.1, "0.1" }, 244 { 0.3, "0.3" }, 245 { 0.5, "0.5" }, 246 { 0.7, "0.7" }, 247 { 0.9, "0.9" }, 248 }; 249 compareTicks(ticks, expected); 250 } 251 linear_10000_10010_5()252 void linear_10000_10010_5() 253 { 254 auto ticks = ScaleTickIntervals::linear({ 10000, 10010, 5 }); 255 ScaleTickIntervals::Ticks expected { 256 { 10000, "10000" }, 257 { 10002, "10002" }, 258 { 10004, "10004" }, 259 { 10006, "10006" }, 260 { 10008, "10008" }, 261 { 10010, "10010" }, 262 }; 263 compareTicks(ticks, expected); 264 } 265 linear_10000_20000_5()266 void linear_10000_20000_5() 267 { 268 auto ticks = ScaleTickIntervals::linear({ 10000, 20000, 5 }); 269 ScaleTickIntervals::Ticks expected { 270 { 10000, "10000" }, 271 { 12000, "12000" }, 272 { 14000, "14000" }, 273 { 16000, "16000" }, 274 { 18000, "18000" }, 275 { 20000, "20000" }, 276 }; 277 compareTicks(ticks, expected); 278 } 279 linear_m1_1_10()280 void linear_m1_1_10() 281 { 282 auto ticks = ScaleTickIntervals::linear({ -1, 1, 10 }); 283 ScaleTickIntervals::Ticks expected { 284 { -1.0, "-1.0" }, 285 { -0.8, "-0.8" }, 286 { -0.6, "-0.6" }, 287 { -0.4, "-0.4" }, 288 { -0.2, "-0.2" }, 289 { 0.0, "0.0" }, 290 { 0.2, "0.2" }, 291 { 0.4, "0.4" }, 292 { 0.6, "0.6" }, 293 { 0.8, "0.8" }, 294 { 1.0, "1.0" } 295 }; 296 compareTicks(ticks, expected); 297 } 298 linear_221p23_623p7_57p4()299 void linear_221p23_623p7_57p4() 300 { 301 auto ticks = ScaleTickIntervals::linear({ 221.23, 623.7, 4 }); 302 // only 4 ticks, not 5, because none of the rounded tick 303 // values lies on an end value 304 ScaleTickIntervals::Ticks expected { 305 { 300, "300" }, 306 { 400, "400" }, 307 { 500, "500" }, 308 { 600, "600" }, 309 }; 310 compareTicks(ticks, expected); 311 } 312 linear_sqrt2_pi_7()313 void linear_sqrt2_pi_7() 314 { 315 auto ticks = ScaleTickIntervals::linear({ sqrt(2.0), M_PI, 7 }); 316 // This would be better in steps of 0.25, but we only round to 317 // integral powers of ten 318 ScaleTickIntervals::Ticks expected { 319 { 1.5, "1.5" }, 320 { 1.7, "1.7" }, 321 { 1.9, "1.9" }, 322 { 2.1, "2.1" }, 323 { 2.3, "2.3" }, 324 { 2.5, "2.5" }, 325 { 2.7, "2.7" }, 326 { 2.9, "2.9" }, 327 { 3.1, "3.1" }, 328 }; 329 compareTicks(ticks, expected); 330 } 331 linear_pi_avogadro_7()332 void linear_pi_avogadro_7() 333 { 334 auto ticks = ScaleTickIntervals::linear({ M_PI, 6.022140857e23, 7 }); 335 ScaleTickIntervals::Ticks expected { 336 // not perfect, but ok-ish 337 { 0, "0.0e+00" }, 338 { 9e+22, "9.0e+22" }, 339 { 1.8e+23, "1.8e+23" }, 340 { 2.7e+23, "2.7e+23" }, 341 { 3.6e+23, "3.6e+23" }, 342 { 4.5e+23, "4.5e+23" }, 343 { 5.4e+23, "5.4e+23" }, 344 }; 345 compareTicks(ticks, expected); 346 } 347 linear_2_3_1()348 void linear_2_3_1() 349 { 350 auto ticks = ScaleTickIntervals::linear({ 2, 3, 1 }); 351 ScaleTickIntervals::Ticks expected { 352 { 2.0, "2" }, 353 { 3.0, "3" } 354 }; 355 compareTicks(ticks, expected); 356 } 357 linear_2_3_2()358 void linear_2_3_2() 359 { 360 auto ticks = ScaleTickIntervals::linear({ 2, 3, 2 }); 361 ScaleTickIntervals::Ticks expected { 362 { 2.0, "2.0" }, 363 { 2.5, "2.5" }, 364 { 3.0, "3.0" } 365 }; 366 compareTicks(ticks, expected); 367 } 368 linear_2_3_3()369 void linear_2_3_3() 370 { 371 auto ticks = ScaleTickIntervals::linear({ 2, 3, 3 }); 372 ScaleTickIntervals::Ticks expected { 373 { 2.0, "2.0" }, 374 { 2.3, "2.3" }, 375 { 2.6, "2.6" }, 376 { 2.9, "2.9" } 377 }; 378 compareTicks(ticks, expected); 379 } 380 linear_2_3_4()381 void linear_2_3_4() 382 { 383 auto ticks = ScaleTickIntervals::linear({ 2, 3, 4 }); 384 // This would be better in steps of 0.25, but we only round to 385 // integral powers of ten 386 ScaleTickIntervals::Ticks expected { 387 { 2.0, "2.0" }, 388 { 2.3, "2.3" }, 389 { 2.6, "2.6" }, 390 { 2.9, "2.9" } 391 }; 392 compareTicks(ticks, expected); 393 } 394 linear_2_3_5()395 void linear_2_3_5() 396 { 397 auto ticks = ScaleTickIntervals::linear({ 2, 3, 5 }); 398 ScaleTickIntervals::Ticks expected { 399 { 2.0, "2.0" }, 400 { 2.2, "2.2" }, 401 { 2.4, "2.4" }, 402 { 2.6, "2.6" }, 403 { 2.8, "2.8" }, 404 { 3.0, "3.0" } 405 }; 406 compareTicks(ticks, expected); 407 } 408 linear_2_3_6()409 void linear_2_3_6() 410 { 411 auto ticks = ScaleTickIntervals::linear({ 2, 3, 6 }); 412 ScaleTickIntervals::Ticks expected { 413 { 2.0, "2.0" }, 414 { 2.2, "2.2" }, 415 { 2.4, "2.4" }, 416 { 2.6, "2.6" }, 417 { 2.8, "2.8" }, 418 { 3.0, "3.0" } 419 }; 420 compareTicks(ticks, expected); 421 } 422 linear_1_1_10()423 void linear_1_1_10() 424 { 425 // pathological range 426 auto ticks = ScaleTickIntervals::linear({ 1, 1, 10 }); 427 ScaleTickIntervals::Ticks expected { 428 { 1.0, "1" } 429 }; 430 compareTicks(ticks, expected); 431 } 432 linear_0_0_10()433 void linear_0_0_10() 434 { 435 // pathological range 436 auto ticks = ScaleTickIntervals::linear({ 0, 0, 10 }); 437 ScaleTickIntervals::Ticks expected { 438 { 0.0, "0.0" } 439 }; 440 compareTicks(ticks, expected); 441 } 442 linear_0_1_1()443 void linear_0_1_1() 444 { 445 auto ticks = ScaleTickIntervals::linear({ 0, 1, 1 }); 446 ScaleTickIntervals::Ticks expected { 447 { 0.0, "0" }, 448 { 1.0, "1" } 449 }; 450 compareTicks(ticks, expected); 451 } 452 linear_0_1_0()453 void linear_0_1_0() 454 { 455 // senseless input 456 auto ticks = ScaleTickIntervals::linear({ 0, 1, 0 }); 457 ScaleTickIntervals::Ticks expected { 458 { 0.0, "0.0" }, 459 }; 460 compareTicks(ticks, expected); 461 } 462 linear_0_1_m1()463 void linear_0_1_m1() 464 { 465 // senseless input 466 auto ticks = ScaleTickIntervals::linear({ 0, 1, -1 }); 467 ScaleTickIntervals::Ticks expected { 468 { 0.0, "0.0" }, 469 }; 470 compareTicks(ticks, expected); 471 } 472 linear_0p465_778_10()473 void linear_0p465_778_10() 474 { 475 // a case that gave unsatisfactory results in real life 476 // (initially it had the first tick at 1) 477 auto ticks = ScaleTickIntervals::linear({ 0.465, 778.08, 10 }); 478 ScaleTickIntervals::Ticks expected { 479 { 10, "10" }, 480 { 90, "90" }, 481 { 170, "170" }, 482 { 250, "250" }, 483 { 330, "330" }, 484 { 410, "410" }, 485 { 490, "490" }, 486 { 570, "570" }, 487 { 650, "650" }, 488 { 730, "730" }, 489 }; 490 compareTicks(ticks, expected); 491 } 492 log_1_10_2()493 void log_1_10_2() 494 { 495 auto ticks = ScaleTickIntervals::logarithmic({ 1, 10, 2 }); 496 ScaleTickIntervals::Ticks expected { 497 { 1.0, "1.0" }, 498 { 3.2, "3.2" }, 499 { 10.0, "10" }, 500 }; 501 compareTicks(ticks, expected); 502 } 503 log_0_10_2()504 void log_0_10_2() 505 { 506 auto ticks = ScaleTickIntervals::logarithmic({ 0, 10, 2 }); 507 ScaleTickIntervals::Ticks expected { 508 { 1e-6, "1e-06" }, 509 { 1, "1" }, 510 }; 511 compareTicks(ticks, expected); 512 } 513 log_pi_avogadro_7()514 void log_pi_avogadro_7() 515 { 516 auto ticks = ScaleTickIntervals::logarithmic({ M_PI, 6.022140857e23, 7 }); 517 ScaleTickIntervals::Ticks expected { 518 { 1000, "1000" }, 519 { 1e+06, "1e+06" }, 520 { 1e+09, "1e+09" }, 521 { 1e+12, "1e+12" }, 522 { 1e+15, "1e+15" }, 523 { 1e+18, "1e+18" }, 524 { 1e+21, "1e+21" }, 525 }; 526 compareTicks(ticks, expected, true); 527 } 528 log_0p465_778_10()529 void log_0p465_778_10() 530 { 531 auto ticks = ScaleTickIntervals::logarithmic({ 0.465, 778.08, 10 }); 532 ScaleTickIntervals::Ticks expected { 533 { 0.5, "0.50" }, 534 { 1, "1.0" }, 535 { 2, "2.0" }, 536 { 4, "4.0" }, 537 { 8, "8.0" }, 538 { 16, "16" }, 539 { 32, "32" }, 540 { 64, "64" }, 541 { 130, "130" }, 542 { 260, "260" }, 543 { 510, "510" }, 544 }; 545 compareTicks(ticks, expected); 546 } 547 log_1_10k_10()548 void log_1_10k_10() 549 { 550 auto ticks = ScaleTickIntervals::logarithmic({ 1.0, 10000.0, 10 }); 551 ScaleTickIntervals::Ticks expected { 552 { 1.0, "1.0" }, 553 { 2.5, "2.5" }, 554 { 6.3, "6.3" }, 555 { 16.0, "16" }, 556 { 40.0, "40" }, 557 { 100.0, "100" }, 558 { 250.0, "250" }, 559 { 630.0, "630" }, 560 { 1600.0, "1600" }, 561 { 4000.0, "4000" }, 562 { 10000.0, "1e+04" }, 563 }; 564 compareTicks(ticks, expected, true); 565 } 566 log_80_10k_6()567 void log_80_10k_6() 568 { 569 auto ticks = ScaleTickIntervals::logarithmic({ 80.0, 10000.0, 6 }); 570 ScaleTickIntervals::Ticks expected { 571 { 130, "130" }, 572 { 260, "260" }, 573 { 510, "510" }, 574 { 1000, "1000" }, 575 { 2000, "2000" }, 576 { 4100, "4100" }, 577 { 8200, "8200" } 578 }; 579 compareTicks(ticks, expected, true); 580 } 581 log_80_800k_10()582 void log_80_800k_10() 583 { 584 auto ticks = ScaleTickIntervals::logarithmic({ 80.0, 800000.0, 10 }); 585 ScaleTickIntervals::Ticks expected { 586 { 100, "100" }, 587 { 250, "250" }, 588 { 630, "630" }, 589 { 1600, "1600" }, 590 { 4000, "4000" }, 591 { 10000, "1e+04" }, 592 { 25000, "2.5e+04" }, 593 { 63000, "6.3e+04" }, 594 { 160000, "1.6e+05" }, 595 { 400000, "4e+05" }, 596 }; 597 compareTicks(ticks, expected, true); 598 } 599 log_0_1_0()600 void log_0_1_0() 601 { 602 // senseless input 603 auto ticks = ScaleTickIntervals::logarithmic({ 0, 1, 0 }); 604 ScaleTickIntervals::Ticks expected { 605 }; 606 compareTicks(ticks, expected); 607 } 608 log_0_1_m1()609 void log_0_1_m1() 610 { 611 // senseless input 612 auto ticks = ScaleTickIntervals::logarithmic({ 0, 1, -1 }); 613 ScaleTickIntervals::Ticks expected { 614 }; 615 compareTicks(ticks, expected); 616 } 617 618 }; 619 620 #endif 621 622 623