/engine/math/math_utils.c

https://github.com/r-lyeh/AVA · C · 122 lines · 97 code · 16 blank · 9 comment · 10 complexity · 1272a20834e8306e07112b6e5633cc8e MD5 · raw file

  1. // includes code by @glampert (public domain).
  2. #pragma once
  3. #include "../detect/detect_inline.c"
  4. #include "math_linear.c"
  5. #include <float.h> // FLT_MIN, FLT_MAX
  6. #include <stdint.h>
  7. #include <math.h>
  8. #ifndef M_PI // even with _USE_MATH_DEFINES not always available
  9. #define M_PI 3.14159265358979323846
  10. #endif
  11. // ----------------------------------------------------------------------------
  12. // Fast approximations of math functions.
  13. // - by @glampert, public domain.
  14. #include <float.h>
  15. static const float FloatEpsilon = FLT_EPSILON;
  16. static const float PI = C_PI;
  17. static const float HalfPI = C_PI * 0.5f;
  18. static const float TAU = C_PI * 2.0f;
  19. typedef union Float2UInt {
  20. float asFloat;
  21. uint32_t asUInt;
  22. } Float2UInt;
  23. static m_inline float floatRound(float x) {
  24. // Probably slower than std::floor(), also depends of FPU settings,
  25. // but we only need this for that special sin/cos() case anyways...
  26. const int i = (int)(x);
  27. return (x >= 0.0f) ? (float)(i) : (float)(i - 1);
  28. }
  29. static m_inline float floatAbs(float x) {
  30. // Mask-off the sign bit
  31. Float2UInt i;
  32. i.asFloat = x;
  33. i.asUInt &= 0x7FFFFFFF;
  34. return i.asFloat;
  35. }
  36. static m_inline float floatInvSqrt(float x) {
  37. // Modified version of the emblematic Q_rsqrt() from Quake 3.
  38. // See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
  39. Float2UInt i;
  40. float y, r;
  41. y = x * 0.5f;
  42. i.asFloat = x;
  43. i.asUInt = 0x5F3759DF - (i.asUInt >> 1);
  44. r = i.asFloat;
  45. r = r * (1.5f - (r * r * y));
  46. return r;
  47. }
  48. static m_inline float floatSin(float radians) {
  49. static const float A = -2.39e-08f;
  50. static const float B = 2.7526e-06f;
  51. static const float C = 1.98409e-04f;
  52. static const float D = 8.3333315e-03f;
  53. static const float E = 1.666666664e-01f;
  54. if (radians < 0.0f || radians >= TAU)
  55. {
  56. radians -= floatRound(radians / TAU) * TAU;
  57. }
  58. if (radians < PI)
  59. {
  60. if (radians > HalfPI)
  61. {
  62. radians = PI - radians;
  63. }
  64. }
  65. else
  66. {
  67. radians = (radians > (PI + HalfPI)) ? (radians - TAU) : (PI - radians);
  68. }
  69. const float s = radians * radians;
  70. return radians * (((((A * s + B) * s - C) * s + D) * s - E) * s + 1.0f);
  71. }
  72. static m_inline float floatCos(float radians) {
  73. static const float A = -2.605e-07f;
  74. static const float B = 2.47609e-05f;
  75. static const float C = 1.3888397e-03f;
  76. static const float D = 4.16666418e-02f;
  77. static const float E = 4.999999963e-01f;
  78. if (radians < 0.0f || radians >= TAU) {
  79. radians -= floatRound(radians / TAU) * TAU;
  80. }
  81. float d;
  82. if (radians < PI) {
  83. if (radians > HalfPI)
  84. {
  85. radians = PI - radians;
  86. d = -1.0f;
  87. }
  88. else
  89. {
  90. d = 1.0f;
  91. }
  92. } else {
  93. if (radians > (PI + HalfPI))
  94. {
  95. radians = radians - TAU;
  96. d = 1.0f;
  97. }
  98. else
  99. {
  100. radians = PI - radians;
  101. d = -1.0f;
  102. }
  103. }
  104. const float s = radians * radians;
  105. return d * (((((A * s + B) * s - C) * s + D) * s - E) * s + 1.0f);
  106. }