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 | |

66 | QT_BEGIN_NAMESPACE |

67 | |

68 | #define QT_SINE_TABLE_SIZE 256 |

69 | |

70 | extern Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE]; |

71 | |

72 | template <typename T> int qCeil(T v) |

73 | { |

74 | using std::ceil; |

75 | return int(ceil(v)); |

76 | } |

77 | |

78 | template <typename T> int qFloor(T v) |

79 | { |

80 | using std::floor; |

81 | return int(floor(v)); |

82 | } |

83 | |

84 | template <typename T> auto qFabs(T v) |

85 | { |

86 | using std::fabs; |

87 | return fabs(v); |

88 | } |

89 | |

90 | template <typename T> auto qSin(T v) |

91 | { |

92 | using std::sin; |

93 | return sin(v); |

94 | } |

95 | |

96 | template <typename T> auto qCos(T v) |

97 | { |

98 | using std::cos; |

99 | return cos(v); |

100 | } |

101 | |

102 | template <typename T> auto qTan(T v) |

103 | { |

104 | using std::tan; |

105 | return tan(v); |

106 | } |

107 | |

108 | template <typename T> auto qAcos(T v) |

109 | { |

110 | using std::acos; |

111 | return acos(v); |

112 | } |

113 | |

114 | template <typename T> auto qAsin(T v) |

115 | { |

116 | using std::asin; |

117 | return asin(v); |

118 | } |

119 | |

120 | template <typename T> auto qAtan(T v) |

121 | { |

122 | using std::atan; |

123 | return atan(v); |

124 | } |

125 | |

126 | template <typename T1, typename T2> auto qAtan2(T1 y, T2 x) |

127 | { |

128 | using std::atan2; |

129 | return atan2(y, x); |

130 | } |

131 | |

132 | template <typename T> auto qSqrt(T v) |

133 | { |

134 | using std::sqrt; |

135 | return sqrt(v); |

136 | } |

137 | |

138 | namespace QtPrivate { |

139 | template <typename R, typename F> // For qfloat16 to specialize |

140 | struct QHypotType { using type = decltype(std::hypot(R(1), F(1))); }; |

141 | |

142 | // Implements hypot() without limiting number of arguments: |

143 | template <typename T> |

144 | class QHypotHelper |

145 | { |

146 | T scale, total; |

147 | template <typename F> friend class QHypotHelper; |

148 | QHypotHelper(T first, T prior) : scale(first), total(prior) {} |

149 | public: |

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 | |

180 | template<typename F, typename ...Fs> |

181 | auto 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: |

187 | template <typename Tx, typename Ty> |

188 | auto 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 |

196 | template <typename Tx, typename Ty, typename Tz> |

197 | auto 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 | |

204 | template <typename T> auto qLn(T v) |

205 | { |

206 | using std::log; |

207 | return log(v); |

208 | } |

209 | |

210 | template <typename T> auto qExp(T v) |

211 | { |

212 | using std::exp; |

213 | return exp(v); |

214 | } |

215 | |

216 | template <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 | |

276 | inline 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 | |

286 | inline 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 | |

296 | constexpr inline float qDegreesToRadians(float degrees) |

297 | { |

298 | return degrees * float(M_PI / 180); |

299 | } |

300 | |

301 | constexpr inline double qDegreesToRadians(double degrees) |

302 | { |

303 | return degrees * (M_PI / 180); |

304 | } |

305 | |

306 | constexpr inline long double qDegreesToRadians(long double degrees) |

307 | { |

308 | return degrees * (M_PI / 180); |

309 | } |

310 | |

311 | template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true> |

312 | constexpr inline double qDegreesToRadians(T degrees) |

313 | { |

314 | return qDegreesToRadians(static_cast<double>(degrees)); |

315 | } |

316 | |

317 | constexpr inline float qRadiansToDegrees(float radians) |

318 | { |

319 | return radians * float(180 / M_PI); |

320 | } |

321 | |

322 | constexpr inline double qRadiansToDegrees(double radians) |

323 | { |

324 | return radians * (180 / M_PI); |

325 | } |

326 | |

327 | constexpr 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 | |

336 | namespace QtPrivate { |

337 | constexpr 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 | |

348 | constexpr 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 | |

360 | constexpr inline quint32 qConstexprNextPowerOfTwo(qint32 v) |

361 | { |

362 | return qConstexprNextPowerOfTwo(quint32(v)); |

363 | } |

364 | |

365 | constexpr inline quint64 qConstexprNextPowerOfTwo(qint64 v) |

366 | { |

367 | return qConstexprNextPowerOfTwo(quint64(v)); |

368 | } |

369 | } // namespace QtPrivate |

370 | |

371 | constexpr 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 | |

384 | constexpr 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 | |

397 | constexpr inline quint32 qNextPowerOfTwo(qint32 v) |

398 | { |

399 | return qNextPowerOfTwo(quint32(v)); |

400 | } |

401 | |

402 | constexpr inline quint64 qNextPowerOfTwo(qint64 v) |

403 | { |

404 | return qNextPowerOfTwo(quint64(v)); |

405 | } |

406 | |

407 | QT_END_NAMESPACE |

408 | |

409 | #endif // QMATH_H |

410 |