Math.h 4.4 KB

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