1/****************************************************************************
2**
3** Copyright (C) 2021 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QMATH_H
41#define QMATH_H
42
43#if 0
44#pragma qt_class(QtMath)
45#endif
46
47#include <QtCore/qglobal.h>
48#include <QtCore/qalgorithms.h>
49
50#if __has_include(<bit>) && __cplusplus > 201703L
51#include <bit>
52#endif
53
54#ifndef _USE_MATH_DEFINES
55# define _USE_MATH_DEFINES
56# define undef_USE_MATH_DEFINES
57#endif
58
59#include <cmath>
60
61#ifdef undef_USE_MATH_DEFINES
62# undef _USE_MATH_DEFINES
63# undef undef_USE_MATH_DEFINES
64#endif
65
66QT_BEGIN_NAMESPACE
67
68#define QT_SINE_TABLE_SIZE 256
69
70extern Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE];
71
72template <typename T> int qCeil(T v)
73{
74 using std::ceil;
75 return int(ceil(v));
76}
77
78template <typename T> int qFloor(T v)
79{
80 using std::floor;
81 return int(floor(v));
82}
83
84template <typename T> auto qFabs(T v)
85{
86 using std::fabs;
87 return fabs(v);
88}
89
90template <typename T> auto qSin(T v)
91{
92 using std::sin;
93 return sin(v);
94}
95
96template <typename T> auto qCos(T v)
97{
98 using std::cos;
99 return cos(v);
100}
101
102template <typename T> auto qTan(T v)
103{
104 using std::tan;
105 return tan(v);
106}
107
108template <typename T> auto qAcos(T v)
109{
110 using std::acos;
111 return acos(v);
112}
113
114template <typename T> auto qAsin(T v)
115{
116 using std::asin;
117 return asin(v);
118}
119
120template <typename T> auto qAtan(T v)
121{
122 using std::atan;
123 return atan(v);
124}
125
126template <typename T1, typename T2> auto qAtan2(T1 y, T2 x)
127{
128 using std::atan2;
129 return atan2(y, x);
130}
131
132template <typename T> auto qSqrt(T v)
133{
134 using std::sqrt;
135 return sqrt(v);
136}
137
138namespace QtPrivate {
139template <typename R, typename F> // For qfloat16 to specialize
140struct QHypotType { using type = decltype(std::hypot(R(1), F(1))); };
141
142// Implements hypot() without limiting number of arguments:
143template <typename T>
144class QHypotHelper
145{
146 T scale, total;
147 template <typename F> friend class QHypotHelper;
148 QHypotHelper(T first, T prior) : scale(first), total(prior) {}
149public:
150 QHypotHelper(T first) : scale(qAbs(first)), total(1) {}
151 T result() const
152 { return qIsFinite(scale) ? scale > 0 ? scale * T(std::sqrt(total)) : T(0) : scale; }
153
154 template<typename F, typename ...Fs>
155 auto add(F first, Fs... rest) const
156 { return add(first).add(rest...); }
157
158 template<typename F, typename R = typename QHypotType<T, F>::type>
159 QHypotHelper<R> add(F next) const
160 {
161 if (qIsInf(scale) || (qIsNaN(scale) && !qIsInf(next)))
162 return QHypotHelper<R>(scale, R(1));
163 if (qIsNaN(next))
164 return QHypotHelper<R>(next, R(1));
165 const R val = qAbs(next);
166 if (!(scale > 0) || qIsInf(next))
167 return QHypotHelper<R>(val, R(1));
168 if (!(val > 0))
169 return QHypotHelper<R>(scale, total);
170 if (val > scale) {
171 const R ratio = scale / next;
172 return QHypotHelper<R>(val, total * ratio * ratio + 1);
173 }
174 const R ratio = next / scale;
175 return QHypotHelper<R>(scale, total + ratio * ratio);
176 }
177};
178} // QtPrivate
179
180template<typename F, typename ...Fs>
181auto qHypot(F first, Fs... rest)
182{
183 return QtPrivate::QHypotHelper<F>(first).add(rest...).result();
184}
185
186// However, where possible, use the standard library implementations:
187template <typename Tx, typename Ty>
188auto qHypot(Tx x, Ty y)
189{
190 // C99 has hypot(), hence C++11 has std::hypot()
191 using std::hypot;
192 return hypot(x, y);
193}
194
195#if __cpp_lib_hypot >= 201603L // Expected to be true
196template <typename Tx, typename Ty, typename Tz>
197auto qHypot(Tx x, Ty y, Tz z)
198{
199 using std::hypot;
200 return hypot(x, y, z);
201}
202#endif // else: no need to over-ride the arbitrarily-many-arg form
203
204template <typename T> auto qLn(T v)
205{
206 using std::log;
207 return log(v);
208}
209
210template <typename T> auto qExp(T v)
211{
212 using std::exp;
213 return exp(v);
214}
215
216template <typename T1, typename T2> auto qPow(T1 x, T2 y)
217{
218 using std::pow;
219 return pow(x, y);
220}
221
222// TODO: use template variables (e.g. Qt::pi<type>) for these once we have C++14 support:
223
224#ifndef M_E
225#define M_E (2.7182818284590452354)
226#endif
227
228#ifndef M_LOG2E
229#define M_LOG2E (1.4426950408889634074)
230#endif
231
232#ifndef M_LOG10E
233#define M_LOG10E (0.43429448190325182765)
234#endif
235
236#ifndef M_LN2
237#define M_LN2 (0.69314718055994530942)
238#endif
239
240#ifndef M_LN10
241#define M_LN10 (2.30258509299404568402)
242#endif
243
244#ifndef M_PI
245#define M_PI (3.14159265358979323846)
246#endif
247
248#ifndef M_PI_2
249#define M_PI_2 (1.57079632679489661923)
250#endif
251
252#ifndef M_PI_4
253#define M_PI_4 (0.78539816339744830962)
254#endif
255
256#ifndef M_1_PI
257#define M_1_PI (0.31830988618379067154)
258#endif
259
260#ifndef M_2_PI
261#define M_2_PI (0.63661977236758134308)
262#endif
263
264#ifndef M_2_SQRTPI
265#define M_2_SQRTPI (1.12837916709551257390)
266#endif
267
268#ifndef M_SQRT2
269#define M_SQRT2 (1.41421356237309504880)
270#endif
271
272#ifndef M_SQRT1_2
273#define M_SQRT1_2 (0.70710678118654752440)
274#endif
275
276inline qreal qFastSin(qreal x)
277{
278 int si = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
279 qreal d = x - si * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
280 int ci = si + QT_SINE_TABLE_SIZE / 4;
281 si &= QT_SINE_TABLE_SIZE - 1;
282 ci &= QT_SINE_TABLE_SIZE - 1;
283 return qt_sine_table[si] + (qt_sine_table[ci] - 0.5 * qt_sine_table[si] * d) * d;
284}
285
286inline qreal qFastCos(qreal x)
287{
288 int ci = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
289 qreal d = x - ci * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
290 int si = ci + QT_SINE_TABLE_SIZE / 4;
291 si &= QT_SINE_TABLE_SIZE - 1;
292 ci &= QT_SINE_TABLE_SIZE - 1;
293 return qt_sine_table[si] - (qt_sine_table[ci] + 0.5 * qt_sine_table[si] * d) * d;
294}
295
296constexpr inline float qDegreesToRadians(float degrees)
297{
298 return degrees * float(M_PI / 180);
299}
300
301constexpr inline double qDegreesToRadians(double degrees)
302{
303 return degrees * (M_PI / 180);
304}
305
306constexpr inline long double qDegreesToRadians(long double degrees)
307{
308 return degrees * (M_PI / 180);
309}
310
311template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
312constexpr inline double qDegreesToRadians(T degrees)
313{
314 return qDegreesToRadians(static_cast<double>(degrees));
315}
316
317constexpr inline float qRadiansToDegrees(float radians)
318{
319 return radians * float(180 / M_PI);
320}
321
322constexpr inline double qRadiansToDegrees(double radians)
323{
324 return radians * (180 / M_PI);
325}
326
327constexpr inline long double qRadiansToDegrees(long double radians)
328{
329 return radians * (180 / M_PI);
330}
331
332// A qRadiansToDegrees(Integral) overload isn't here; it's extremely
333// questionable that someone is manipulating quantities in radians
334// using integral datatypes...
335
336namespace QtPrivate {
337constexpr inline quint32 qConstexprNextPowerOfTwo(quint32 v)
338{
339 v |= v >> 1;
340 v |= v >> 2;
341 v |= v >> 4;
342 v |= v >> 8;
343 v |= v >> 16;
344 ++v;
345 return v;
346}
347
348constexpr inline quint64 qConstexprNextPowerOfTwo(quint64 v)
349{
350 v |= v >> 1;
351 v |= v >> 2;
352 v |= v >> 4;
353 v |= v >> 8;
354 v |= v >> 16;
355 v |= v >> 32;
356 ++v;
357 return v;
358}
359
360constexpr inline quint32 qConstexprNextPowerOfTwo(qint32 v)
361{
362 return qConstexprNextPowerOfTwo(quint32(v));
363}
364
365constexpr inline quint64 qConstexprNextPowerOfTwo(qint64 v)
366{
367 return qConstexprNextPowerOfTwo(quint64(v));
368}
369} // namespace QtPrivate
370
371constexpr inline quint32 qNextPowerOfTwo(quint32 v)
372{
373#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
374 return std::bit_ceil(v + 1);
375#elif defined(QT_HAS_BUILTIN_CLZ)
376 if (v == 0)
377 return 1;
378 return 2U << (31 ^ QAlgorithmsPrivate::qt_builtin_clz(v));
379#else
380 return QtPrivate::qConstexprNextPowerOfTwo(v);
381#endif
382}
383
384constexpr inline quint64 qNextPowerOfTwo(quint64 v)
385{
386#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
387 return std::bit_ceil(v + 1);
388#elif defined(QT_HAS_BUILTIN_CLZLL)
389 if (v == 0)
390 return 1;
391 return Q_UINT64_C(2) << (63 ^ QAlgorithmsPrivate::qt_builtin_clzll(v));
392#else
393 return QtPrivate::qConstexprNextPowerOfTwo(v);
394#endif
395}
396
397constexpr inline quint32 qNextPowerOfTwo(qint32 v)
398{
399 return qNextPowerOfTwo(quint32(v));
400}
401
402constexpr inline quint64 qNextPowerOfTwo(qint64 v)
403{
404 return qNextPowerOfTwo(quint64(v));
405}
406
407QT_END_NAMESPACE
408
409#endif // QMATH_H
410

source code of qtbase/src/corelib/kernel/qmath.h