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

187 行
6.6 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 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 <lol/math/constants.h>
  18. #include <../legacy/lol/base/types.h> // ldouble
  19. #include <cmath>
  20. #include <cstdio>
  21. #include <algorithm>
  22. #include <type_traits>
  23. #include <stdint.h>
  24. namespace lol
  25. {
  26. // This is OUR namespace. Don't let Windows headers mess with it.
  27. #undef min
  28. #undef max
  29. // Macros for type traits
  30. #define LOL_T_ARITHMETIC typename std::enable_if<std::is_arithmetic<T>::value, T>::type
  31. #define LOL_T_SIGNED typename std::enable_if<std::is_signed<T>::value, T>::type
  32. #define LOL_T_UNSIGNED typename std::enable_if<std::is_arithmetic<T>::value && \
  33. !std::is_signed<T>::value, T>::type
  34. #define LOL_T_INTEGRAL typename std::enable_if<std::is_integral<T>::value, T>::type
  35. #define LOL_T_FLOATING_POINT typename std::enable_if<std::is_floating_point<T>::value, T>::type
  36. // Mechanism to import standard cmath functions
  37. #define LOL_FORWARD_FP_1_ARG(f) \
  38. template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \
  39. [[nodiscard]] static inline T2 f(T x) { return std::f(x); }
  40. #define LOL_FORWARD_ARITH_2_ARGS(f) \
  41. template<typename T, typename T2 = T, typename DUMMY = LOL_T_ARITHMETIC> \
  42. [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); }
  43. #define LOL_FORWARD_FP_2_ARGS(f) \
  44. template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \
  45. [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); }
  46. LOL_FORWARD_FP_1_ARG(sqrt)
  47. LOL_FORWARD_FP_1_ARG(cbrt)
  48. LOL_FORWARD_FP_1_ARG(exp)
  49. LOL_FORWARD_FP_2_ARGS(pow)
  50. LOL_FORWARD_FP_1_ARG(sin)
  51. LOL_FORWARD_FP_1_ARG(cos)
  52. LOL_FORWARD_FP_1_ARG(tan)
  53. LOL_FORWARD_FP_1_ARG(asin)
  54. LOL_FORWARD_FP_1_ARG(acos)
  55. LOL_FORWARD_FP_1_ARG(atan)
  56. LOL_FORWARD_FP_2_ARGS(atan2)
  57. LOL_FORWARD_ARITH_2_ARGS(min)
  58. LOL_FORWARD_ARITH_2_ARGS(max)
  59. LOL_FORWARD_FP_2_ARGS(fmod)
  60. LOL_FORWARD_FP_1_ARG(floor)
  61. LOL_FORWARD_FP_1_ARG(ceil)
  62. LOL_FORWARD_FP_1_ARG(round)
  63. // Our extensions
  64. template<typename T, typename T2 = LOL_T_FLOATING_POINT>
  65. [[nodiscard]] static inline T2 sincos(T x, T *s, T *c)
  66. {
  67. *s = std::sin(x);
  68. *c = std::cos(x);
  69. }
  70. // Inherited from GLSL
  71. [[nodiscard]] static inline float degrees(float radians)
  72. {
  73. return radians * (180.0f / F_PI);
  74. }
  75. [[nodiscard]] static inline double degrees(double radians)
  76. {
  77. return radians * (180.0 / D_PI);
  78. }
  79. [[nodiscard]] static inline ldouble degrees(ldouble radians)
  80. {
  81. return radians * (180.0L / LD_PI);
  82. }
  83. [[nodiscard]] static inline float radians(float degrees)
  84. {
  85. return degrees * (F_PI / 180.0f);
  86. }
  87. [[nodiscard]] static inline double radians(double degrees)
  88. {
  89. return degrees * (D_PI / 180.0);
  90. }
  91. [[nodiscard]] static inline ldouble radians(ldouble degrees)
  92. {
  93. return degrees * (LD_PI / 180.0L);
  94. }
  95. // The integer versions return floating point values. This avoids nasty
  96. // surprises when calling radians(180) instead of radians(180.0).
  97. [[nodiscard]] static inline float degrees(int8_t x) { return degrees(float(x)); }
  98. [[nodiscard]] static inline float degrees(uint8_t x) { return degrees(float(x)); }
  99. [[nodiscard]] static inline float degrees(int16_t x) { return degrees(float(x)); }
  100. [[nodiscard]] static inline float degrees(uint16_t x) { return degrees(float(x)); }
  101. [[nodiscard]] static inline double degrees(int32_t x) { return degrees(double(x)); }
  102. [[nodiscard]] static inline double degrees(uint32_t x) { return degrees(double(x)); }
  103. [[nodiscard]] static inline ldouble degrees(int64_t x) { return degrees(ldouble(x)); }
  104. [[nodiscard]] static inline ldouble degrees(uint64_t x) { return degrees(ldouble(x)); }
  105. [[nodiscard]] static inline float radians(int8_t x) { return radians(float(x)); }
  106. [[nodiscard]] static inline float radians(uint8_t x) { return radians(float(x)); }
  107. [[nodiscard]] static inline float radians(int16_t x) { return radians(float(x)); }
  108. [[nodiscard]] static inline float radians(uint16_t x) { return radians(float(x)); }
  109. [[nodiscard]] static inline double radians(int32_t x) { return radians(double(x)); }
  110. [[nodiscard]] static inline double radians(uint32_t x) { return radians(double(x)); }
  111. [[nodiscard]] static inline ldouble radians(int64_t x) { return radians(ldouble(x)); }
  112. [[nodiscard]] static inline ldouble radians(uint64_t x) { return radians(ldouble(x)); }
  113. template<typename T, typename T2 = LOL_T_FLOATING_POINT>
  114. [[nodiscard]] static inline T2 mix(T a, T b, T x)
  115. {
  116. return a + (b - a) * x;
  117. }
  118. // Inherited from HLSL
  119. template<typename T, typename T2 = LOL_T_FLOATING_POINT>
  120. [[nodiscard]] static inline T2 lerp(T a, T b, T x)
  121. {
  122. return mix(a, b, x);
  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 */