1/****************************************************************************
2**
3** Copyright (C) 2019 The Qt Company Ltd.
4** Copyright (C) 2018 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#ifndef QNUMERIC_P_H
42#define QNUMERIC_P_H
43
44//
45// W A R N I N G
46// -------------
47//
48// This file is not part of the Qt API. It exists purely as an
49// implementation detail. This header file may change from version to
50// version without notice, or even be removed.
51//
52// We mean it.
53//
54
55#include "QtCore/private/qglobal_p.h"
56#include <cmath>
57#include <limits>
58
59#if defined(Q_CC_MSVC)
60# include <intrin.h>
61# include <float.h>
62# if defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_ARM_64)
63# define Q_INTRINSIC_MUL_OVERFLOW64
64# define Q_UMULH(v1, v2) __umulh(v1, v2);
65# define Q_SMULH(v1, v2) __mulh(v1, v2);
66# pragma intrinsic(__umulh)
67# pragma intrinsic(__mulh)
68# endif
69#endif
70
71# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
72#include <arm64_ghs.h>
73# define Q_INTRINSIC_MUL_OVERFLOW64
74# define Q_UMULH(v1, v2) __MULUH64(v1, v2);
75# define Q_SMULH(v1, v2) __MULSH64(v1, v2);
76#endif
77
78#if !defined(Q_CC_MSVC) && (defined(Q_OS_QNX) || defined(Q_CC_INTEL))
79# include <math.h>
80# ifdef isnan
81# define QT_MATH_H_DEFINES_MACROS
82QT_BEGIN_NAMESPACE
83namespace qnumeric_std_wrapper {
84// the 'using namespace std' below is cases where the stdlib already put the math.h functions in the std namespace and undefined the macros.
85Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
86Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
87Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
88Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(double d) { using namespace std; return fpclassify(d); }
89Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
90Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
91Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
92Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(float f) { using namespace std; return fpclassify(f); }
93}
94QT_END_NAMESPACE
95// These macros from math.h conflict with the real functions in the std namespace.
96# undef signbit
97# undef isnan
98# undef isinf
99# undef isfinite
100# undef fpclassify
101# endif // defined(isnan)
102#endif
103
104QT_BEGIN_NAMESPACE
105
106namespace qnumeric_std_wrapper {
107#if defined(QT_MATH_H_DEFINES_MACROS)
108# undef QT_MATH_H_DEFINES_MACROS
109Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); }
110Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); }
111Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); }
112Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return math_h_fpclassify(d); }
113Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); }
114Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); }
115Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); }
116Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return math_h_fpclassify(f); }
117#else
118Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(x: d); }
119Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(x: d); }
120Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(x: d); }
121Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return std::fpclassify(x: d); }
122Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(x: f); }
123Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(x: f); }
124Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(x: f); }
125Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return std::fpclassify(x: f); }
126#endif
127}
128
129Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() noexcept
130{
131 Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_infinity,
132 "platform has no definition for infinity for type double");
133 return std::numeric_limits<double>::infinity();
134}
135
136#if QT_CONFIG(signaling_nan)
137Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() noexcept
138{
139 Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_signaling_NaN,
140 "platform has no definition for signaling NaN for type double");
141 return std::numeric_limits<double>::signaling_NaN();
142}
143#endif
144
145// Quiet NaN
146Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() noexcept
147{
148 Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_quiet_NaN,
149 "platform has no definition for quiet NaN for type double");
150 return std::numeric_limits<double>::quiet_NaN();
151}
152
153Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(double d)
154{
155 return qnumeric_std_wrapper::isinf(d);
156}
157
158Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(double d)
159{
160 return qnumeric_std_wrapper::isnan(d);
161}
162
163Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(double d)
164{
165 return qnumeric_std_wrapper::isfinite(d);
166}
167
168Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(double d)
169{
170 return qnumeric_std_wrapper::fpclassify(d);
171}
172
173Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f)
174{
175 return qnumeric_std_wrapper::isinf(f);
176}
177
178Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(float f)
179{
180 return qnumeric_std_wrapper::isnan(f);
181}
182
183Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
184{
185 return qnumeric_std_wrapper::isfinite(f);
186}
187
188Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(float f)
189{
190 return qnumeric_std_wrapper::fpclassify(f);
191}
192
193#ifndef Q_CLANG_QDOC
194namespace {
195/*!
196 Returns true if the double \a v can be converted to type \c T, false if
197 it's out of range. If the conversion is successful, the converted value is
198 stored in \a value; if it was not successful, \a value will contain the
199 minimum or maximum of T, depending on the sign of \a d. If \c T is
200 unsigned, then \a value contains the absolute value of \a v.
201
202 This function works for v containing infinities, but not NaN. It's the
203 caller's responsibility to exclude that possibility before calling it.
204*/
205template <typename T> static inline bool convertDoubleTo(double v, T *value)
206{
207 Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
208
209 // The [conv.fpint] (7.10 Floating-integral conversions) section of the C++
210 // standard says only exact conversions are guaranteed. Converting
211 // integrals to floating-point with loss of precision has implementation-
212 // defined behavior whether the next higher or next lower is returned;
213 // converting FP to integral is UB if it can't be represented.
214 //
215 // That means we can't write UINT64_MAX+1. Writing ldexp(1, 64) would be
216 // correct, but Clang, ICC and MSVC don't realize that it's a constant and
217 // the math call stays in the compiled code.
218
219 double supremum;
220 if (std::numeric_limits<T>::is_signed) {
221 supremum = -1.0 * std::numeric_limits<T>::min(); // -1 * (-2^63) = 2^63, exact (for T = qint64)
222 *value = std::numeric_limits<T>::min();
223 if (v < std::numeric_limits<T>::min())
224 return false;
225 } else {
226 using ST = typename std::make_signed<T>::type;
227 supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
228 v = fabs(x: v);
229 }
230
231 *value = std::numeric_limits<T>::max();
232 if (v >= supremum)
233 return false;
234
235 // Now we can convert, these two conversions cannot be UB
236 *value = T(v);
237
238QT_WARNING_PUSH
239QT_WARNING_DISABLE_GCC("-Wfloat-equal")
240QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
241
242 return *value == v;
243
244QT_WARNING_POP
245}
246
247// Overflow math.
248// This provides efficient implementations for int, unsigned, qsizetype and
249// size_t. Implementations for 8- and 16-bit types will work but may not be as
250// efficient. Implementations for 64-bit may be missing on 32-bit platforms.
251
252#if ((defined(Q_CC_INTEL) ? (Q_CC_INTEL >= 1800 && !defined(Q_OS_WIN)) : defined(Q_CC_GNU)) \
253 && Q_CC_GNU >= 500) || __has_builtin(__builtin_add_overflow)
254// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows
255
256template <typename T> inline
257typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
258add_overflow(T v1, T v2, T *r)
259{ return __builtin_add_overflow(v1, v2, r); }
260
261template <typename T> inline
262typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
263sub_overflow(T v1, T v2, T *r)
264{ return __builtin_sub_overflow(v1, v2, r); }
265
266template <typename T> inline
267typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
268mul_overflow(T v1, T v2, T *r)
269{ return __builtin_mul_overflow(v1, v2, r); }
270
271#else
272// Generic implementations
273
274template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
275add_overflow(T v1, T v2, T *r)
276{
277 // unsigned additions are well-defined
278 *r = v1 + v2;
279 return v1 > T(v1 + v2);
280}
281
282template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
283add_overflow(T v1, T v2, T *r)
284{
285 // Here's how we calculate the overflow:
286 // 1) unsigned addition is well-defined, so we can always execute it
287 // 2) conversion from unsigned back to signed is implementation-
288 // defined and in the implementations we use, it's a no-op.
289 // 3) signed integer overflow happens if the sign of the two input operands
290 // is the same but the sign of the result is different. In other words,
291 // the sign of the result must be the same as the sign of either
292 // operand.
293
294 using U = typename std::make_unsigned<T>::type;
295 *r = T(U(v1) + U(v2));
296
297 // If int is two's complement, assume all integer types are too.
298 if (std::is_same<int32_t, int>::value) {
299 // Two's complement equivalent (generates slightly shorter code):
300 // x ^ y is negative if x and y have different signs
301 // x & y is negative if x and y are negative
302 // (x ^ z) & (y ^ z) is negative if x and z have different signs
303 // AND y and z have different signs
304 return ((v1 ^ *r) & (v2 ^ *r)) < 0;
305 }
306
307 bool s1 = (v1 < 0);
308 bool s2 = (v2 < 0);
309 bool sr = (*r < 0);
310 return s1 != sr && s2 != sr;
311 // also: return s1 == s2 && s1 != sr;
312}
313
314template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
315sub_overflow(T v1, T v2, T *r)
316{
317 // unsigned subtractions are well-defined
318 *r = v1 - v2;
319 return v1 < v2;
320}
321
322template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
323sub_overflow(T v1, T v2, T *r)
324{
325 // See above for explanation. This is the same with some signs reversed.
326 // We can't use add_overflow(v1, -v2, r) because it would be UB if
327 // v2 == std::numeric_limits<T>::min().
328
329 using U = typename std::make_unsigned<T>::type;
330 *r = T(U(v1) - U(v2));
331
332 if (std::is_same<int32_t, int>::value)
333 return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
334
335 bool s1 = (v1 < 0);
336 bool s2 = !(v2 < 0);
337 bool sr = (*r < 0);
338 return s1 != sr && s2 != sr;
339 // also: return s1 == s2 && s1 != sr;
340}
341
342template <typename T> inline
343typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
344mul_overflow(T v1, T v2, T *r)
345{
346 // use the next biggest type
347 // Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
348 using LargerInt = QIntegerForSize<sizeof(T) * 2>;
349 using Larger = typename std::conditional<std::is_signed<T>::value,
350 typename LargerInt::Signed, typename LargerInt::Unsigned>::type;
351 Larger lr = Larger(v1) * Larger(v2);
352 *r = T(lr);
353 return lr > std::numeric_limits<T>::max() || lr < std::numeric_limits<T>::min();
354}
355
356# if defined(Q_INTRINSIC_MUL_OVERFLOW64)
357template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
358{
359 *r = v1 * v2;
360 return Q_UMULH(v1, v2);
361}
362template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r)
363{
364 // This is slightly more complex than the unsigned case above: the sign bit
365 // of 'low' must be replicated as the entire 'high', so the only valid
366 // values for 'high' are 0 and -1. Use unsigned multiply since it's the same
367 // as signed for the low bits and use a signed right shift to verify that
368 // 'high' is nothing but sign bits that match the sign of 'low'.
369
370 qint64 high = Q_SMULH(v1, v2);
371 *r = qint64(quint64(v1) * quint64(v2));
372 return (*r >> 63) != high;
373}
374
375# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
376template <> inline bool mul_overflow(uint64_t v1, uint64_t v2, uint64_t *r)
377{
378 return mul_overflow<quint64>(v1,v2,reinterpret_cast<quint64*>(r));
379}
380
381template <> inline bool mul_overflow(int64_t v1, int64_t v2, int64_t *r)
382{
383 return mul_overflow<qint64>(v1,v2,reinterpret_cast<qint64*>(r));
384}
385# endif // OS_INTEGRITY ARM64
386# endif // Q_INTRINSIC_MUL_OVERFLOW64
387
388# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
389// We can use intrinsics for the unsigned operations with MSVC
390template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
391{ return _addcarry_u32(0, v1, v2, r); }
392
393// 32-bit mul_overflow is fine with the generic code above
394
395template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r)
396{
397# if defined(Q_PROCESSOR_X86_64)
398 return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r));
399# else
400 uint low, high;
401 uchar carry = _addcarry_u32(0, unsigned(v1), unsigned(v2), &low);
402 carry = _addcarry_u32(carry, v1 >> 32, v2 >> 32, &high);
403 *r = (quint64(high) << 32) | low;
404 return carry;
405# endif // !x86-64
406}
407# endif // MSVC X86
408#endif // !GCC
409}
410#endif // Q_CLANG_QDOC
411
412QT_END_NAMESPACE
413
414#endif // QNUMERIC_P_H
415

source code of qtbase/src/corelib/global/qnumeric_p.h