2011-04-27 10:05:43 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-15 07:08:27 +00:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
2017-12-01 04:37:57 +00:00
|
|
|
** Copyright (C) 2018 Intel Corporation.
|
2016-01-15 07:08:27 +00:00
|
|
|
** Contact: https://www.qt.io/licensing/
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** This file is part of the QtCore module of the Qt Toolkit.
|
|
|
|
**
|
2016-01-15 07:08:27 +00:00
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2012-09-19 12:28:29 +00:00
|
|
|
** 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
|
2015-01-28 08:44:43 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
2016-01-15 07:08:27 +00:00
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-09-19 12:28:29 +00:00
|
|
|
**
|
2011-04-27 10:05:43 +00:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-09-19 12:28:29 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2016-01-15 07:08:27 +00:00
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
2016-01-15 07:08:27 +00:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
|
|
** 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-2.0.html and
|
|
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef QNUMERIC_P_H
|
|
|
|
#define QNUMERIC_P_H
|
|
|
|
|
|
|
|
//
|
|
|
|
// W A R N I N G
|
|
|
|
// -------------
|
|
|
|
//
|
|
|
|
// This file is not part of the Qt API. It exists purely as an
|
|
|
|
// implementation detail. This header file may change from version to
|
|
|
|
// version without notice, or even be removed.
|
|
|
|
//
|
|
|
|
// We mean it.
|
|
|
|
//
|
|
|
|
|
2016-06-15 12:04:53 +00:00
|
|
|
#include "QtCore/private/qglobal_p.h"
|
2015-08-10 11:15:24 +00:00
|
|
|
#include <cmath>
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
#include <limits>
|
|
|
|
|
2016-03-23 09:25:46 +00:00
|
|
|
#if defined(Q_CC_MSVC)
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
# include <intrin.h>
|
2018-11-15 00:19:43 +00:00
|
|
|
# include <float.h>
|
|
|
|
# if defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_ARM_64)
|
|
|
|
# define Q_INTRINSIC_MUL_OVERFLOW64
|
|
|
|
# define Q_UMULH(v1, v2) __umulh(v1, v2);
|
|
|
|
# define Q_SMULH(v1, v2) __mulh(v1, v2);
|
|
|
|
# pragma intrinsic(__umulh)
|
|
|
|
# pragma intrinsic(__mulh)
|
|
|
|
# endif
|
2015-08-10 11:15:24 +00:00
|
|
|
#endif
|
|
|
|
|
2018-10-24 12:57:44 +00:00
|
|
|
# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
|
|
|
|
#include <arm64_ghs.h>
|
2018-11-15 00:19:43 +00:00
|
|
|
# define Q_INTRINSIC_MUL_OVERFLOW64
|
|
|
|
# define Q_UMULH(v1, v2) __MULUH64(v1, v2);
|
|
|
|
# define Q_SMULH(v1, v2) __MULSH64(v1, v2);
|
2018-10-24 12:57:44 +00:00
|
|
|
#endif
|
|
|
|
|
2016-12-01 15:46:40 +00:00
|
|
|
#if !defined(Q_CC_MSVC) && (defined(Q_OS_QNX) || defined(Q_CC_INTEL))
|
2016-07-23 02:56:41 +00:00
|
|
|
# include <math.h>
|
2016-11-30 23:29:45 +00:00
|
|
|
# ifdef isnan
|
|
|
|
# define QT_MATH_H_DEFINES_MACROS
|
2015-08-10 11:15:24 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
namespace qnumeric_std_wrapper {
|
|
|
|
// the 'using namespace std' below is cases where the stdlib already put the math.h functions in the std namespace and undefined the macros.
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
|
2015-08-10 11:15:24 +00:00
|
|
|
}
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
// These macros from math.h conflict with the real functions in the std namespace.
|
2016-11-30 23:29:45 +00:00
|
|
|
# undef signbit
|
|
|
|
# undef isnan
|
|
|
|
# undef isinf
|
|
|
|
# undef isfinite
|
|
|
|
# endif // defined(isnan)
|
2015-08-10 11:15:24 +00:00
|
|
|
#endif
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2015-08-10 11:15:24 +00:00
|
|
|
namespace qnumeric_std_wrapper {
|
2016-12-01 15:46:40 +00:00
|
|
|
#if defined(QT_MATH_H_DEFINES_MACROS)
|
2016-07-23 02:56:41 +00:00
|
|
|
# undef QT_MATH_H_DEFINES_MACROS
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); }
|
2015-08-10 11:15:24 +00:00
|
|
|
#else
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(d); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(f); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(f); }
|
|
|
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(f); }
|
2015-08-10 11:15:24 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() Q_DECL_NOEXCEPT
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:22:38 +00:00
|
|
|
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_infinity,
|
|
|
|
"platform has no definition for infinity for type double");
|
|
|
|
return std::numeric_limits<double>::infinity();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2015-08-10 11:22:38 +00:00
|
|
|
// Signaling NaN
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() Q_DECL_NOEXCEPT
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:22:38 +00:00
|
|
|
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_signaling_NaN,
|
|
|
|
"platform has no definition for signaling NaN for type double");
|
|
|
|
return std::numeric_limits<double>::signaling_NaN();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2015-08-10 11:22:38 +00:00
|
|
|
// Quiet NaN
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() Q_DECL_NOEXCEPT
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:22:38 +00:00
|
|
|
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_quiet_NaN,
|
|
|
|
"platform has no definition for quiet NaN for type double");
|
|
|
|
return std::numeric_limits<double>::quiet_NaN();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(double d)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:15:24 +00:00
|
|
|
return qnumeric_std_wrapper::isinf(d);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(double d)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:15:24 +00:00
|
|
|
return qnumeric_std_wrapper::isnan(d);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(double d)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:15:24 +00:00
|
|
|
return qnumeric_std_wrapper::isfinite(d);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:15:24 +00:00
|
|
|
return qnumeric_std_wrapper::isinf(f);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(float f)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:15:24 +00:00
|
|
|
return qnumeric_std_wrapper::isnan(f);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-04-03 23:41:34 +00:00
|
|
|
Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2015-08-10 11:15:24 +00:00
|
|
|
return qnumeric_std_wrapper::isfinite(f);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-01-16 10:16:13 +00:00
|
|
|
#ifndef Q_CLANG_QDOC
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
namespace {
|
2018-07-14 23:42:08 +00:00
|
|
|
/*!
|
|
|
|
Returns true if the double \a v can be converted to type \c T, false if
|
|
|
|
it's out of range. If the conversion is successful, the converted value is
|
|
|
|
stored in \a value; if it was not successful, \a value will contain the
|
|
|
|
minimum or maximum of T, depending on the sign of \a d. If \c T is
|
|
|
|
unsigned, then \a value contains the absolute value of \a v.
|
|
|
|
|
|
|
|
This function works for v containing infinities, but not NaN. It's the
|
|
|
|
caller's responsibility to exclude that possibility before calling it.
|
|
|
|
*/
|
|
|
|
template <typename T> static inline bool convertDoubleTo(double v, T *value)
|
|
|
|
{
|
|
|
|
Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
|
|
|
|
|
|
|
// The [conv.fpint] (7.10 Floating-integral conversions) section of the C++
|
|
|
|
// standard says only exact conversions are guaranteed. Converting
|
|
|
|
// integrals to floating-point with loss of precision has implementation-
|
|
|
|
// defined behavior whether the next higher or next lower is returned;
|
|
|
|
// converting FP to integral is UB if it can't be represented.
|
|
|
|
//
|
|
|
|
// That means we can't write UINT64_MAX+1. Writing ldexp(1, 64) would be
|
|
|
|
// correct, but Clang, ICC and MSVC don't realize that it's a constant and
|
|
|
|
// the math call stays in the compiled code.
|
|
|
|
|
|
|
|
double supremum;
|
|
|
|
if (std::numeric_limits<T>::is_signed) {
|
|
|
|
supremum = -1.0 * std::numeric_limits<T>::min(); // -1 * (-2^63) = 2^63, exact (for T = qint64)
|
|
|
|
*value = std::numeric_limits<T>::min();
|
|
|
|
if (v < std::numeric_limits<T>::min())
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
using ST = typename std::make_signed<T>::type;
|
|
|
|
supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
|
|
|
|
v = fabs(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
*value = std::numeric_limits<T>::max();
|
|
|
|
if (v >= supremum)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Now we can convert, these two conversions cannot be UB
|
|
|
|
*value = T(v);
|
|
|
|
|
|
|
|
QT_WARNING_PUSH
|
|
|
|
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
|
|
|
|
QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
|
|
|
|
|
|
|
|
return *value == v;
|
|
|
|
|
|
|
|
QT_WARNING_POP
|
|
|
|
}
|
|
|
|
|
2017-12-01 04:37:57 +00:00
|
|
|
// Overflow math.
|
|
|
|
// This provides efficient implementations for int, unsigned, qsizetype and
|
|
|
|
// size_t. Implementations for 8- and 16-bit types will work but may not be as
|
|
|
|
// efficient. Implementations for 64-bit may be missing on 32-bit platforms.
|
|
|
|
|
2018-12-14 20:49:18 +00:00
|
|
|
#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || (defined(Q_CC_INTEL) && !defined(Q_OS_WIN))) || QT_HAS_BUILTIN(__builtin_add_overflow)
|
2017-12-01 04:37:57 +00:00
|
|
|
// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows
|
|
|
|
|
|
|
|
template <typename T> inline
|
|
|
|
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
|
|
|
add_overflow(T v1, T v2, T *r)
|
|
|
|
{ return __builtin_add_overflow(v1, v2, r); }
|
|
|
|
|
|
|
|
template <typename T> inline
|
|
|
|
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
|
|
|
sub_overflow(T v1, T v2, T *r)
|
|
|
|
{ return __builtin_sub_overflow(v1, v2, r); }
|
|
|
|
|
|
|
|
template <typename T> inline
|
|
|
|
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
|
|
|
mul_overflow(T v1, T v2, T *r)
|
|
|
|
{ return __builtin_mul_overflow(v1, v2, r); }
|
|
|
|
|
|
|
|
#else
|
|
|
|
// Generic implementations
|
|
|
|
|
2017-01-20 12:58:10 +00:00
|
|
|
template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
add_overflow(T v1, T v2, T *r)
|
|
|
|
{
|
|
|
|
// unsigned additions are well-defined
|
|
|
|
*r = v1 + v2;
|
|
|
|
return v1 > T(v1 + v2);
|
|
|
|
}
|
|
|
|
|
2017-12-01 04:37:57 +00:00
|
|
|
template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
|
|
|
|
add_overflow(T v1, T v2, T *r)
|
|
|
|
{
|
|
|
|
// Here's how we calculate the overflow:
|
|
|
|
// 1) unsigned addition is well-defined, so we can always execute it
|
|
|
|
// 2) conversion from unsigned back to signed is implementation-
|
|
|
|
// defined and in the implementations we use, it's a no-op.
|
|
|
|
// 3) signed integer overflow happens if the sign of the two input operands
|
|
|
|
// is the same but the sign of the result is different. In other words,
|
|
|
|
// the sign of the result must be the same as the sign of either
|
|
|
|
// operand.
|
|
|
|
|
|
|
|
using U = typename std::make_unsigned<T>::type;
|
|
|
|
*r = T(U(v1) + U(v2));
|
|
|
|
|
|
|
|
// If int is two's complement, assume all integer types are too.
|
|
|
|
if (std::is_same<int32_t, int>::value) {
|
|
|
|
// Two's complement equivalent (generates slightly shorter code):
|
|
|
|
// x ^ y is negative if x and y have different signs
|
|
|
|
// x & y is negative if x and y are negative
|
|
|
|
// (x ^ z) & (y ^ z) is negative if x and z have different signs
|
|
|
|
// AND y and z have different signs
|
|
|
|
return ((v1 ^ *r) & (v2 ^ *r)) < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool s1 = (v1 < 0);
|
|
|
|
bool s2 = (v2 < 0);
|
|
|
|
bool sr = (*r < 0);
|
|
|
|
return s1 != sr && s2 != sr;
|
|
|
|
// also: return s1 == s2 && s1 != sr;
|
|
|
|
}
|
|
|
|
|
2017-01-20 12:58:10 +00:00
|
|
|
template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
|
2017-12-01 04:37:57 +00:00
|
|
|
sub_overflow(T v1, T v2, T *r)
|
|
|
|
{
|
|
|
|
// unsigned subtractions are well-defined
|
|
|
|
*r = v1 - v2;
|
|
|
|
return v1 < v2;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
|
|
|
|
sub_overflow(T v1, T v2, T *r)
|
|
|
|
{
|
|
|
|
// See above for explanation. This is the same with some signs reversed.
|
|
|
|
// We can't use add_overflow(v1, -v2, r) because it would be UB if
|
|
|
|
// v2 == std::numeric_limits<T>::min().
|
|
|
|
|
|
|
|
using U = typename std::make_unsigned<T>::type;
|
|
|
|
*r = T(U(v1) - U(v2));
|
|
|
|
|
|
|
|
if (std::is_same<int32_t, int>::value)
|
|
|
|
return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
|
|
|
|
|
|
|
|
bool s1 = (v1 < 0);
|
|
|
|
bool s2 = !(v2 < 0);
|
|
|
|
bool sr = (*r < 0);
|
|
|
|
return s1 != sr && s2 != sr;
|
|
|
|
// also: return s1 == s2 && s1 != sr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T> inline
|
|
|
|
typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
mul_overflow(T v1, T v2, T *r)
|
|
|
|
{
|
|
|
|
// use the next biggest type
|
|
|
|
// Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
|
2017-12-01 04:37:57 +00:00
|
|
|
using LargerInt = QIntegerForSize<sizeof(T) * 2>;
|
|
|
|
using Larger = typename std::conditional<std::is_signed<T>::value,
|
|
|
|
typename LargerInt::Signed, typename LargerInt::Unsigned>::type;
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
Larger lr = Larger(v1) * Larger(v2);
|
|
|
|
*r = T(lr);
|
2017-12-01 04:37:57 +00:00
|
|
|
return lr > std::numeric_limits<T>::max() || lr < std::numeric_limits<T>::min();
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
}
|
|
|
|
|
2018-11-15 00:19:43 +00:00
|
|
|
# if defined(Q_INTRINSIC_MUL_OVERFLOW64)
|
2018-10-24 12:57:44 +00:00
|
|
|
template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
|
|
|
|
{
|
|
|
|
*r = v1 * v2;
|
2018-11-15 00:19:43 +00:00
|
|
|
return Q_UMULH(v1, v2);
|
2018-10-24 12:57:44 +00:00
|
|
|
}
|
|
|
|
template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r)
|
|
|
|
{
|
2018-11-15 00:19:43 +00:00
|
|
|
// This is slightly more complex than the unsigned case above: the sign bit
|
|
|
|
// of 'low' must be replicated as the entire 'high', so the only valid
|
|
|
|
// values for 'high' are 0 and -1. Use unsigned multiply since it's the same
|
|
|
|
// as signed for the low bits and use a signed right shift to verify that
|
|
|
|
// 'high' is nothing but sign bits that match the sign of 'low'.
|
|
|
|
|
2018-12-11 02:55:09 +00:00
|
|
|
qint64 high = Q_SMULH(v1, v2);
|
2018-11-15 00:19:43 +00:00
|
|
|
*r = qint64(quint64(v1) * quint64(v2));
|
|
|
|
return (*r >> 63) != high;
|
2018-10-24 12:57:44 +00:00
|
|
|
}
|
|
|
|
|
2018-11-15 00:19:43 +00:00
|
|
|
# if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
|
2018-10-24 12:57:44 +00:00
|
|
|
template <> inline bool mul_overflow(uint64_t v1, uint64_t v2, uint64_t *r)
|
|
|
|
{
|
|
|
|
return mul_overflow<quint64>(v1,v2,reinterpret_cast<quint64*>(r));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <> inline bool mul_overflow(int64_t v1, int64_t v2, int64_t *r)
|
|
|
|
{
|
|
|
|
return mul_overflow<qint64>(v1,v2,reinterpret_cast<qint64*>(r));
|
|
|
|
}
|
2018-11-15 00:19:43 +00:00
|
|
|
# endif // OS_INTEGRITY ARM64
|
|
|
|
# endif // Q_INTRINSIC_MUL_OVERFLOW64
|
2018-10-24 12:57:44 +00:00
|
|
|
|
2017-12-01 04:37:57 +00:00
|
|
|
# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
|
|
|
|
// We can use intrinsics for the unsigned operations with MSVC
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
|
2017-12-01 04:37:57 +00:00
|
|
|
{ return _addcarry_u32(0, v1, v2, r); }
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
|
2017-12-01 04:37:57 +00:00
|
|
|
// 32-bit mul_overflow is fine with the generic code above
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
|
|
|
|
template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r)
|
MSVC x86: implement add_overflow for quint64
There's no 64-bit ADD instruction, so we make do with ADD+ADC. This is
what Clang generates. ICC uses the two as well, but then performs some
subtractions to find out if it overflowed. GCC for some inexplicable
reason attempts to use SSE2 if that's enabled, otherwise it performs the
subtractions like ICC.
Alternative implementation which generates better code, but violates
strict aliasing:
uint *low = reinterpret_cast<uint *>(r);
uint *high = low + 1;
return _addcarry_u32(_addcarry_u32(0, unsigned(v1), unsigned(v2), low),
v1 >> 32, v2 >> 32, high);
Manual testing shows this works. tst_qnumeric passes in debug mode. MSVC
2017 15.9 still miscompiles in release mode (reported to MS as [1]).
[1] https://developercommunity.visualstudio.com/content/problem/409039/-addcarry-u32-wrong-results-with-constant-inputs.html
Change-Id: I61ce366d57bc46c89db5fffd15704d53ebd4af3c
Reviewed-by: Thomas Miller <thomaslmiller91@gmail.com>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
2018-12-14 20:34:55 +00:00
|
|
|
{
|
|
|
|
# if defined(Q_PROCESSOR_X86_64)
|
|
|
|
return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r));
|
|
|
|
# else
|
|
|
|
uint low, high;
|
|
|
|
uchar carry = _addcarry_u32(0, unsigned(v1), unsigned(v2), &low);
|
|
|
|
carry = _addcarry_u32(carry, v1 >> 32, v2 >> 32, &high);
|
|
|
|
*r = (quint64(high) << 32) | low;
|
|
|
|
return carry;
|
|
|
|
# endif // !x86-64
|
|
|
|
}
|
2018-11-15 00:19:43 +00:00
|
|
|
# endif // MSVC X86
|
2017-12-01 04:37:57 +00:00
|
|
|
#endif // !GCC
|
2015-10-29 11:39:58 +00:00
|
|
|
}
|
2017-01-16 10:16:13 +00:00
|
|
|
#endif // Q_CLANG_QDOC
|
Add code to perform overflow-checking additions and multiplication
Most processors have carry flags which they set on addition overflow, so
it's a good idea to access them whenever possible. Most of them also
have widening multiply instructions that can be used to detect overflow
of the non-widening version.
Tested to compile on:
Architecture Compiler
x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta
x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6*
IA-64 LP64 GCC 4.8
ARMv7-A GCC 4.9, Clang 3.6*
AArch64 Clang 3.6*
MIPS GCC 4.9, Clang 3.6*
MIPS64 GCC 4.9, Clang 3.6*
PowerPC GCC 4.9, Clang 3.6*
PowerPC 64 GCC 4.9, Clang 3.6*
SPARC Clang 3.6*
SPARCv9 Clang 3.6*
[*] supports the intrinsics
If the compiler does not offer a way to detect an overflow, we do it by
hand. For unsigned additions, that's easy, since the C++ language
specifies the behavior of the overflow. That's also the reason why this
code is implemented only for unsigned integers.
For the multiplication, if the compiler does not support widening
multiplications, we do it with a division instead. This is necessary for
GCC < 4.5 and compilers not compatible with GCC or MSVC.
Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-10 00:09:18 +00:00
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
|
|
|
#endif // QNUMERIC_P_H
|