Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qmath.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QMATH_H
0005 #define QMATH_H
0006 
0007 #if 0
0008 #pragma qt_class(QtMath)
0009 #endif
0010 
0011 #include <QtCore/qglobal.h>
0012 #include <QtCore/qalgorithms.h>
0013 
0014 #if __has_include(<bit>) && __cplusplus > 201703L
0015 #include <bit>
0016 #endif
0017 
0018 #ifndef _USE_MATH_DEFINES
0019 #  define _USE_MATH_DEFINES
0020 #  define undef_USE_MATH_DEFINES
0021 #endif
0022 
0023 #include <cmath>
0024 
0025 #ifdef undef_USE_MATH_DEFINES
0026 #  undef _USE_MATH_DEFINES
0027 #  undef undef_USE_MATH_DEFINES
0028 #endif
0029 
0030 QT_BEGIN_NAMESPACE
0031 
0032 #define QT_SINE_TABLE_SIZE 256
0033 
0034 extern Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE];
0035 
0036 template <typename T> int qCeil(T v)
0037 {
0038     using std::ceil;
0039     return int(ceil(v));
0040 }
0041 
0042 template <typename T> int qFloor(T v)
0043 {
0044     using std::floor;
0045     return int(floor(v));
0046 }
0047 
0048 template <typename T> auto qFabs(T v)
0049 {
0050     using std::fabs;
0051     return fabs(v);
0052 }
0053 
0054 template <typename T> auto qSin(T v)
0055 {
0056     using std::sin;
0057     return sin(v);
0058 }
0059 
0060 template <typename T> auto qCos(T v)
0061 {
0062     using std::cos;
0063     return cos(v);
0064 }
0065 
0066 template <typename T> auto qTan(T v)
0067 {
0068     using std::tan;
0069     return tan(v);
0070 }
0071 
0072 template <typename T> auto qAcos(T v)
0073 {
0074     using std::acos;
0075     return acos(v);
0076 }
0077 
0078 template <typename T> auto qAsin(T v)
0079 {
0080     using std::asin;
0081     return asin(v);
0082 }
0083 
0084 template <typename T> auto qAtan(T v)
0085 {
0086     using std::atan;
0087     return atan(v);
0088 }
0089 
0090 template <typename T1, typename T2> auto qAtan2(T1 y, T2 x)
0091 {
0092     using std::atan2;
0093     return atan2(y, x);
0094 }
0095 
0096 template <typename T> auto qSqrt(T v)
0097 {
0098     using std::sqrt;
0099     return sqrt(v);
0100 }
0101 
0102 namespace QtPrivate {
0103 template <typename R, typename F> // For qfloat16 to specialize
0104 struct QHypotType { using type = decltype(std::hypot(R(1), F(1))); };
0105 
0106 // Implements hypot() without limiting number of arguments:
0107 template <typename T>
0108 class QHypotHelper
0109 {
0110     T scale, total;
0111     template <typename F> friend class QHypotHelper;
0112     QHypotHelper(T first, T prior) : scale(first), total(prior) {}
0113 public:
0114     QHypotHelper(T first) : scale(qAbs(first)), total(1) {}
0115     T result() const
0116     { return qIsFinite(scale) ? scale > 0 ? scale * T(qSqrt(total)) : T(0) : scale; }
0117 
0118     template<typename F, typename ...Fs>
0119     auto add(F first, Fs... rest) const
0120     { return add(first).add(rest...); }
0121 
0122     template<typename F, typename R = typename QHypotType<T, F>::type>
0123     QHypotHelper<R> add(F next) const
0124     {
0125         if (qIsInf(scale) || (qIsNaN(scale) && !qIsInf(next)))
0126             return QHypotHelper<R>(scale, R(1));
0127         if (qIsNaN(next))
0128             return QHypotHelper<R>(next, R(1));
0129         const R val = qAbs(next);
0130         if (!(scale > 0) || qIsInf(next))
0131             return QHypotHelper<R>(val, R(1));
0132         if (!(val > 0))
0133             return QHypotHelper<R>(scale, total);
0134         if (val > scale) {
0135             const R ratio = scale / next;
0136             return QHypotHelper<R>(val, total * ratio * ratio + R(1));
0137         }
0138         const R ratio = next / scale;
0139         return QHypotHelper<R>(scale, total + ratio * ratio);
0140     }
0141 };
0142 } // QtPrivate
0143 
0144 template<typename F, typename ...Fs>
0145 auto qHypot(F first, Fs... rest)
0146 {
0147     return QtPrivate::QHypotHelper<F>(first).add(rest...).result();
0148 }
0149 
0150 // However, where possible, use the standard library implementations:
0151 template <typename Tx, typename Ty>
0152 auto qHypot(Tx x, Ty y)
0153 {
0154     // C99 has hypot(), hence C++11 has std::hypot()
0155     using std::hypot;
0156     return hypot(x, y);
0157 }
0158 
0159 #if defined(__cpp_lib_hypot) && __cpp_lib_hypot >= 201603L // Expected to be true
0160 template <typename Tx, typename Ty, typename Tz>
0161 auto qHypot(Tx x, Ty y, Tz z)
0162 {
0163     using std::hypot;
0164     return hypot(x, y, z);
0165 }
0166 #endif // else: no need to over-ride the arbitrarily-many-arg form
0167 
0168 template <typename T> auto qLn(T v)
0169 {
0170     using std::log;
0171     return log(v);
0172 }
0173 
0174 template <typename T> auto qExp(T v)
0175 {
0176     using std::exp;
0177     return exp(v);
0178 }
0179 
0180 template <typename T1, typename T2> auto qPow(T1 x, T2 y)
0181 {
0182     using std::pow;
0183     return pow(x, y);
0184 }
0185 
0186 // TODO: use template variables (e.g. Qt::pi<type>) for these once we have C++14 support:
0187 
0188 #ifndef M_E
0189 #define M_E (2.7182818284590452354)
0190 #endif
0191 
0192 #ifndef M_LOG2E
0193 #define M_LOG2E (1.4426950408889634074)
0194 #endif
0195 
0196 #ifndef M_LOG10E
0197 #define M_LOG10E (0.43429448190325182765)
0198 #endif
0199 
0200 #ifndef M_LN2
0201 #define M_LN2 (0.69314718055994530942)
0202 #endif
0203 
0204 #ifndef M_LN10
0205 #define M_LN10 (2.30258509299404568402)
0206 #endif
0207 
0208 #ifndef M_PI
0209 #define M_PI (3.14159265358979323846)
0210 #endif
0211 
0212 #ifndef M_PI_2
0213 #define M_PI_2 (1.57079632679489661923)
0214 #endif
0215 
0216 #ifndef M_PI_4
0217 #define M_PI_4 (0.78539816339744830962)
0218 #endif
0219 
0220 #ifndef M_1_PI
0221 #define M_1_PI (0.31830988618379067154)
0222 #endif
0223 
0224 #ifndef M_2_PI
0225 #define M_2_PI (0.63661977236758134308)
0226 #endif
0227 
0228 #ifndef M_2_SQRTPI
0229 #define M_2_SQRTPI (1.12837916709551257390)
0230 #endif
0231 
0232 #ifndef M_SQRT2
0233 #define M_SQRT2 (1.41421356237309504880)
0234 #endif
0235 
0236 #ifndef M_SQRT1_2
0237 #define M_SQRT1_2 (0.70710678118654752440)
0238 #endif
0239 
0240 inline qreal qFastSin(qreal x)
0241 {
0242     int si = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
0243     qreal d = x - si * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
0244     int ci = si + QT_SINE_TABLE_SIZE / 4;
0245     si &= QT_SINE_TABLE_SIZE - 1;
0246     ci &= QT_SINE_TABLE_SIZE - 1;
0247     return qt_sine_table[si] + (qt_sine_table[ci] - 0.5 * qt_sine_table[si] * d) * d;
0248 }
0249 
0250 inline qreal qFastCos(qreal x)
0251 {
0252     int ci = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
0253     qreal d = x - ci * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
0254     int si = ci + QT_SINE_TABLE_SIZE / 4;
0255     si &= QT_SINE_TABLE_SIZE - 1;
0256     ci &= QT_SINE_TABLE_SIZE - 1;
0257     return qt_sine_table[si] - (qt_sine_table[ci] + 0.5 * qt_sine_table[si] * d) * d;
0258 }
0259 
0260 constexpr inline float qDegreesToRadians(float degrees)
0261 {
0262     return degrees * float(M_PI / 180);
0263 }
0264 
0265 constexpr inline double qDegreesToRadians(double degrees)
0266 {
0267     return degrees * (M_PI / 180);
0268 }
0269 
0270 constexpr inline long double qDegreesToRadians(long double degrees)
0271 {
0272     return degrees * (M_PI / 180);
0273 }
0274 
0275 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
0276 constexpr inline double qDegreesToRadians(T degrees)
0277 {
0278     return qDegreesToRadians(static_cast<double>(degrees));
0279 }
0280 
0281 constexpr inline float qRadiansToDegrees(float radians)
0282 {
0283     return radians * float(180 / M_PI);
0284 }
0285 
0286 constexpr inline double qRadiansToDegrees(double radians)
0287 {
0288     return radians * (180 / M_PI);
0289 }
0290 
0291 constexpr inline long double qRadiansToDegrees(long double radians)
0292 {
0293     return radians * (180 / M_PI);
0294 }
0295 
0296 // A qRadiansToDegrees(Integral) overload isn't here; it's extremely
0297 // questionable that someone is manipulating quantities in radians
0298 // using integral datatypes...
0299 
0300 namespace QtPrivate {
0301 constexpr inline quint32 qConstexprNextPowerOfTwo(quint32 v)
0302 {
0303     v |= v >> 1;
0304     v |= v >> 2;
0305     v |= v >> 4;
0306     v |= v >> 8;
0307     v |= v >> 16;
0308     ++v;
0309     return v;
0310 }
0311 
0312 constexpr inline quint64 qConstexprNextPowerOfTwo(quint64 v)
0313 {
0314     v |= v >> 1;
0315     v |= v >> 2;
0316     v |= v >> 4;
0317     v |= v >> 8;
0318     v |= v >> 16;
0319     v |= v >> 32;
0320     ++v;
0321     return v;
0322 }
0323 
0324 constexpr inline quint32 qConstexprNextPowerOfTwo(qint32 v)
0325 {
0326     return qConstexprNextPowerOfTwo(quint32(v));
0327 }
0328 
0329 constexpr inline quint64 qConstexprNextPowerOfTwo(qint64 v)
0330 {
0331     return qConstexprNextPowerOfTwo(quint64(v));
0332 }
0333 } // namespace QtPrivate
0334 
0335 constexpr inline quint32 qNextPowerOfTwo(quint32 v)
0336 {
0337     Q_ASSERT(static_cast<qint32>(v) >= 0); // There is a next power of two
0338 #if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
0339     return std::bit_ceil(v + 1);
0340 #elif defined(QT_HAS_BUILTIN_CLZ)
0341     if (v == 0)
0342         return 1;
0343     return 2U << (31 ^ QAlgorithmsPrivate::qt_builtin_clz(v));
0344 #else
0345     return QtPrivate::qConstexprNextPowerOfTwo(v);
0346 #endif
0347 }
0348 
0349 constexpr inline quint64 qNextPowerOfTwo(quint64 v)
0350 {
0351     Q_ASSERT(static_cast<qint64>(v) >= 0); // There is a next power of two
0352 #if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
0353     return std::bit_ceil(v + 1);
0354 #elif defined(QT_HAS_BUILTIN_CLZLL)
0355     if (v == 0)
0356         return 1;
0357     return Q_UINT64_C(2) << (63 ^ QAlgorithmsPrivate::qt_builtin_clzll(v));
0358 #else
0359     return QtPrivate::qConstexprNextPowerOfTwo(v);
0360 #endif
0361 }
0362 
0363 constexpr inline quint32 qNextPowerOfTwo(qint32 v)
0364 {
0365     return qNextPowerOfTwo(quint32(v));
0366 }
0367 
0368 constexpr inline quint64 qNextPowerOfTwo(qint64 v)
0369 {
0370     return qNextPowerOfTwo(quint64(v));
0371 }
0372 
0373 constexpr inline unsigned long qNextPowerOfTwo(unsigned long v)
0374 {
0375     return qNextPowerOfTwo(QIntegerForSizeof<long>::Unsigned(v));
0376 }
0377 
0378 constexpr inline unsigned long qNextPowerOfTwo(long v)
0379 {
0380     return qNextPowerOfTwo(QIntegerForSizeof<long>::Unsigned(v));
0381 }
0382 
0383 QT_END_NAMESPACE
0384 
0385 #endif // QMATH_H