您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

184 行
5.7 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010–2023 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #pragma once
  13. //
  14. // Various maths functions
  15. // ———————————————————————
  16. //
  17. #include <cmath>
  18. #include <cstdio>
  19. #include <algorithm>
  20. #include <type_traits>
  21. #if defined __cpp_lib_int_pow2
  22. #include <bit>
  23. #endif
  24. #include <stdint.h>
  25. namespace lol
  26. {
  27. // Macros for type traits
  28. #define LOL_T_ARITHMETIC typename std::enable_if<std::is_arithmetic<T>::value, T>::type
  29. #define LOL_T_SIGNED typename std::enable_if<std::is_signed<T>::value, T>::type
  30. #define LOL_T_UNSIGNED typename std::enable_if<std::is_arithmetic<T>::value && \
  31. !std::is_signed<T>::value, T>::type
  32. #define LOL_T_INTEGRAL typename std::enable_if<std::is_integral<T>::value, T>::type
  33. #define LOL_T_FLOATING_POINT typename std::enable_if<std::is_floating_point<T>::value, T>::type
  34. // Mechanism to import standard cmath functions
  35. #define LOL_FORWARD_FP_1_ARG(f) \
  36. template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \
  37. [[nodiscard]] static inline T2 f(T x) { return std::f(x); }
  38. #define LOL_FORWARD_ARITH_2_ARGS(f) \
  39. template<typename T, typename T2 = T, typename DUMMY = LOL_T_ARITHMETIC> \
  40. [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); }
  41. #define LOL_FORWARD_FP_2_ARGS(f) \
  42. template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \
  43. [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); }
  44. LOL_FORWARD_FP_1_ARG(sqrt)
  45. LOL_FORWARD_FP_1_ARG(cbrt)
  46. LOL_FORWARD_FP_1_ARG(exp)
  47. LOL_FORWARD_FP_2_ARGS(pow)
  48. LOL_FORWARD_FP_1_ARG(sin)
  49. LOL_FORWARD_FP_1_ARG(cos)
  50. LOL_FORWARD_FP_1_ARG(tan)
  51. LOL_FORWARD_FP_1_ARG(asin)
  52. LOL_FORWARD_FP_1_ARG(acos)
  53. LOL_FORWARD_FP_1_ARG(atan)
  54. LOL_FORWARD_FP_2_ARGS(atan2)
  55. LOL_FORWARD_ARITH_2_ARGS(min)
  56. LOL_FORWARD_ARITH_2_ARGS(max)
  57. LOL_FORWARD_FP_2_ARGS(fmod)
  58. LOL_FORWARD_FP_1_ARG(floor)
  59. LOL_FORWARD_FP_1_ARG(ceil)
  60. LOL_FORWARD_FP_1_ARG(round)
  61. // Inherited from GLSL
  62. [[nodiscard]] static inline float degrees(float radians)
  63. {
  64. return radians * (180.0f / F_PI);
  65. }
  66. [[nodiscard]] static inline double degrees(double radians)
  67. {
  68. return radians * (180.0 / D_PI);
  69. }
  70. [[nodiscard]] static inline long double degrees(long double radians)
  71. {
  72. return radians * (180.0L / LD_PI);
  73. }
  74. [[nodiscard]] static inline float radians(float degrees)
  75. {
  76. return degrees * (F_PI / 180.0f);
  77. }
  78. [[nodiscard]] static inline double radians(double degrees)
  79. {
  80. return degrees * (D_PI / 180.0);
  81. }
  82. [[nodiscard]] static inline long double radians(long double degrees)
  83. {
  84. return degrees * (LD_PI / 180.0L);
  85. }
  86. // Integer version of radians() for convenience
  87. [[nodiscard]] static inline double radians(int32_t degrees)
  88. {
  89. return radians(double(degrees));
  90. }
  91. [[nodiscard]] static inline double radians(int64_t degrees)
  92. {
  93. return radians(double(degrees));
  94. }
  95. // Interpolation
  96. template<typename T, typename T2 = LOL_T_FLOATING_POINT>
  97. [[nodiscard]] static inline T2 mix(T a, T b, T x)
  98. {
  99. return a + (b - a) * x;
  100. }
  101. // Inherited from HLSL
  102. template<typename T, typename T2 = LOL_T_FLOATING_POINT>
  103. [[nodiscard]] static inline T2 lerp(T a, T b, T x)
  104. {
  105. return mix(a, b, x);
  106. }
  107. // Round up to next power of two
  108. template<typename T, typename T2=LOL_T_UNSIGNED>
  109. [[nodiscard]] static inline T2 bit_ceil(T x)
  110. {
  111. #if defined __cpp_lib_int_pow2
  112. return std::bit_ceil(x);
  113. #else
  114. x = x - 1;
  115. if constexpr (sizeof(x) > 4) x |= uint64_t(x) >> 32;
  116. if constexpr (sizeof(x) > 2) x |= uint64_t(x) >> 16;
  117. if constexpr (sizeof(x) > 1) x |= uint64_t(x) >> 8;
  118. x |= uint64_t(x) >> 4;
  119. x |= uint64_t(x) >> 2;
  120. x |= uint64_t(x) >> 1;
  121. return x + 1;
  122. #endif
  123. }
  124. // C++ doesn't define fabs() or fmod() for all types; we add these for
  125. // convenience to avoid adding complexity to vector.h.
  126. template<typename T, typename T2 = LOL_T_SIGNED>
  127. [[nodiscard]] static inline T2 fabs(T x) { return std::abs(x); }
  128. template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED>
  129. [[nodiscard]] static inline T2 fabs(T x) { return x; }
  130. template<typename T, typename T2 = LOL_T_INTEGRAL>
  131. [[nodiscard]] static inline T2 fmod(T x, T y) { return x % y; }
  132. template<typename T, typename T2 = LOL_T_INTEGRAL>
  133. [[nodiscard]] static inline T2 floor(T x) { return x; }
  134. template<typename T, typename T2 = LOL_T_INTEGRAL>
  135. [[nodiscard]] static inline T2 ceil(T x) { return x; }
  136. template<typename T, typename T2 = LOL_T_INTEGRAL>
  137. [[nodiscard]] static inline T2 round(T x) { return x; }
  138. template<typename T, typename T2 = LOL_T_ARITHMETIC>
  139. [[nodiscard]] static inline T2 sq(T x) { return x * x; }
  140. template<typename T, typename T2 = LOL_T_ARITHMETIC>
  141. [[nodiscard]] static inline T2 fract(T x) { return x - lol::floor(x); }
  142. template<typename T, typename T2 = LOL_T_ARITHMETIC>
  143. [[nodiscard]] static inline T2 clamp(T x, T y, T z) { return min(max(x, y), z); }
  144. template<typename T, typename T2 = LOL_T_ARITHMETIC>
  145. [[nodiscard]] static inline T2 saturate(T x) { return clamp(x, (T)0, (T)1); }
  146. template<typename T, typename T2 = LOL_T_ARITHMETIC>
  147. [[nodiscard]] static inline T2 gcd(T x, T y) { return y == (T)0 ? lol::fabs(x) : lol::gcd(y, lol::fmod(x, y)); }
  148. template<typename T, typename T2 = LOL_T_SIGNED>
  149. [[nodiscard]] static inline T2 sign(T x) { return (T)(((T)0 < x) - (x < (T)0)); }
  150. template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED>
  151. [[nodiscard]] static inline T2 sign(T x) { return (T)((T)0 < x); }
  152. } // namespace lol