Path: blob/master/thirdparty/jolt_physics/Jolt/Math/Math.h
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56JPH_NAMESPACE_BEGIN78/// The constant \f$\pi\f$9static constexpr float JPH_PI = 3.14159265358979323846f;1011/// A large floating point value which, when squared, is still much smaller than FLT_MAX12static constexpr float cLargeFloat = 1.0e15f;1314/// Convert a value from degrees to radians15JPH_INLINE constexpr float DegreesToRadians(float inV)16{17return inV * (JPH_PI / 180.0f);18}1920/// Convert a value from radians to degrees21JPH_INLINE constexpr float RadiansToDegrees(float inV)22{23return inV * (180.0f / JPH_PI);24}2526/// Convert angle in radians to the range \f$[-\pi, \pi]\f$27inline float CenterAngleAroundZero(float inV)28{29if (inV < -JPH_PI)30{31do32inV += 2.0f * JPH_PI;33while (inV < -JPH_PI);34}35else if (inV > JPH_PI)36{37do38inV -= 2.0f * JPH_PI;39while (inV > JPH_PI);40}41JPH_ASSERT(inV >= -JPH_PI && inV <= JPH_PI);42return inV;43}4445/// Clamp a value between two values46template <typename T>47JPH_INLINE constexpr T Clamp(T inV, T inMin, T inMax)48{49return min(max(inV, inMin), inMax);50}5152/// Square a value53template <typename T>54JPH_INLINE constexpr T Square(T inV)55{56return inV * inV;57}5859/// Returns \f$inV^3\f$.60template <typename T>61JPH_INLINE constexpr T Cubed(T inV)62{63return inV * inV * inV;64}6566/// Get the sign of a value67template <typename T>68JPH_INLINE constexpr T Sign(T inV)69{70return inV < 0? T(-1) : T(1);71}7273/// Check if inV is a power of 274template <typename T>75constexpr bool IsPowerOf2(T inV)76{77return inV > 0 && (inV & (inV - 1)) == 0;78}7980/// Align inV up to the next inAlignment bytes81template <typename T>82inline T AlignUp(T inV, uint64 inAlignment)83{84JPH_ASSERT(IsPowerOf2(inAlignment));85return T((uint64(inV) + inAlignment - 1) & ~(inAlignment - 1));86}8788/// Check if inV is inAlignment aligned89template <typename T>90inline bool IsAligned(T inV, uint64 inAlignment)91{92JPH_ASSERT(IsPowerOf2(inAlignment));93return (uint64(inV) & (inAlignment - 1)) == 0;94}9596/// Compute number of trailing zero bits (how many low bits are zero)97inline uint CountTrailingZeros(uint32 inValue)98{99#if defined(JPH_CPU_X86) || defined(JPH_CPU_WASM)100#if defined(JPH_USE_TZCNT)101return _tzcnt_u32(inValue);102#elif defined(JPH_COMPILER_MSVC)103if (inValue == 0)104return 32;105unsigned long result;106_BitScanForward(&result, inValue);107return result;108#else109if (inValue == 0)110return 32;111return __builtin_ctz(inValue);112#endif113#elif defined(JPH_CPU_ARM)114#if defined(JPH_COMPILER_MSVC)115if (inValue == 0)116return 32;117unsigned long result;118_BitScanForward(&result, inValue);119return result;120#else121if (inValue == 0)122return 32;123return __builtin_ctz(inValue);124#endif125#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH)126return inValue ? __builtin_ctz(inValue) : 32;127#else128#error Undefined129#endif130}131132/// Compute the number of leading zero bits (how many high bits are zero)133inline uint CountLeadingZeros(uint32 inValue)134{135#if defined(JPH_CPU_X86) || defined(JPH_CPU_WASM)136#if defined(JPH_USE_LZCNT)137return _lzcnt_u32(inValue);138#elif defined(JPH_COMPILER_MSVC)139if (inValue == 0)140return 32;141unsigned long result;142_BitScanReverse(&result, inValue);143return 31 - result;144#else145if (inValue == 0)146return 32;147return __builtin_clz(inValue);148#endif149#elif defined(JPH_CPU_ARM)150#if defined(JPH_COMPILER_MSVC)151return _CountLeadingZeros(inValue);152#else153return __builtin_clz(inValue);154#endif155#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH)156return inValue ? __builtin_clz(inValue) : 32;157#else158#error Undefined159#endif160}161162/// Count the number of 1 bits in a value163inline uint CountBits(uint32 inValue)164{165#if defined(JPH_COMPILER_CLANG) || defined(JPH_COMPILER_GCC)166return __builtin_popcount(inValue);167#elif defined(JPH_COMPILER_MSVC)168#if defined(JPH_USE_SSE4_2)169return _mm_popcnt_u32(inValue);170#elif defined(JPH_USE_NEON) && (_MSC_VER >= 1930) // _CountOneBits not available on MSVC2019171return _CountOneBits(inValue);172#else173inValue = inValue - ((inValue >> 1) & 0x55555555);174inValue = (inValue & 0x33333333) + ((inValue >> 2) & 0x33333333);175inValue = (inValue + (inValue >> 4)) & 0x0F0F0F0F;176return (inValue * 0x01010101) >> 24;177#endif178#else179#error Undefined180#endif181}182183/// Get the next higher power of 2 of a value, or the value itself if the value is already a power of 2184inline uint32 GetNextPowerOf2(uint32 inValue)185{186return inValue <= 1? uint32(1) : uint32(1) << (32 - CountLeadingZeros(inValue - 1));187}188189// Simple implementation of C++20 std::bit_cast (unfortunately not constexpr)190template <class To, class From>191JPH_INLINE To BitCast(const From &inValue)192{193static_assert(std::is_trivially_constructible_v<To>);194static_assert(sizeof(From) == sizeof(To));195196union FromTo197{198To mTo;199From mFrom;200};201202FromTo convert;203convert.mFrom = inValue;204return convert.mTo;205}206207JPH_NAMESPACE_END208209210