diff options
Diffstat (limited to 'tests/auto/corelib/kernel/qmath/tst_qmath.cpp')
-rw-r--r-- | tests/auto/corelib/kernel/qmath/tst_qmath.cpp | 189 |
1 files changed, 148 insertions, 41 deletions
diff --git a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp index feb704e0aa..1961b71d83 100644 --- a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp +++ b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp @@ -1,34 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> #include <qmath.h> +#include <qfloat16.h> class tst_QMath : public QObject { @@ -39,6 +15,11 @@ private slots: void degreesToRadians(); void radiansToDegrees_data(); void radiansToDegrees(); + void trigonometry_data(); + void trigonometry(); + void hypotenuse(); + void funcs_data(); + void funcs(); void qNextPowerOfTwo32S_data(); void qNextPowerOfTwo32S(); void qNextPowerOfTwo64S_data(); @@ -131,6 +112,143 @@ void tst_QMath::radiansToDegrees() QCOMPARE(qRadiansToDegrees(radiansDouble), degreesDouble); } +void tst_QMath::trigonometry_data() +{ + QTest::addColumn<double>("x"); + QTest::addColumn<double>("y"); + QTest::addColumn<double>("angle"); + + QTest::newRow("zero") << 1.0 << 0.0 << 0.0; + QTest::newRow("turn/4") << 0.0 << 1.0 << M_PI_2; + QTest::newRow("turn/2") << -1.0 << 0.0 << M_PI; + QTest::newRow("3*turn/4") << 0.0 << -1.0 << -M_PI_2; +} + +void tst_QMath::trigonometry() +{ + QFETCH(const double, x); + QFETCH(const double, y); + QFETCH(const double, angle); + const double hypot = qHypot(x, y); + QVERIFY(hypot > 0); + QCOMPARE(qAtan2(y, x), angle); + QCOMPARE(qSin(angle), y / hypot); + if (x >= 0 && (y || x)) // aSin() always in right half-plane + QCOMPARE(qAsin(y / hypot), angle); + QCOMPARE(qCos(angle), x / hypot); + if (y >= 0 && (y || x)) // aCos() always in upper half-plane + QCOMPARE(qAcos(x / hypot), angle); + if (x > 0) { + QCOMPARE(qTan(angle), y / x); + QCOMPARE(qAtan(y / x), angle); + } +} + +void tst_QMath::hypotenuse() +{ + // Correct return-types, particularly when qfloat16 is involved: + static_assert(std::is_same<decltype(qHypot(qfloat16(1), qfloat16(1), qfloat16(1), + qfloat16(1), qfloat16(1), qfloat16(1), + qfloat16(1), qfloat16(1), qfloat16(1))), + qfloat16>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), qfloat16(4), qfloat16(12))), + qfloat16>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), qfloat16(4), 12.0f)), float>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), 4.0f, qfloat16(12))), float>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, qfloat16(4), qfloat16(12))), float>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), 4.0f, 12.0f)), float>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, qfloat16(4), 12.0f)), float>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, 4.0f, qfloat16(12))), float>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), qfloat16(4))), qfloat16>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, qfloat16(4))), float>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), 4.0f)), float>::value); + static_assert(std::is_same<decltype(qHypot(3.0, qfloat16(4))), double>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), 4.0)), double>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), 4)), double>::value); + static_assert(std::is_same<decltype(qHypot(3, qfloat16(4))), double>::value); + static_assert(std::is_same<decltype(qHypot(qfloat16(3), 4.0L)), long double>::value); + static_assert(std::is_same<decltype(qHypot(3.0L, qfloat16(4))), long double>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, 4.0f)), float>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, 4.0)), double>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, 4)), double>::value); + static_assert(std::is_same<decltype(qHypot(3.0f, 4.0L)), long double>::value); + static_assert(std::is_same<decltype(qHypot(3.0, 4.0f)), double>::value); + static_assert(std::is_same<decltype(qHypot(3, 4.0f)), double>::value); + static_assert(std::is_same<decltype(qHypot(3.0L, 4.0f)), long double>::value); + static_assert(std::is_same<decltype(qHypot(3.0, 4.0L)), long double>::value); + static_assert(std::is_same<decltype(qHypot(3.0L, 4.0)), long double>::value); + static_assert(std::is_same<decltype(qHypot(3.0, 4.0)), double>::value); + static_assert(std::is_same<decltype(qHypot(3, 4.0)), double>::value); + static_assert(std::is_same<decltype(qHypot(3.0, 4)), double>::value); + static_assert(std::is_same<decltype(qHypot(3, 4)), double>::value); + + // Works for all numeric types: + QCOMPARE(qHypot(3, 4), 5); + QCOMPARE(qHypot(qfloat16(5), qfloat16(12)), qfloat16(13)); + QCOMPARE(qHypot(3.0f, 4.0f, 12.0f), 13.0f); + QCOMPARE(qHypot(3.0, 4.0, 12.0, 84.0), 85.0); + QCOMPARE(qHypot(3.0f, 4.0f, 12.0f, 84.0f, 720.0f), 725.0f); + QCOMPARE(qHypot(3.0, 4.0, 12.0, 84.0, 3612.0), 3613.0); + // Integral gets promoted to double: + QCOMPARE(qHypot(1, 1), M_SQRT2); + // Caller can mix types freely: + QCOMPARE(qHypot(3.0f, 4, 12.0, 84.0f, qfloat16(720), 10500), 10525); + // NaN wins over any finite: + QCOMPARE(qHypot(3, 4.0, 12.0f, qQNaN()), qQNaN()); + QCOMPARE(qHypot(3, 4.0, qQNaN(), 12.0f), qQNaN()); + QCOMPARE(qHypot(3, qQNaN(), 4.0, 12.0f), qQNaN()); + QCOMPARE(qHypot(qQNaN(), 3, 4.0, 12.0f), qQNaN()); + // but Infinity beats NaN: + QCOMPARE(qHypot(3, 4.0f, -qInf(), qQNaN()), qInf()); + QCOMPARE(qHypot(3, -qInf(), 4.0f, qQNaN()), qInf()); + QCOMPARE(qHypot(-qInf(), 3, 4.0f, qQNaN()), qInf()); + QCOMPARE(qHypot(qQNaN(), 3, -qInf(), 4.0f), qInf()); + QCOMPARE(qHypot(3, qQNaN(), 4.0f, -qInf()), qInf()); + QCOMPARE(qHypot(3, 4.0f, qQNaN(), -qInf()), qInf()); + // Components whose squares sum to zero don't change the end result: + const double minD = std::numeric_limits<double>::min(); + QVERIFY(minD * minD + minD * minD == 0); // *NOT* QCOMPARE + QCOMPARE(qHypot(minD, minD, 12.0), 12.0); + const float minF = std::numeric_limits<float>::min(); + QVERIFY(minF * minF + minF * minF == 0.0f); // *NOT* QCOMPARE + QCOMPARE(qHypot(minF, minF, 12.0f), 12.0f); + const qfloat16 minF16 = std::numeric_limits<qfloat16>::min(); + QVERIFY(minF16 * minF16 + minF16 * minF16 == qfloat16(0)); // *NOT* QCOMPARE + QCOMPARE(qHypot(minF16, minF16, qfloat16(12)), qfloat16(12)); +} + +void tst_QMath::funcs_data() +{ + QTest::addColumn<double>("value"); + QTest::addColumn<int>("floor"); + QTest::addColumn<int>("ceil"); + QTest::addColumn<double>("abs"); + QTest::addColumn<double>("sqrt"); + QTest::addColumn<double>("log"); + QTest::addColumn<double>("exp"); + QTest::addColumn<double>("cube"); + const double nan = qQNaN(); + + QTest::newRow("0") << 0.0 << 0 << 0 << 0.0 << 0.0 << nan << 1.0 << 0.0; + QTest::newRow("1.44") + << 1.44 << 1 << 2 << 1.44 << 1.2 << 0.36464311358790924 << 4.220695816996552 << 2.985984; + QTest::newRow("-1.44") + << -1.44 << -2 << -1 << 1.44 << nan << nan << 0.23692775868212176 << -2.985984; +} + +void tst_QMath::funcs() +{ + QFETCH(double, value); + QTEST(qFloor(value), "floor"); + QTEST(qCeil(value), "ceil"); + QTEST(qFabs(value), "abs"); + if (value >= 0) + QTEST(qSqrt(value), "sqrt"); + if (value > 0) + QTEST(qLn(value), "log"); + QTEST(qExp(value), "exp"); + QTEST(qPow(value, 3), "cube"); +} void tst_QMath::qNextPowerOfTwo32S_data() { @@ -147,9 +265,6 @@ void tst_QMath::qNextPowerOfTwo32S_data() QTest::newRow("2^30") << (1 << 30) << (1U << 31); QTest::newRow("2^30 + 1") << (1 << 30) + 1 << (1U << 31); QTest::newRow("2^31 - 1") << 0x7FFFFFFF << (1U<<31); - QTest::newRow("-1") << -1 << 0U; - QTest::newRow("-128") << -128 << 0U; - QTest::newRow("-(2^31)") << int(0x80000000) << 0U; } void tst_QMath::qNextPowerOfTwo32S() @@ -175,8 +290,6 @@ void tst_QMath::qNextPowerOfTwo32U_data() QTest::newRow("2^30") << (1U << 30) << (1U << 31); QTest::newRow("2^30 + 1") << (1U << 30) + 1 << (1U << 31); QTest::newRow("2^31 - 1") << 2147483647U << 2147483648U; - QTest::newRow("2^31") << 2147483648U << 0U; - QTest::newRow("2^31 + 1") << 2147483649U << 0U; } void tst_QMath::qNextPowerOfTwo32U() @@ -203,10 +316,6 @@ void tst_QMath::qNextPowerOfTwo64S_data() QTest::newRow("2^31") << Q_INT64_C(2147483648) << Q_UINT64_C(0x100000000); QTest::newRow("2^31 + 1") << Q_INT64_C(2147483649) << Q_UINT64_C(0x100000000); QTest::newRow("2^63 - 1") << Q_INT64_C(0x7FFFFFFFFFFFFFFF) << Q_UINT64_C(0x8000000000000000); - QTest::newRow("-1") << Q_INT64_C(-1) << Q_UINT64_C(0); - QTest::newRow("-128") << Q_INT64_C(-128) << Q_UINT64_C(0); - QTest::newRow("-(2^31)") << -Q_INT64_C(0x80000000) << Q_UINT64_C(0); - QTest::newRow("-(2^63)") << (qint64)Q_INT64_C(0x8000000000000000) << Q_UINT64_C(0); } void tst_QMath::qNextPowerOfTwo64S() @@ -230,8 +339,6 @@ void tst_QMath::qNextPowerOfTwo64U_data() QTest::newRow("65535") << Q_UINT64_C(65535) << Q_UINT64_C(65536); QTest::newRow("65536") << Q_UINT64_C(65536) << Q_UINT64_C(131072); QTest::newRow("2^63 - 1") << Q_UINT64_C(0x7FFFFFFFFFFFFFFF) << Q_UINT64_C(0x8000000000000000); - QTest::newRow("2^63") << Q_UINT64_C(0x8000000000000000) << Q_UINT64_C(0); - QTest::newRow("2^63 + 1") << Q_UINT64_C(0x8000000000000001) << Q_UINT64_C(0); } void tst_QMath::qNextPowerOfTwo64U() |