File indexing completed on 2024-10-13 04:16:16
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 // First included header is the public header of the class we are testing; 0005 // this forces the header to be self-contained. 0006 #include "helpermath.h" 0007 0008 #include <algorithm> 0009 #include <cmath> 0010 #include <limits> 0011 #include <optional> 0012 #include <qgenericmatrix.h> 0013 #include <qglobal.h> 0014 #include <qobject.h> 0015 #include <qtest.h> 0016 #include <qtestcase.h> 0017 #include <qtestdata.h> 0018 0019 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0020 #include <qtmetamacros.h> 0021 #else 0022 #include <qobjectdefs.h> 0023 #include <qstring.h> 0024 #endif 0025 0026 namespace PerceptualColor 0027 { 0028 0029 class TestHelperMath : public QObject 0030 { 0031 Q_OBJECT 0032 0033 public: 0034 explicit TestHelperMath(QObject *parent = nullptr) 0035 : QObject(parent) 0036 { 0037 } 0038 0039 private Q_SLOTS: 0040 0041 void initTestCase() 0042 { 0043 // Called before the first test function is executed 0044 } 0045 0046 void cleanupTestCase() 0047 { 0048 // Called after the last test function was executed 0049 } 0050 0051 void init() 0052 { 0053 // Called before each test function is executed 0054 } 0055 void cleanup() 0056 { 0057 // Called after every test function 0058 } 0059 0060 void testInRangeInt() 0061 { 0062 QCOMPARE(PerceptualColor::isInRange<int>(3, 3, 2), false); 0063 QCOMPARE(PerceptualColor::isInRange<int>(3, 2, 2), false); 0064 QCOMPARE(PerceptualColor::isInRange<int>(3, 0, 2), false); 0065 QCOMPARE(PerceptualColor::isInRange<int>(3, 4, 2), false); 0066 QCOMPARE(PerceptualColor::isInRange<int>(3, 3, 3), true); 0067 QCOMPARE(PerceptualColor::isInRange<int>(3, 4, 3), false); 0068 QCOMPARE(PerceptualColor::isInRange<int>(3, 2, 3), false); 0069 QCOMPARE(PerceptualColor::isInRange<int>(0, 1, 2), true); 0070 QCOMPARE(PerceptualColor::isInRange<int>(0, 0, 2), true); 0071 QCOMPARE(PerceptualColor::isInRange<int>(0, 2, 2), true); 0072 QCOMPARE(PerceptualColor::isInRange<int>(0, 3, 2), false); 0073 QCOMPARE(PerceptualColor::isInRange<int>(0, -1, 2), false); 0074 QCOMPARE(PerceptualColor::isInRange<int>(1, 2, 3), true); 0075 QCOMPARE(PerceptualColor::isInRange<int>(1, 1, 3), true); 0076 QCOMPARE(PerceptualColor::isInRange<int>(1, 3, 3), true); 0077 QCOMPARE(PerceptualColor::isInRange<int>(1, 0, 3), false); 0078 QCOMPARE(PerceptualColor::isInRange<int>(1, 4, 3), false); 0079 QCOMPARE(PerceptualColor::isInRange<int>(-1, 0, 1), true); 0080 QCOMPARE(PerceptualColor::isInRange<int>(-1, -1, 1), true); 0081 QCOMPARE(PerceptualColor::isInRange<int>(-1, 1, 1), true); 0082 QCOMPARE(PerceptualColor::isInRange<int>(-1, 2, 1), false); 0083 QCOMPARE(PerceptualColor::isInRange<int>(-1, -2, 1), false); 0084 QCOMPARE(PerceptualColor::isInRange<int>(-2, -1, 0), true); 0085 QCOMPARE(PerceptualColor::isInRange<int>(-2, -2, 0), true); 0086 QCOMPARE(PerceptualColor::isInRange<int>(-2, 0, 0), true); 0087 QCOMPARE(PerceptualColor::isInRange<int>(-2, -3, 0), false); 0088 QCOMPARE(PerceptualColor::isInRange<int>(-2, 1, 0), false); 0089 QCOMPARE(PerceptualColor::isInRange<int>(-3, -2, -1), true); 0090 QCOMPARE(PerceptualColor::isInRange<int>(-3, -3, -1), true); 0091 QCOMPARE(PerceptualColor::isInRange<int>(-3, -1, -1), true); 0092 QCOMPARE(PerceptualColor::isInRange<int>(-3, -4, -1), false); 0093 QCOMPARE(PerceptualColor::isInRange<int>(-3, 0, -1), false); 0094 QCOMPARE(PerceptualColor::isInRange<double>(3, 3, 2), false); 0095 QCOMPARE(PerceptualColor::isInRange<double>(3, 2, 2), false); 0096 QCOMPARE(PerceptualColor::isInRange<double>(3, 0, 2), false); 0097 QCOMPARE(PerceptualColor::isInRange<double>(3, 4, 2), false); 0098 QCOMPARE(PerceptualColor::isInRange<double>(3, 3, 3), true); 0099 QCOMPARE(PerceptualColor::isInRange<double>(3, 4, 3), false); 0100 QCOMPARE(PerceptualColor::isInRange<double>(3, 2, 3), false); 0101 QCOMPARE(PerceptualColor::isInRange<double>(0, 1, 2), true); 0102 QCOMPARE(PerceptualColor::isInRange<double>(0, 0, 2), true); 0103 QCOMPARE(PerceptualColor::isInRange<double>(0, 2, 2), true); 0104 QCOMPARE(PerceptualColor::isInRange<double>(0, 3, 2), false); 0105 QCOMPARE(PerceptualColor::isInRange<double>(0, -1, 2), false); 0106 QCOMPARE(PerceptualColor::isInRange<double>(1, 2, 3), true); 0107 QCOMPARE(PerceptualColor::isInRange<double>(1, 1, 3), true); 0108 QCOMPARE(PerceptualColor::isInRange<double>(1, 3, 3), true); 0109 QCOMPARE(PerceptualColor::isInRange<double>(1, 0, 3), false); 0110 QCOMPARE(PerceptualColor::isInRange<double>(1, 4, 3), false); 0111 QCOMPARE(PerceptualColor::isInRange<double>(-1, 0, 1), true); 0112 QCOMPARE(PerceptualColor::isInRange<double>(-1, -1, 1), true); 0113 QCOMPARE(PerceptualColor::isInRange<double>(-1, 1, 1), true); 0114 QCOMPARE(PerceptualColor::isInRange<double>(-1, 2, 1), false); 0115 QCOMPARE(PerceptualColor::isInRange<double>(-1, -2, 1), false); 0116 QCOMPARE(PerceptualColor::isInRange<double>(-2, -1, 0), true); 0117 QCOMPARE(PerceptualColor::isInRange<double>(-2, -2, 0), true); 0118 QCOMPARE(PerceptualColor::isInRange<double>(-2, 0, 0), true); 0119 QCOMPARE(PerceptualColor::isInRange<double>(-2, -3, 0), false); 0120 QCOMPARE(PerceptualColor::isInRange<double>(-2, 1, 0), false); 0121 QCOMPARE(PerceptualColor::isInRange<double>(-3, -2, -1), true); 0122 QCOMPARE(PerceptualColor::isInRange<double>(-3, -3, -1), true); 0123 QCOMPARE(PerceptualColor::isInRange<double>(-3, -1, -1), true); 0124 QCOMPARE(PerceptualColor::isInRange<double>(-3, -4, -1), false); 0125 QCOMPARE(PerceptualColor::isInRange<double>(-3, 0, -1), false); 0126 0127 QCOMPARE(PerceptualColor::isInRange<double>(-3.1, 0.2, -1.3), false); 0128 0129 if constexpr (std::numeric_limits<double>::has_infinity) { 0130 constexpr auto inf = std::numeric_limits<double>::infinity(); 0131 QCOMPARE(PerceptualColor::isInRange<double>(-inf, 0, inf), // 0132 true); 0133 QCOMPARE(PerceptualColor::isInRange<double>(-5, 0, inf), // 0134 true); 0135 QCOMPARE(PerceptualColor::isInRange<double>(-inf, 0, 5), // 0136 true); 0137 QCOMPARE(PerceptualColor::isInRange<double>(inf, 0, -inf), // 0138 false); 0139 QCOMPARE(PerceptualColor::isInRange<double>(5, 0, -inf), // 0140 false); 0141 QCOMPARE(PerceptualColor::isInRange<double>(inf, 0, -5), // 0142 false); 0143 QCOMPARE(PerceptualColor::isInRange<double>(-inf, -inf, inf), // 0144 true); 0145 QCOMPARE(PerceptualColor::isInRange<double>(-inf, inf, inf), // 0146 true); 0147 QCOMPARE(PerceptualColor::isInRange<double>(-5, inf, inf), // 0148 true); 0149 QCOMPARE(PerceptualColor::isInRange<double>(-inf, -inf, 5), // 0150 true); 0151 } 0152 0153 if constexpr (std::numeric_limits<double>::has_quiet_NaN) { 0154 constexpr auto nan = std::numeric_limits<double>::quiet_NaN(); 0155 QCOMPARE(PerceptualColor::isInRange<double>(3, 4, 5), // 0156 true); 0157 QCOMPARE(PerceptualColor::isInRange<double>(nan, 4, 5), // 0158 false); 0159 QCOMPARE(PerceptualColor::isInRange<double>(3, nan, 5), // 0160 false); 0161 QCOMPARE(PerceptualColor::isInRange<double>(3, 4, nan), // 0162 false); 0163 0164 QCOMPARE(PerceptualColor::isInRange<double>(5, 4, 3), // 0165 false); 0166 QCOMPARE(PerceptualColor::isInRange<double>(nan, 4, 3), // 0167 false); 0168 QCOMPARE(PerceptualColor::isInRange<double>(5, nan, 3), // 0169 false); 0170 QCOMPARE(PerceptualColor::isInRange<double>(5, 4, nan), // 0171 false); 0172 } 0173 } 0174 0175 void testRounding() 0176 { 0177 QCOMPARE(roundToDigits(12.3456, 6), 12.345600); 0178 QCOMPARE(roundToDigits(12.3456, 5), 12.34560); 0179 QCOMPARE(roundToDigits(12.3456, 4), 12.3456); 0180 QCOMPARE(roundToDigits(12.3456, 3), 12.346); 0181 QCOMPARE(roundToDigits(12.3456, 2), 12.35); 0182 QCOMPARE(roundToDigits(12.3456, 1), 12.3); 0183 QCOMPARE(roundToDigits(12.3456, 0), 12.); 0184 QCOMPARE(roundToDigits(12.3456, -1), 10.); 0185 QCOMPARE(roundToDigits(12.3456, -2), 0.); 0186 QCOMPARE(roundToDigits(92.3456, -2), 100.); 0187 0188 QCOMPARE(roundToDigits(-12.3456, 6), -12.345600); 0189 QCOMPARE(roundToDigits(-12.3456, 5), -12.34560); 0190 QCOMPARE(roundToDigits(-12.3456, 4), -12.3456); 0191 QCOMPARE(roundToDigits(-12.3456, 3), -12.346); 0192 QCOMPARE(roundToDigits(-12.3456, 2), -12.35); 0193 QCOMPARE(roundToDigits(-12.3456, 1), -12.3); 0194 QCOMPARE(roundToDigits(-12.3456, 0), -12.); 0195 QCOMPARE(roundToDigits(-12.3456, -1), -10.); 0196 QCOMPARE(roundToDigits(-12.3456, -2), -0.); 0197 QCOMPARE(roundToDigits(-92.3456, -2), -100.); 0198 0199 if constexpr (std::numeric_limits<double>::has_infinity) { 0200 QCOMPARE( // 0201 roundToDigits(std::numeric_limits<double>::infinity(), 6), // 0202 std::numeric_limits<double>::infinity()); 0203 QCOMPARE( // 0204 roundToDigits(-std::numeric_limits<double>::infinity(), 6), // 0205 -std::numeric_limits<double>::infinity()); 0206 } 0207 0208 if constexpr (std::numeric_limits<double>::has_quiet_NaN) { 0209 constexpr auto quietNan = std::numeric_limits<double>::quiet_NaN(); 0210 QVERIFY(std::isnan(roundToDigits(quietNan, 6))); 0211 } 0212 0213 if constexpr (std::numeric_limits<double>::has_signaling_NaN) { 0214 constexpr auto signalingNan = // 0215 std::numeric_limits<double>::signaling_NaN(); 0216 QVERIFY(std::isnan(roundToDigits(signalingNan, 6))); 0217 } 0218 } 0219 0220 void testIsOdd() 0221 { 0222 QCOMPARE(isOdd(-2), false); 0223 QCOMPARE(isOdd(-1), true); 0224 QCOMPARE(isOdd(-0), false); 0225 QCOMPARE(isOdd(0), false); 0226 QCOMPARE(isOdd(1), true); 0227 QCOMPARE(isOdd(2), false); 0228 } 0229 0230 void testIsNearlyEqual() 0231 { 0232 QVERIFY(isNearlyEqual(2., 2.)); 0233 QVERIFY(isNearlyEqual(1.5, 1.5)); 0234 QVERIFY(isNearlyEqual(1., 1.)); 0235 QVERIFY(isNearlyEqual(0.5, 0.5)); 0236 QVERIFY(isNearlyEqual(0., 0.)); 0237 QVERIFY(isNearlyEqual(-0., 0.)); 0238 QVERIFY(isNearlyEqual(0., -0.)); 0239 QVERIFY(isNearlyEqual(-0., -0.)); 0240 QVERIFY(isNearlyEqual(-0.5, -0.5)); 0241 0242 QVERIFY(!isNearlyEqual(0., 1.)); 0243 0244 if constexpr (std::numeric_limits<double>::has_infinity) { 0245 QVERIFY(isNearlyEqual(std::numeric_limits<double>::infinity(), // 0246 std::numeric_limits<double>::infinity())); 0247 QVERIFY(isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0248 -std::numeric_limits<double>::infinity())); 0249 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::infinity(), // 0250 -std::numeric_limits<double>::infinity())); 0251 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::infinity(), // 0252 5.)); 0253 QVERIFY(!isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0254 5.)); 0255 } 0256 0257 if constexpr (std::numeric_limits<double>::has_quiet_NaN) { 0258 // NaN should never compare equal to itself or any other value. 0259 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0260 5.)); 0261 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0262 0.)); 0263 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0264 std::numeric_limits<double>::infinity())); 0265 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0266 -std::numeric_limits<double>::infinity())); 0267 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0268 std::numeric_limits<double>::quiet_NaN())); 0269 0270 // NaN should never compare equal to itself or any other value. 0271 QVERIFY( // 0272 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0273 5.)); 0274 QVERIFY( // 0275 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0276 0.)); 0277 QVERIFY( // 0278 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0279 std::numeric_limits<double>::infinity())); 0280 QVERIFY( // 0281 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0282 -std::numeric_limits<double>::infinity())); 0283 QVERIFY( // 0284 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0285 std::numeric_limits<double>::signaling_NaN())); 0286 } 0287 0288 if constexpr (std::numeric_limits<double>::has_signaling_NaN // 0289 && std::numeric_limits<double>::has_quiet_NaN // 0290 ) { 0291 QVERIFY( // 0292 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0293 std::numeric_limits<double>::quiet_NaN())); 0294 } 0295 } 0296 0297 void testIsNearlyEqualEpsilon() 0298 { 0299 QVERIFY(isNearlyEqual(2., 2., 0.1)); 0300 QVERIFY(isNearlyEqual(1.5, 1.5, 0.1)); 0301 QVERIFY(isNearlyEqual(1., 1., 0.1)); 0302 QVERIFY(isNearlyEqual(0.5, 0.5, 0.1)); 0303 QVERIFY(isNearlyEqual(0., 0., 0.1)); 0304 QVERIFY(isNearlyEqual(-0., 0., 0.1)); 0305 QVERIFY(isNearlyEqual(0., -0., 0.1)); 0306 QVERIFY(isNearlyEqual(-0., -0., 0.1)); 0307 QVERIFY(isNearlyEqual(-0.5, -0.5, 0.1)); 0308 0309 QVERIFY(isNearlyEqual(2., 2., 0.)); 0310 QVERIFY(isNearlyEqual(2., 2., -0.)); 0311 QVERIFY(isNearlyEqual(2., 2., -1.)); 0312 0313 QVERIFY(isNearlyEqual(5., 6., 2.)); 0314 0315 QVERIFY(!isNearlyEqual(0., 1., 0.)); 0316 QVERIFY(!isNearlyEqual(0., 1., -0.)); 0317 QVERIFY(!isNearlyEqual(0., 1., -1.)); 0318 0319 if constexpr (std::numeric_limits<double>::has_infinity) { 0320 QVERIFY(isNearlyEqual(std::numeric_limits<double>::infinity(), // 0321 std::numeric_limits<double>::infinity(), 0322 2.)); 0323 QVERIFY(isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0324 -std::numeric_limits<double>::infinity(), 0325 2.)); 0326 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::infinity(), // 0327 -std::numeric_limits<double>::infinity(), 0328 2.)); 0329 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::infinity(), // 0330 5., 0331 2.)); 0332 QVERIFY(!isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0333 5., 0334 2.)); 0335 0336 QVERIFY(isNearlyEqual(std::numeric_limits<double>::infinity(), // 0337 std::numeric_limits<double>::infinity(), 0338 std::numeric_limits<double>::infinity())); 0339 QVERIFY(isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0340 -std::numeric_limits<double>::infinity(), 0341 std::numeric_limits<double>::infinity())); 0342 0343 QVERIFY(isNearlyEqual(std::numeric_limits<double>::infinity(), // 0344 std::numeric_limits<double>::infinity(), 0345 -std::numeric_limits<double>::infinity())); 0346 QVERIFY(isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0347 -std::numeric_limits<double>::infinity(), 0348 -std::numeric_limits<double>::infinity())); 0349 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::infinity(), // 0350 -std::numeric_limits<double>::infinity(), 0351 -std::numeric_limits<double>::infinity())); 0352 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::infinity(), // 0353 5., 0354 -std::numeric_limits<double>::infinity())); 0355 QVERIFY(!isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0356 5., 0357 -std::numeric_limits<double>::infinity())); 0358 0359 if constexpr (std::numeric_limits<double>::has_quiet_NaN) { 0360 QVERIFY( // 0361 !isNearlyEqual(std::numeric_limits<double>::infinity(), // 0362 std::numeric_limits<double>::infinity(), 0363 std::numeric_limits<double>::quiet_NaN())); 0364 QVERIFY( // 0365 !isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0366 -std::numeric_limits<double>::infinity(), 0367 std::numeric_limits<double>::quiet_NaN())); 0368 QVERIFY( // 0369 !isNearlyEqual(std::numeric_limits<double>::infinity(), // 0370 -std::numeric_limits<double>::infinity(), 0371 std::numeric_limits<double>::quiet_NaN())); 0372 QVERIFY( // 0373 !isNearlyEqual(std::numeric_limits<double>::infinity(), // 0374 5., 0375 std::numeric_limits<double>::quiet_NaN())); 0376 QVERIFY( // 0377 !isNearlyEqual(-std::numeric_limits<double>::infinity(), // 0378 5., 0379 std::numeric_limits<double>::quiet_NaN())); 0380 } 0381 } 0382 0383 if constexpr (std::numeric_limits<double>::has_quiet_NaN) { 0384 // NaN should never compare equal to itself or any other value. 0385 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0386 5., 0387 2.)); 0388 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0389 0., 0390 2.)); 0391 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0392 std::numeric_limits<double>::infinity(), 0393 2.)); 0394 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0395 -std::numeric_limits<double>::infinity(), 0396 2.)); 0397 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0398 std::numeric_limits<double>::quiet_NaN(), 0399 2.)); 0400 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0401 5., 0402 std::numeric_limits<double>::infinity())); 0403 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0404 0., 0405 std::numeric_limits<double>::infinity())); 0406 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0407 std::numeric_limits<double>::infinity(), 0408 std::numeric_limits<double>::infinity())); 0409 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0410 -std::numeric_limits<double>::infinity(), 0411 std::numeric_limits<double>::infinity())); 0412 QVERIFY(!isNearlyEqual(std::numeric_limits<double>::quiet_NaN(), // 0413 std::numeric_limits<double>::quiet_NaN(), 0414 std::numeric_limits<double>::infinity())); 0415 0416 // NaN should never compare equal to itself or any other value. 0417 QVERIFY( // 0418 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0419 5., 0420 2.)); 0421 QVERIFY( // 0422 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0423 0., 0424 2.)); 0425 QVERIFY( // 0426 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0427 std::numeric_limits<double>::infinity(), 0428 2.)); 0429 QVERIFY( // 0430 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0431 -std::numeric_limits<double>::infinity(), 0432 2.)); 0433 QVERIFY( // 0434 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0435 std::numeric_limits<double>::signaling_NaN(), 0436 2.)); 0437 0438 QVERIFY( // 0439 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0440 5., 0441 std::numeric_limits<double>::infinity())); 0442 QVERIFY( // 0443 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0444 0., 0445 std::numeric_limits<double>::infinity())); 0446 QVERIFY( // 0447 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0448 std::numeric_limits<double>::infinity(), 0449 std::numeric_limits<double>::infinity())); 0450 QVERIFY( // 0451 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0452 -std::numeric_limits<double>::infinity(), 0453 std::numeric_limits<double>::infinity())); 0454 QVERIFY( // 0455 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0456 std::numeric_limits<double>::signaling_NaN(), 0457 std::numeric_limits<double>::infinity())); 0458 } 0459 0460 if constexpr (std::numeric_limits<double>::has_signaling_NaN // 0461 && std::numeric_limits<double>::has_quiet_NaN // 0462 ) { 0463 QVERIFY( // 0464 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0465 std::numeric_limits<double>::quiet_NaN(), 0466 2.)); 0467 QVERIFY( // 0468 !isNearlyEqual(std::numeric_limits<double>::signaling_NaN(), // 0469 std::numeric_limits<double>::quiet_NaN(), 0470 std::numeric_limits<double>::infinity())); 0471 } 0472 } 0473 0474 void testNormalizeAngle() 0475 { 0476 QCOMPARE(normalizedAngle360(0.), 0); 0477 QCOMPARE(normalizedAngle360(359.9), 359.9); 0478 QCOMPARE(normalizedAngle360(360.), 0); 0479 QCOMPARE(normalizedAngle360(720.), 0); 0480 QCOMPARE(normalizedAngle360(-1.), 359); 0481 QCOMPARE(normalizedAngle360(-1.3), 358.7); 0482 } 0483 0484 void testCreateSquareMatrix3() 0485 { 0486 // clang-format off 0487 const auto temp = createSquareMatrix3( 0488 1, 2, 3, 0489 4, 5, 6, 0490 7, 8, 9); 0491 // clang-format on 0492 QCOMPARE(temp(0, 0), 1); 0493 QCOMPARE(temp(0, 1), 2); 0494 QCOMPARE(temp(0, 2), 3); 0495 QCOMPARE(temp(1, 0), 4); 0496 QCOMPARE(temp(1, 1), 5); 0497 QCOMPARE(temp(1, 2), 6); 0498 QCOMPARE(temp(2, 0), 7); 0499 QCOMPARE(temp(2, 1), 8); 0500 QCOMPARE(temp(2, 2), 9); 0501 } 0502 0503 void testInverseMatrixFromNonInvertible() 0504 { 0505 // clang-format off 0506 const auto temp = createSquareMatrix3( 0507 1, 2, 3, // 0508 4, 5, 6, // 0509 7, 8, 9); 0510 // clang-format on 0511 const auto inverse = inverseMatrix(temp); 0512 QVERIFY(!inverse.has_value()); 0513 } 0514 0515 void testInverseMatrixFromInvertible() 0516 { 0517 // clang-format off 0518 const auto temp = createSquareMatrix3( 0519 1, 2, 1, // 0520 0, 1, 3, // 0521 -1, 0, 1); 0522 // clang-format on 0523 const auto actualInverse = inverseMatrix(temp); 0524 // clang-format off 0525 const auto expectedInverse = createSquareMatrix3( 0526 -0.25, 0.5, -1.25, 0527 0.75, -0.5, 0.75, 0528 -0.25, 0.5, -0.25); 0529 // clang-format on 0530 QCOMPARE(actualInverse, expectedInverse); 0531 } 0532 0533 void testCreateTrio() 0534 { 0535 const Trio temp = createTrio(7, 6, 5); 0536 QCOMPARE(temp(0, 0), 7); 0537 QCOMPARE(temp(1, 0), 6); 0538 QCOMPARE(temp(2, 0), 5); 0539 } 0540 0541 void testCreateMatrix() 0542 { 0543 const auto temp = createMatrix<2, 2, int>(7, 6, 5, 4); 0544 QCOMPARE(temp(0, 0), 7); 0545 QCOMPARE(temp(0, 1), 6); 0546 QCOMPARE(temp(1, 0), 5); 0547 QCOMPARE(temp(1, 1), 4); 0548 } 0549 0550 void testDecimalPlaces_data() 0551 { 0552 QTest::addColumn<int>("maxRange"); 0553 QTest::addColumn<int>("significantFigures"); 0554 QTest::addColumn<int>("expected"); 0555 0556 QTest::newRow("0 << -1 << 0") << 0 << -1 << 0; 0557 QTest::newRow("0 << 0 << 0") << 0 << 0 << 0; 0558 QTest::newRow("0 << 1 << 0") << 0 << 1 << 0; 0559 QTest::newRow("0 << 2 << 1") << 0 << 2 << 1; 0560 QTest::newRow("0 << 3 << 2") << 0 << 3 << 2; 0561 QTest::newRow("0 << 4 << 3") << 0 << 4 << 3; 0562 0563 QTest::newRow("1 << -1 << 0") << 1 << -1 << 0; 0564 QTest::newRow("1 << 0 << 0") << 1 << 0 << 0; 0565 QTest::newRow("1 << 1 << 0") << 1 << 1 << 0; 0566 QTest::newRow("1 << 2 << 1") << 1 << 2 << 1; 0567 QTest::newRow("1 << 3 << 2") << 1 << 3 << 2; 0568 QTest::newRow("1 << 4 << 3") << 1 << 4 << 3; 0569 0570 QTest::newRow("2 << -1 << 0") << 2 << -1 << 0; 0571 QTest::newRow("2 << 0 << 0") << 2 << 0 << 0; 0572 QTest::newRow("2 << 1 << 0") << 2 << 1 << 0; 0573 QTest::newRow("2 << 2 << 1") << 2 << 2 << 1; 0574 QTest::newRow("2 << 3 << 2") << 2 << 3 << 2; 0575 QTest::newRow("2 << 4 << 3") << 2 << 4 << 3; 0576 0577 QTest::newRow("100 << -1 << 0") << 100 << -1 << 0; 0578 QTest::newRow("100 << 0 << 0") << 100 << 0 << 0; 0579 QTest::newRow("100 << 1 << 0") << 100 << 1 << 0; 0580 QTest::newRow("100 << 2 << 0") << 100 << 2 << 0; 0581 QTest::newRow("100 << 3 << 0") << 100 << 3 << 0; 0582 QTest::newRow("100 << 4 << 1") << 100 << 4 << 1; 0583 0584 QTest::newRow("255 << -1 << 0") << 255 << -1 << 0; 0585 QTest::newRow("255 << 0 << 0") << 255 << 0 << 0; 0586 QTest::newRow("255 << 1 << 0") << 255 << 1 << 0; 0587 QTest::newRow("255 << 2 << 0") << 255 << 2 << 0; 0588 QTest::newRow("255 << 3 << 0") << 255 << 3 << 0; 0589 QTest::newRow("255 << 4 << 1") << 255 << 4 << 1; 0590 0591 QTest::newRow("-255 << -1 << 0") << -255 << -1 << 0; 0592 QTest::newRow("-255 << 0 << 0") << -255 << 0 << 0; 0593 QTest::newRow("-255 << 1 << 0") << -255 << 1 << 0; 0594 QTest::newRow("-255 << 2 << 0") << -255 << 2 << 0; 0595 QTest::newRow("-255 << 3 << 0") << -255 << 3 << 0; 0596 QTest::newRow("-255 << 4 << 1") << -255 << 4 << 1; 0597 0598 QTest::newRow("360 << -1 << 0") << 360 << -1 << 0; 0599 QTest::newRow("360 << 0 << 0") << 360 << 0 << 0; 0600 QTest::newRow("360 << 1 << 0") << 360 << 1 << 0; 0601 QTest::newRow("360 << 2 << 0") << 360 << 2 << 0; 0602 QTest::newRow("360 << 3 << 0") << 360 << 3 << 0; 0603 QTest::newRow("360 << 4 << 1") << 360 << 4 << 1; 0604 } 0605 0606 void testDecimalPlaces() 0607 { 0608 QFETCH(int, maxRange); 0609 QFETCH(int, significantFigures); 0610 QFETCH(int, expected); 0611 0612 QCOMPARE(decimalPlaces(maxRange, significantFigures), expected); 0613 } 0614 0615 void testNormalizePolar360() 0616 { 0617 double radius; 0618 double angleDegree; 0619 0620 // Value of 0, 0° 0621 radius = 0; 0622 angleDegree = 0; 0623 normalizePolar360(radius, angleDegree); 0624 normalizePolar360(radius, angleDegree); 0625 QCOMPARE(radius, 0); 0626 QCOMPARE(angleDegree, 0); 0627 0628 // Same for initialization with -0, 0 0629 radius = -0; 0630 angleDegree = 0; 0631 normalizePolar360(radius, angleDegree); 0632 QCOMPARE(radius, 0); 0633 QCOMPARE(angleDegree, 0); 0634 0635 // Yet normalized values are taken as-is 0636 radius = 2; 0637 angleDegree = 3; 0638 normalizePolar360(radius, angleDegree); 0639 QCOMPARE(radius, 2); 0640 QCOMPARE(angleDegree, 3); 0641 0642 // Negative radii are normalized (180° shift for angle) 0643 radius = -2; 0644 angleDegree = 183; 0645 normalizePolar360(radius, angleDegree); 0646 QCOMPARE(radius, 2); 0647 QCOMPARE(angleDegree, 3); 0648 0649 // Out-of-range angle is normalized 0650 radius = 2; 0651 angleDegree = 363; 0652 normalizePolar360(radius, angleDegree); 0653 QCOMPARE(radius, 2); 0654 QCOMPARE(angleDegree, 3); 0655 0656 radius = 2; 0657 angleDegree = -357; 0658 normalizePolar360(radius, angleDegree); 0659 QCOMPARE(radius, 2); 0660 QCOMPARE(angleDegree, 3); 0661 0662 // Also when both radius and angle are 0663 // out-of-range, normalization works 0664 radius = -2; 0665 angleDegree = -357; 0666 normalizePolar360(radius, angleDegree); 0667 QCOMPARE(radius, 2); 0668 QCOMPARE(angleDegree, 183); 0669 radius = -2; 0670 angleDegree = -717; 0671 normalizePolar360(radius, angleDegree); 0672 QCOMPARE(radius, 2); 0673 QCOMPARE(angleDegree, 183); 0674 radius = -2; 0675 angleDegree = 363; 0676 normalizePolar360(radius, angleDegree); 0677 QCOMPARE(radius, 2); 0678 QCOMPARE(angleDegree, 183); 0679 radius = -2; 0680 angleDegree = 723; 0681 normalizePolar360(radius, angleDegree); 0682 QCOMPARE(radius, 2); 0683 QCOMPARE(angleDegree, 183); 0684 0685 // When radius is 0, angle (while meaningless) is 0686 // preserved (but normalized) 0687 radius = 0; 0688 angleDegree = 150; 0689 normalizePolar360(radius, angleDegree); 0690 QCOMPARE(radius, 0); 0691 QCOMPARE(angleDegree, 150); 0692 radius = 0; 0693 angleDegree = 370; 0694 normalizePolar360(radius, angleDegree); 0695 QCOMPARE(radius, 0); 0696 QCOMPARE(angleDegree, 10); 0697 0698 // When radius is -0, angle (while meaningless) is 0699 // preserved (but normalized) 0700 radius = -0; 0701 angleDegree = 150; 0702 normalizePolar360(radius, angleDegree); 0703 QCOMPARE(radius, 0); 0704 QCOMPARE(angleDegree, 150); 0705 radius = -0; 0706 angleDegree = 370; 0707 normalizePolar360(radius, angleDegree); 0708 QCOMPARE(radius, 0); 0709 QCOMPARE(angleDegree, 10); 0710 0711 // Edge case: 360° 0712 radius = -0; 0713 angleDegree = 360; 0714 normalizePolar360(radius, angleDegree); 0715 QCOMPARE(radius, 0); 0716 QCOMPARE(angleDegree, 0); 0717 radius = 0; 0718 angleDegree = 360; 0719 normalizePolar360(radius, angleDegree); 0720 QCOMPARE(radius, 0); 0721 QCOMPARE(angleDegree, 0); 0722 radius = 5; 0723 angleDegree = 360; 0724 normalizePolar360(radius, angleDegree); 0725 QCOMPARE(radius, 5); 0726 QCOMPARE(angleDegree, 0); 0727 } 0728 }; 0729 0730 } // namespace PerceptualColor 0731 0732 QTEST_MAIN(PerceptualColor::TestHelperMath) 0733 // The following “include” is necessary because we do not use a header file: 0734 #include "testhelpermath.moc"