summaryrefslogtreecommitdiffstats
path: root/src/corelib/global
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-11-27 20:02:57 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-01-14 09:57:40 -0800
commit0ca6ad8cfc0827775e5bf001cd8d17f247a1400f (patch)
tree841b51b08d392d6388782b529b729c23bd5ab514 /src/corelib/global
parentdd3c4cb9bfc965ae40e914216862fbb350c55992 (diff)
convertDoubleTo: move the precision upgrade test up
Hopefully, the compiler will realize that the suprema calculated below are actually bigger than these limits and make the appropriate dead code eliminations. Change-Id: I89446ea06b5742efb194fffd16bb99f78b26eb0e Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/corelib/global')
-rw-r--r--src/corelib/global/qnumeric_p.h17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 823a1812de..bb3f1a976b 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -189,6 +189,19 @@ template<typename T>
static inline bool convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
{
static_assert(std::numeric_limits<T>::is_integer);
+ static_assert(std::is_integral_v<T>);
+ constexpr bool TypeIsLarger = std::numeric_limits<T>::digits > std::numeric_limits<double>::digits;
+
+ if constexpr (TypeIsLarger) {
+ using S = std::make_signed_t<T>;
+ constexpr S max_mantissa = S(1) << std::numeric_limits<double>::digits;
+ // T has more bits than double's mantissa, so don't allow "upgrading"
+ // to T (makes it look like the number had more precision than really
+ // was transmitted)
+ if (!allow_precision_upgrade && (v > double(max_mantissa) || v < double(-max_mantissa - 1)))
+ return false;
+ }
+
// The [conv.fpint] (7.10 Floating-integral conversions) section of the C++
// standard says only exact conversions are guaranteed. Converting
@@ -211,10 +224,6 @@ static inline bool convertDoubleTo(double v, T *value, bool allow_precision_upgr
supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
v = fabs(v);
}
- if (std::is_integral<T>::value && sizeof(T) > 4 && !allow_precision_upgrade) {
- if (v > double(Q_INT64_C(1)<<53) || v < double(-((Q_INT64_C(1)<<53) + 1)))
- return false;
- }
*value = std::numeric_limits<T>::max();
if (v >= supremum)