Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
Math.h
Go to the documentation of this file.
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
8
10static constexpr float JPH_PI = 3.14159265358979323846f;
11
13static constexpr float cLargeFloat = 1.0e15f;
14
16JPH_INLINE constexpr float DegreesToRadians(float inV)
17{
18 return inV * (JPH_PI / 180.0f);
19}
20
22JPH_INLINE constexpr float RadiansToDegrees(float inV)
23{
24 return inV * (180.0f / JPH_PI);
25}
26
28inline 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
49JPH_INLINE float DifferenceOfProducts(float inA, float inB, float inC, float inD)
50{
51#ifdef JPH_USE_FMADD
52 float cd = inC * inD;
53 float err = std::fma(-inC, inD, cd);
54 float dop = std::fma(inA, inB, -cd);
55 return dop + err;
56#else
57 return inA * inB - inC * inD;
58#endif
59}
60
62template <typename T>
63JPH_INLINE constexpr T Clamp(T inV, T inMin, T inMax)
64{
65 return min(max(inV, inMin), inMax);
66}
67
69template <typename T>
70JPH_INLINE constexpr T Square(T inV)
71{
72 return inV * inV;
73}
74
76JPH_INLINE float Sqrt(float inV)
77{
78#ifdef JPH_USE_SSE
79 return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(inV)));
80#elif defined(JPH_USE_NEON)
81 return vget_lane_f32(vsqrt_f32(vdup_n_f32(inV)), 0);
82#elif defined(JPH_CPU_RISCV)
83 float res;
84 asm("fsqrt.s %0, %1" : "=f"(res) : "f"(inV));
85 return res;
86#else
87 return std::sqrt(inV);
88#endif
89}
90
92JPH_INLINE double Sqrt(double inV)
93{
94#ifdef JPH_USE_SSE
95 return _mm_cvtsd_f64(_mm_sqrt_sd(_mm_undefined_pd(), _mm_set_sd(inV)));
96#elif defined(JPH_USE_NEON)
97 return vget_lane_f64(vsqrt_f64(vdup_n_f64(inV)), 0);
98#elif defined(JPH_CPU_RISCV)
99 double res;
100 asm("fsqrt.d %0, %1" : "=f"(res) : "f"(inV));
101 return res;
102#else
103 return std::sqrt(inV);
104#endif
105}
106
108template <typename T>
109JPH_INLINE constexpr T Cubed(T inV)
110{
111 return inV * inV * inV;
112}
113
118JPH_INLINE float MulRSqrtApproximate(float inA, float inB)
119{
120 JPH_ASSERT(inB >= FLT_MIN);
121
122#ifndef JPH_CROSS_PLATFORM_DETERMINISTIC
123 #if defined(JPH_USE_SSE) && !defined(JPH_PLATFORM_WASM)
124 // One Newton-Raphson step: y' = y * (1.5 - 0.5 * x * y^2)
125 __m128 b = _mm_set_ss(inB);
126 __m128 rsqrtb = _mm_rsqrt_ss(b);
127 rsqrtb = _mm_mul_ss(rsqrtb, _mm_sub_ss(_mm_set_ss(1.5f), _mm_mul_ss(_mm_mul_ss(_mm_set_ss(0.5f), b), _mm_mul_ss(rsqrtb, rsqrtb))));
128 return inA * _mm_cvtss_f32(rsqrtb);
129 #elif defined(JPH_USE_NEON)
130 // vrsqrts_f32 accuracy is less so two Newton-Raphson steps are needed
131 float32x2_t b = vdup_n_f32(inB);
132 float32x2_t rsqrtb = vrsqrte_f32(b);
133 rsqrtb = vmul_f32(rsqrtb, vrsqrts_f32(b, vmul_f32(rsqrtb, rsqrtb)));
134 rsqrtb = vmul_f32(rsqrtb, vrsqrts_f32(b, vmul_f32(rsqrtb, rsqrtb)));
135 return inA * vget_lane_f32(rsqrtb, 0);
136 #elif defined(JPH_USE_RVV)
137 // vfrsqrt7 also needs two Newton-Raphson iterations
138 vfloat32m1_t b = __riscv_vfmv_v_f_f32m1(inB, 1);
139 vfloat32m1_t half_b = __riscv_vfmul_vf_f32m1(b, 0.5f, 1);
140 vfloat32m1_t rsqrtb = __riscv_vfrsqrt7_v_f32m1(b, 1);
141 rsqrtb = __riscv_vfmul_vv_f32m1(rsqrtb, __riscv_vfrsub_vf_f32m1(__riscv_vfmul_vv_f32m1(half_b, __riscv_vfmul_vv_f32m1(rsqrtb, rsqrtb, 1), 1), 1.5f, 1), 1);
142 rsqrtb = __riscv_vfmul_vv_f32m1(rsqrtb, __riscv_vfrsub_vf_f32m1(__riscv_vfmul_vv_f32m1(half_b, __riscv_vfmul_vv_f32m1(rsqrtb, rsqrtb, 1), 1), 1.5f, 1), 1);
143 return inA * __riscv_vfmv_f_s_f32m1_f32(rsqrtb);
144 #else
145 return inA / Sqrt(inB);
146 #endif
147#else
148 return inA / Sqrt(inB);
149#endif // JPH_CROSS_PLATFORM_DETERMINISTIC
150}
151
153template <typename T>
154JPH_INLINE constexpr T Sign(T inV)
155{
156 return inV < 0? T(-1) : T(1);
157}
158
160template <typename T>
161constexpr bool IsPowerOf2(T inV)
162{
163 return inV > 0 && (inV & (inV - 1)) == 0;
164}
165
167template <typename T>
168inline T AlignUp(T inV, uint64 inAlignment)
169{
170 JPH_ASSERT(IsPowerOf2(inAlignment));
171 return T((uint64(inV) + inAlignment - 1) & ~(inAlignment - 1));
172}
173
175template <typename T>
176inline bool IsAligned(T inV, uint64 inAlignment)
177{
178 JPH_ASSERT(IsPowerOf2(inAlignment));
179 return (uint64(inV) & (inAlignment - 1)) == 0;
180}
181
184{
185#if defined(JPH_CPU_X86) || defined(JPH_CPU_WASM)
186 #if defined(JPH_USE_TZCNT)
187 return _tzcnt_u32(inValue);
188 #elif defined(JPH_COMPILER_MSVC)
189 if (inValue == 0)
190 return 32;
191 unsigned long result;
192 _BitScanForward(&result, inValue);
193 return result;
194 #else
195 return inValue? __builtin_ctz(inValue) : 32;
196 #endif
197#elif defined(JPH_CPU_ARM)
198 #if defined(JPH_COMPILER_MSVC)
199 if (inValue == 0)
200 return 32;
201 unsigned long result;
202 _BitScanForward(&result, inValue);
203 return result;
204 #else
205 return inValue? __builtin_ctz(inValue) : 32;
206 #endif
207#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH)
208 return inValue? __builtin_ctz(inValue) : 32;
209#else
210 #error Undefined
211#endif
212}
213
216{
217#if defined(JPH_CPU_X86) || defined(JPH_CPU_WASM)
218 #if defined(JPH_USE_LZCNT)
219 return _lzcnt_u32(inValue);
220 #elif defined(JPH_COMPILER_MSVC)
221 if (inValue == 0)
222 return 32;
223 unsigned long result;
224 _BitScanReverse(&result, inValue);
225 return 31 - result;
226 #else
227 return inValue? __builtin_clz(inValue) : 32;
228 #endif
229#elif defined(JPH_CPU_ARM)
230 #if defined(JPH_COMPILER_MSVC)
231 return _CountLeadingZeros(inValue);
232 #else
233 return inValue? __builtin_clz(inValue) : 32;
234 #endif
235#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH)
236 return inValue? __builtin_clz(inValue) : 32;
237#else
238 #error Undefined
239#endif
240}
241
243inline uint CountBits(uint32 inValue)
244{
245#if defined(JPH_COMPILER_CLANG) || defined(JPH_COMPILER_GCC)
246 return __builtin_popcount(inValue);
247#elif defined(JPH_COMPILER_MSVC)
248 #if defined(JPH_USE_SSE4_2)
249 return _mm_popcnt_u32(inValue);
250 #elif defined(JPH_USE_NEON) && (_MSC_VER >= 1930) // _CountOneBits not available on MSVC2019
251 return _CountOneBits(inValue);
252 #else
253 inValue = inValue - ((inValue >> 1) & 0x55555555);
254 inValue = (inValue & 0x33333333) + ((inValue >> 2) & 0x33333333);
255 inValue = (inValue + (inValue >> 4)) & 0x0F0F0F0F;
256 return (inValue * 0x01010101) >> 24;
257 #endif
258#else
259 #error Undefined
260#endif
261}
262
265{
266 return inValue <= 1? uint32(1) : uint32(1) << (32 - CountLeadingZeros(inValue - 1));
267}
268
270template <class To, class From>
271JPH_INLINE constexpr To BitCast(const From &inValue)
272{
273 static_assert(std::is_trivially_constructible_v<To>);
274 static_assert(sizeof(From) == sizeof(To));
275 return __builtin_bit_cast(To, inValue);
276}
277
std::uint64_t uint64
Definition Core.h:569
unsigned int uint
Definition Core.h:564
#define JPH_NAMESPACE_END
Definition Core.h:487
std::uint32_t uint32
Definition Core.h:567
#define JPH_NAMESPACE_BEGIN
Definition Core.h:481
#define JPH_ASSERT(...)
Definition IssueReporting.h:28
JPH_INLINE constexpr T Clamp(T inV, T inMin, T inMax)
Clamp a value between two values.
Definition Math.h:63
JPH_INLINE constexpr T Sign(T inV)
Get the sign of a value.
Definition Math.h:154
float CenterAngleAroundZero(float inV)
Convert angle in radians to the range .
Definition Math.h:28
constexpr bool IsPowerOf2(T inV)
Check if inV is a power of 2.
Definition Math.h:161
uint CountBits(uint32 inValue)
Count the number of 1 bits in a value.
Definition Math.h:243
JPH_INLINE constexpr T Square(T inV)
Square a value.
Definition Math.h:70
JPH_INLINE constexpr float DegreesToRadians(float inV)
Convert a value from degrees to radians.
Definition Math.h:16
JPH_INLINE constexpr To BitCast(const From &inValue)
Simple implementation of C++20 std::bit_cast.
Definition Math.h:271
JPH_INLINE constexpr T Cubed(T inV)
Returns .
Definition Math.h:109
JPH_INLINE constexpr float RadiansToDegrees(float inV)
Convert a value from radians to degrees.
Definition Math.h:22
JPH_INLINE float Sqrt(float inV)
Take the square root of a float value.
Definition Math.h:76
bool IsAligned(T inV, uint64 inAlignment)
Check if inV is inAlignment aligned.
Definition Math.h:176
uint CountTrailingZeros(uint32 inValue)
Compute number of trailing zero bits (how many low bits are zero)
Definition Math.h:183
uint CountLeadingZeros(uint32 inValue)
Compute the number of leading zero bits (how many high bits are zero)
Definition Math.h:215
JPH_INLINE float DifferenceOfProducts(float inA, float inB, float inC, float inD)
Definition Math.h:49
JPH_INLINE float MulRSqrtApproximate(float inA, float inB)
Definition Math.h:118
uint32 GetNextPowerOf2(uint32 inValue)
Get the next higher power of 2 of a value, or the value itself if the value is already a power of 2.
Definition Math.h:264
T AlignUp(T inV, uint64 inAlignment)
Align inV up to the next inAlignment bytes.
Definition Math.h:168