2
0

Math.h 4.9 KB

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