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
82 QT_BEGIN_NAMESPACE
83 namespace 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.
math_h_isnan(double d)85 Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
math_h_isinf(double d)86 Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
math_h_isfinite(double d)87 Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
math_h_fpclassify(double d)88 Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(double d) { using namespace std; return fpclassify(d); }
math_h_isnan(float f)89 Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
math_h_isinf(float f)90 Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
math_h_isfinite(float f)91 Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
math_h_fpclassify(float f)92 Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(float f) { using namespace std; return fpclassify(f); }
93 }
94 QT_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 
104 QT_BEGIN_NAMESPACE
105 
106 namespace qnumeric_std_wrapper {
107 #if defined(QT_MATH_H_DEFINES_MACROS)
108 #  undef QT_MATH_H_DEFINES_MACROS
isnan(double d)109 Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); }
isinf(double d)110 Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); }
isfinite(double d)111 Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); }
fpclassify(double d)112 Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return math_h_fpclassify(d); }
isnan(float f)113 Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); }
isinf(float f)114 Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); }
isfinite(float f)115 Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); }
fpclassify(float f)116 Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return math_h_fpclassify(f); }
117 #else
118 Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(d); }
119 Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(d); }
120 Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(d); }
121 Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return std::fpclassify(d); }
122 Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(f); }
123 Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(f); }
124 Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(f); }
125 Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return std::fpclassify(f); }
126 #endif
127 }
128 
qt_inf()129 Q_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)
qt_snan()137 Q_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
qt_qnan()146 Q_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 
qt_is_inf(double d)153 Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(double d)
154 {
155     return qnumeric_std_wrapper::isinf(d);
156 }
157 
qt_is_nan(double d)158 Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(double d)
159 {
160     return qnumeric_std_wrapper::isnan(d);
161 }
162 
qt_is_finite(double d)163 Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(double d)
164 {
165     return qnumeric_std_wrapper::isfinite(d);
166 }
167 
qt_fpclassify(double d)168 Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(double d)
169 {
170     return qnumeric_std_wrapper::fpclassify(d);
171 }
172 
qt_is_inf(float f)173 Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f)
174 {
175     return qnumeric_std_wrapper::isinf(f);
176 }
177 
qt_is_nan(float f)178 Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(float f)
179 {
180     return qnumeric_std_wrapper::isnan(f);
181 }
182 
qt_is_finite(float f)183 Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
184 {
185     return qnumeric_std_wrapper::isfinite(f);
186 }
187 
qt_fpclassify(float f)188 Q_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
194 namespace {
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 */
convertDoubleTo(double v,T * value)205 template <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(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 
238 QT_WARNING_PUSH
239 QT_WARNING_DISABLE_GCC("-Wfloat-equal")
240 QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
241 
242     return *value == v;
243 
244 QT_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 
256 template <typename T> inline
257 typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
add_overflow(T v1,T v2,T * r)258 add_overflow(T v1, T v2, T *r)
259 { return __builtin_add_overflow(v1, v2, r); }
260 
261 template <typename T> inline
262 typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
sub_overflow(T v1,T v2,T * r)263 sub_overflow(T v1, T v2, T *r)
264 { return __builtin_sub_overflow(v1, v2, r); }
265 
266 template <typename T> inline
267 typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
mul_overflow(T v1,T v2,T * r)268 mul_overflow(T v1, T v2, T *r)
269 { return __builtin_mul_overflow(v1, v2, r); }
270 
271 #else
272 // Generic implementations
273 
274 template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
add_overflow(T v1,T v2,T * r)275 add_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 
282 template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
add_overflow(T v1,T v2,T * r)283 add_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 
314 template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
sub_overflow(T v1,T v2,T * r)315 sub_overflow(T v1, T v2, T *r)
316 {
317     // unsigned subtractions are well-defined
318     *r = v1 - v2;
319     return v1 < v2;
320 }
321 
322 template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
sub_overflow(T v1,T v2,T * r)323 sub_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 
342 template <typename T> inline
343 typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
mul_overflow(T v1,T v2,T * r)344 mul_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)
mul_overflow(quint64 v1,quint64 v2,quint64 * r)357 template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
358 {
359     *r = v1 * v2;
360     return Q_UMULH(v1, v2);
361 }
mul_overflow(qint64 v1,qint64 v2,qint64 * r)362 template <> 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)
mul_overflow(uint64_t v1,uint64_t v2,uint64_t * r)376 template <> 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 
mul_overflow(int64_t v1,int64_t v2,int64_t * r)381 template <> 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
add_overflow(unsigned v1,unsigned v2,unsigned * r)390 template <> 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 
add_overflow(quint64 v1,quint64 v2,quint64 * r)395 template <> 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 
412 QT_END_NAMESPACE
413 
414 #endif // QNUMERIC_P_H
415