summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2025-12-10 15:18:24 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2025-12-12 16:45:21 +0000
commit06e42bc08be6f43c8257b3c6667e52a1269a6220 (patch)
treee468279e0b5925816af2d9a5ed125b9f8390f334
parent95c7df09dc122402c2d28c670818f307c1f64668 (diff)
Deploy qHypot() to eliminate sqrt(sum of squares)6.10
Applies to QDoubleMatrix4x4, QDoubleVector2D, QDoubleVector3D. Summing squares and then taking the square root has some {ov,und}erflow failures when the squares are logarithmically beyond about half way to the bounds of the representable values of the type. A hypot() implementation - such as qHypot(), which copes with arbitrarily many parameters - takes care to avoid those failures, thereby producing finite non-zero answers for a broader range of vectors. Using hypot() also preserves precision better, for related reasons, and handles infinities and NaN more coherently, should they arise. In the process, reverse some qFuzzyCompare() || qFuzzyIsNull() checks so that the is-null check is done first, satisfying the precondition of the comparison (neither argument should be zero) before it is reached. Task-number: QTBUG-142020 Pick-to: 6.8 6.5 Change-Id: I34eb88a5e518155ab7c4584ec07a20404a1c0eb5 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Matthias Rauter <matthias.rauter@qt.io> (cherry picked from commit 7e81c07241c3cd65e1f8890de24b99ba4d272e5c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 5c6e3435c052b5d6278fa42e16dfbbd67929c49f)
-rw-r--r--src/positioning/qdoublematrix4x4.cpp27
-rw-r--r--src/positioning/qdoublevector2d.cpp14
-rw-r--r--src/positioning/qdoublevector3d.cpp18
3 files changed, 20 insertions, 39 deletions
diff --git a/src/positioning/qdoublematrix4x4.cpp b/src/positioning/qdoublematrix4x4.cpp
index 23f5229d..d82c19a3 100644
--- a/src/positioning/qdoublematrix4x4.cpp
+++ b/src/positioning/qdoublematrix4x4.cpp
@@ -529,14 +529,11 @@ void QDoubleMatrix4x4::rotate(double angle, double x, double y, double z)
return;
}
- double len = double(x) * double(x) +
- double(y) * double(y) +
- double(z) * double(z);
- if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
- len = std::sqrt(len);
- x = double(double(x) / len);
- y = double(double(y) / len);
- z = double(double(z) / len);
+ if (double len = qHypot(x, y, z);
+ !qFuzzyIsNull(len) && !qFuzzyCompare(len, 1.0)) {
+ x /= len;
+ y /= len;
+ z /= len;
}
double ic = 1.0 - c;
QDoubleMatrix4x4 rot(1); // The "1" says to not load the identity.
@@ -629,14 +626,12 @@ void QDoubleMatrix4x4::projectedRotate(double angle, double x, double y, double
flagBits = General;
return;
}
- double len = double(x) * double(x) +
- double(y) * double(y) +
- double(z) * double(z);
- if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
- len = std::sqrt(len);
- x = double(double(x) / len);
- y = double(double(y) / len);
- z = double(double(z) / len);
+
+ if (const double len = qHypot(x, y, z);
+ !qFuzzyIsNull(len) && !qFuzzyCompare(len, 1.0)) {
+ x /= len;
+ y /= len;
+ z /= len;
}
double ic = 1.0 - c;
QDoubleMatrix4x4 rot(1); // The "1" says to not load the identity.
diff --git a/src/positioning/qdoublevector2d.cpp b/src/positioning/qdoublevector2d.cpp
index 59d3b536..95a9c3d6 100644
--- a/src/positioning/qdoublevector2d.cpp
+++ b/src/positioning/qdoublevector2d.cpp
@@ -16,32 +16,26 @@ QDoubleVector2D::QDoubleVector2D(const QDoubleVector3D &vector) :
double QDoubleVector2D::length() const
{
- return qSqrt(xp * xp + yp * yp);
+ return qHypot(xp, yp);
}
QDoubleVector2D QDoubleVector2D::normalized() const
{
- // Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp);
+ const double len = length();
if (qFuzzyIsNull(len - 1.0))
return *this;
else if (!qFuzzyIsNull(len))
- return *this / (double)qSqrt(len);
+ return *this / len;
else
return QDoubleVector2D();
}
void QDoubleVector2D::normalize()
{
- // Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp);
+ double len = length();
if (qFuzzyIsNull(len - 1.0) || qFuzzyIsNull(len))
return;
- len = qSqrt(len);
-
xp /= len;
yp /= len;
}
diff --git a/src/positioning/qdoublevector3d.cpp b/src/positioning/qdoublevector3d.cpp
index 92ae8bcb..6b3a1b8f 100644
--- a/src/positioning/qdoublevector3d.cpp
+++ b/src/positioning/qdoublevector3d.cpp
@@ -10,29 +10,21 @@ QT_BEGIN_NAMESPACE
QDoubleVector3D QDoubleVector3D::normalized() const
{
- // Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp);
+ const double len = length();
if (qFuzzyIsNull(len - 1.0))
return *this;
else if (!qFuzzyIsNull(len))
- return *this / (double)qSqrt(len);
+ return *this / len;
else
return QDoubleVector3D();
}
void QDoubleVector3D::normalize()
{
- // Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp);
- if (qFuzzyIsNull(len - 1.0) || qFuzzyIsNull(len))
+ double len = length();
+ if (qFuzzyIsNull(len) || qFuzzyIsNull(len - 1.0))
return;
- len = qSqrt(len);
-
xp /= len;
yp /= len;
zp /= len;
@@ -67,7 +59,7 @@ double QDoubleVector3D::distanceToLine
double QDoubleVector3D::length() const
{
- return qSqrt(xp * xp + yp * yp + zp * zp);
+ return qHypot(xp, yp, zp);
}
#ifndef QT_NO_DEBUG_STREAM