Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Math/Math.h
9913 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
JPH_NAMESPACE_BEGIN
8
9
/// The constant \f$\pi\f$
10
static constexpr float JPH_PI = 3.14159265358979323846f;
11
12
/// A large floating point value which, when squared, is still much smaller than FLT_MAX
13
static constexpr float cLargeFloat = 1.0e15f;
14
15
/// Convert a value from degrees to radians
16
JPH_INLINE constexpr float DegreesToRadians(float inV)
17
{
18
return inV * (JPH_PI / 180.0f);
19
}
20
21
/// Convert a value from radians to degrees
22
JPH_INLINE constexpr float RadiansToDegrees(float inV)
23
{
24
return inV * (180.0f / JPH_PI);
25
}
26
27
/// Convert angle in radians to the range \f$[-\pi, \pi]\f$
28
inline float CenterAngleAroundZero(float inV)
29
{
30
if (inV < -JPH_PI)
31
{
32
do
33
inV += 2.0f * JPH_PI;
34
while (inV < -JPH_PI);
35
}
36
else if (inV > JPH_PI)
37
{
38
do
39
inV -= 2.0f * JPH_PI;
40
while (inV > JPH_PI);
41
}
42
JPH_ASSERT(inV >= -JPH_PI && inV <= JPH_PI);
43
return inV;
44
}
45
46
/// Clamp a value between two values
47
template <typename T>
48
JPH_INLINE constexpr T Clamp(T inV, T inMin, T inMax)
49
{
50
return min(max(inV, inMin), inMax);
51
}
52
53
/// Square a value
54
template <typename T>
55
JPH_INLINE constexpr T Square(T inV)
56
{
57
return inV * inV;
58
}
59
60
/// Returns \f$inV^3\f$.
61
template <typename T>
62
JPH_INLINE constexpr T Cubed(T inV)
63
{
64
return inV * inV * inV;
65
}
66
67
/// Get the sign of a value
68
template <typename T>
69
JPH_INLINE constexpr T Sign(T inV)
70
{
71
return inV < 0? T(-1) : T(1);
72
}
73
74
/// Check if inV is a power of 2
75
template <typename T>
76
constexpr bool IsPowerOf2(T inV)
77
{
78
return inV > 0 && (inV & (inV - 1)) == 0;
79
}
80
81
/// Align inV up to the next inAlignment bytes
82
template <typename T>
83
inline T AlignUp(T inV, uint64 inAlignment)
84
{
85
JPH_ASSERT(IsPowerOf2(inAlignment));
86
return T((uint64(inV) + inAlignment - 1) & ~(inAlignment - 1));
87
}
88
89
/// Check if inV is inAlignment aligned
90
template <typename T>
91
inline bool IsAligned(T inV, uint64 inAlignment)
92
{
93
JPH_ASSERT(IsPowerOf2(inAlignment));
94
return (uint64(inV) & (inAlignment - 1)) == 0;
95
}
96
97
/// Compute number of trailing zero bits (how many low bits are zero)
98
inline uint CountTrailingZeros(uint32 inValue)
99
{
100
#if defined(JPH_CPU_X86) || defined(JPH_CPU_WASM)
101
#if defined(JPH_USE_TZCNT)
102
return _tzcnt_u32(inValue);
103
#elif defined(JPH_COMPILER_MSVC)
104
if (inValue == 0)
105
return 32;
106
unsigned long result;
107
_BitScanForward(&result, inValue);
108
return result;
109
#else
110
if (inValue == 0)
111
return 32;
112
return __builtin_ctz(inValue);
113
#endif
114
#elif defined(JPH_CPU_ARM)
115
#if defined(JPH_COMPILER_MSVC)
116
if (inValue == 0)
117
return 32;
118
unsigned long result;
119
_BitScanForward(&result, inValue);
120
return result;
121
#else
122
if (inValue == 0)
123
return 32;
124
return __builtin_ctz(inValue);
125
#endif
126
#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH)
127
return inValue ? __builtin_ctz(inValue) : 32;
128
#else
129
#error Undefined
130
#endif
131
}
132
133
/// Compute the number of leading zero bits (how many high bits are zero)
134
inline uint CountLeadingZeros(uint32 inValue)
135
{
136
#if defined(JPH_CPU_X86) || defined(JPH_CPU_WASM)
137
#if defined(JPH_USE_LZCNT)
138
return _lzcnt_u32(inValue);
139
#elif defined(JPH_COMPILER_MSVC)
140
if (inValue == 0)
141
return 32;
142
unsigned long result;
143
_BitScanReverse(&result, inValue);
144
return 31 - result;
145
#else
146
if (inValue == 0)
147
return 32;
148
return __builtin_clz(inValue);
149
#endif
150
#elif defined(JPH_CPU_ARM)
151
#if defined(JPH_COMPILER_MSVC)
152
return _CountLeadingZeros(inValue);
153
#else
154
return __builtin_clz(inValue);
155
#endif
156
#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH)
157
return inValue ? __builtin_clz(inValue) : 32;
158
#else
159
#error Undefined
160
#endif
161
}
162
163
/// Count the number of 1 bits in a value
164
inline uint CountBits(uint32 inValue)
165
{
166
#if defined(JPH_COMPILER_CLANG) || defined(JPH_COMPILER_GCC)
167
return __builtin_popcount(inValue);
168
#elif defined(JPH_COMPILER_MSVC)
169
#if defined(JPH_USE_SSE4_2)
170
return _mm_popcnt_u32(inValue);
171
#elif defined(JPH_USE_NEON) && (_MSC_VER >= 1930) // _CountOneBits not available on MSVC2019
172
return _CountOneBits(inValue);
173
#else
174
inValue = inValue - ((inValue >> 1) & 0x55555555);
175
inValue = (inValue & 0x33333333) + ((inValue >> 2) & 0x33333333);
176
inValue = (inValue + (inValue >> 4)) & 0x0F0F0F0F;
177
return (inValue * 0x01010101) >> 24;
178
#endif
179
#else
180
#error Undefined
181
#endif
182
}
183
184
/// Get the next higher power of 2 of a value, or the value itself if the value is already a power of 2
185
inline uint32 GetNextPowerOf2(uint32 inValue)
186
{
187
return inValue <= 1? uint32(1) : uint32(1) << (32 - CountLeadingZeros(inValue - 1));
188
}
189
190
// Simple implementation of C++20 std::bit_cast (unfortunately not constexpr)
191
template <class To, class From>
192
JPH_INLINE To BitCast(const From &inValue)
193
{
194
static_assert(std::is_trivially_constructible_v<To>);
195
static_assert(sizeof(From) == sizeof(To));
196
197
union FromTo
198
{
199
To mTo;
200
From mFrom;
201
};
202
203
FromTo convert;
204
convert.mFrom = inValue;
205
return convert.mTo;
206
}
207
208
JPH_NAMESPACE_END
209
210