summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel/qmath/tst_qmath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/kernel/qmath/tst_qmath.cpp')
-rw-r--r--tests/auto/corelib/kernel/qmath/tst_qmath.cpp189
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()