1/****************************************************************************
2**
3** Copyright (C) 2016 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
138template <typename T> auto qLn(T v)
139{
140 using std::log;
141 return log(v);
142}
143
144template <typename T> auto qExp(T v)
145{
146 using std::exp;
147 return exp(v);
148}
149
150template <typename T1, typename T2> auto qPow(T1 x, T2 y)
151{
152 using std::pow;
153 return pow(x, y);
154}
155
156// TODO: use template variables (e.g. Qt::pi<type>) for these once we have C++14 support:
157
158#ifndef M_E
159#define M_E (2.7182818284590452354)
160#endif
161
162#ifndef M_LOG2E
163#define M_LOG2E (1.4426950408889634074)
164#endif
165
166#ifndef M_LOG10E
167#define M_LOG10E (0.43429448190325182765)
168#endif
169
170#ifndef M_LN2
171#define M_LN2 (0.69314718055994530942)
172#endif
173
174#ifndef M_LN10
175#define M_LN10 (2.30258509299404568402)
176#endif
177
178#ifndef M_PI
179#define M_PI (3.14159265358979323846)
180#endif
181
182#ifndef M_PI_2
183#define M_PI_2 (1.57079632679489661923)
184#endif
185
186#ifndef M_PI_4
187#define M_PI_4 (0.78539816339744830962)
188#endif
189
190#ifndef M_1_PI
191#define M_1_PI (0.31830988618379067154)
192#endif
193
194#ifndef M_2_PI
195#define M_2_PI (0.63661977236758134308)
196#endif
197
198#ifndef M_2_SQRTPI
199#define M_2_SQRTPI (1.12837916709551257390)
200#endif
201
202#ifndef M_SQRT2
203#define M_SQRT2 (1.41421356237309504880)
204#endif
205
206#ifndef M_SQRT1_2
207#define M_SQRT1_2 (0.70710678118654752440)
208#endif
209
210inline qreal qFastSin(qreal x)
211{
212 int si = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
213 qreal d = x - si * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
214 int ci = si + QT_SINE_TABLE_SIZE / 4;
215 si &= QT_SINE_TABLE_SIZE - 1;
216 ci &= QT_SINE_TABLE_SIZE - 1;
217 return qt_sine_table[si] + (qt_sine_table[ci] - 0.5 * qt_sine_table[si] * d) * d;
218}
219
220inline qreal qFastCos(qreal x)
221{
222 int ci = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
223 qreal d = x - ci * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
224 int si = ci + QT_SINE_TABLE_SIZE / 4;
225 si &= QT_SINE_TABLE_SIZE - 1;
226 ci &= QT_SINE_TABLE_SIZE - 1;
227 return qt_sine_table[si] - (qt_sine_table[ci] + 0.5 * qt_sine_table[si] * d) * d;
228}
229
230constexpr inline float qDegreesToRadians(float degrees)
231{
232 return degrees * float(M_PI / 180);
233}
234
235constexpr inline double qDegreesToRadians(double degrees)
236{
237 return degrees * (M_PI / 180);
238}
239
240constexpr inline long double qDegreesToRadians(long double degrees)
241{
242 return degrees * (M_PI / 180);
243}
244
245template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
246constexpr inline double qDegreesToRadians(T degrees)
247{
248 return qDegreesToRadians(static_cast<double>(degrees));
249}
250
251constexpr inline float qRadiansToDegrees(float radians)
252{
253 return radians * float(180 / M_PI);
254}
255
256constexpr inline double qRadiansToDegrees(double radians)
257{
258 return radians * (180 / M_PI);
259}
260
261constexpr inline long double qRadiansToDegrees(long double radians)
262{
263 return radians * (180 / M_PI);
264}
265
266// A qRadiansToDegrees(Integral) overload isn't here; it's extremely
267// questionable that someone is manipulating quantities in radians
268// using integral datatypes...
269
270namespace QtPrivate {
271constexpr inline quint32 qConstexprNextPowerOfTwo(quint32 v)
272{
273 v |= v >> 1;
274 v |= v >> 2;
275 v |= v >> 4;
276 v |= v >> 8;
277 v |= v >> 16;
278 ++v;
279 return v;
280}
281
282constexpr inline quint64 qConstexprNextPowerOfTwo(quint64 v)
283{
284 v |= v >> 1;
285 v |= v >> 2;
286 v |= v >> 4;
287 v |= v >> 8;
288 v |= v >> 16;
289 v |= v >> 32;
290 ++v;
291 return v;
292}
293
294constexpr inline quint32 qConstexprNextPowerOfTwo(qint32 v)
295{
296 return qConstexprNextPowerOfTwo(quint32(v));
297}
298
299constexpr inline quint64 qConstexprNextPowerOfTwo(qint64 v)
300{
301 return qConstexprNextPowerOfTwo(quint64(v));
302}
303} // namespace QtPrivate
304
305constexpr inline quint32 qNextPowerOfTwo(quint32 v)
306{
307#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
308 return std::bit_ceil(v + 1);
309#elif defined(QT_HAS_BUILTIN_CLZ)
310 if (v == 0)
311 return 1;
312 return 2U << (31 ^ QAlgorithmsPrivate::qt_builtin_clz(v));
313#else
314 return QtPrivate::qConstexprNextPowerOfTwo(v);
315#endif
316}
317
318constexpr inline quint64 qNextPowerOfTwo(quint64 v)
319{
320#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
321 return std::bit_ceil(v + 1);
322#elif defined(QT_HAS_BUILTIN_CLZLL)
323 if (v == 0)
324 return 1;
325 return Q_UINT64_C(2) << (63 ^ QAlgorithmsPrivate::qt_builtin_clzll(v));
326#else
327 return QtPrivate::qConstexprNextPowerOfTwo(v);
328#endif
329}
330
331constexpr inline quint32 qNextPowerOfTwo(qint32 v)
332{
333 return qNextPowerOfTwo(quint32(v));
334}
335
336constexpr inline quint64 qNextPowerOfTwo(qint64 v)
337{
338 return qNextPowerOfTwo(quint64(v));
339}
340
341QT_END_NAMESPACE
342
343#endif // QMATH_H
344