General Purpose library for Freestanding C++ and POSIX systems
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

210 linhas
3.9 KiB

  1. #pragma once
  2. #include "gp/algorithm/repeat.hpp"
  3. #include <limits>
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. namespace gp{
  7. template<typename T>
  8. constexpr T pi;
  9. template<>
  10. constexpr float pi<float> = 3.1415926535897932384626433832795028841971693993751058209749445923078164062;
  11. template<>
  12. constexpr double pi<double> = 3.1415926535897932384626433832795028841971693993751058209749445923078164062L;
  13. template<typename T>
  14. T abs(T);
  15. template<>
  16. float abs<float>(float value) {
  17. static_assert(sizeof(float) == 4, "bad float size");
  18. union {
  19. float fp;
  20. uint32_t ab;
  21. } p;
  22. p.fp = value;
  23. p.ab &= 0x7fFFffFF;
  24. return p.fp;
  25. }
  26. template<>
  27. double abs<double>(double value) {
  28. static_assert(sizeof(double) == 8, "bad double size");
  29. union {
  30. double fp;
  31. uint64_t ab;
  32. } p;
  33. p.fp = value;
  34. p.ab &= 0x7fFFffFFffFFffFF;
  35. return p.fp;
  36. }
  37. template<typename T>
  38. T floor(T);
  39. template<>
  40. float floor<float>(float value) {
  41. static_assert(sizeof(float) == 4, "bad float size");
  42. if(
  43. value >= 16777216
  44. || value <= std::numeric_limits<int32_t>::min()
  45. || value != value
  46. ) {
  47. return value;
  48. }
  49. int32_t ret = value;
  50. float ret_d = ret;
  51. if(value == ret_d || value >= 0) {
  52. return ret;
  53. } else {
  54. return ret-1;
  55. }
  56. }
  57. template<>
  58. double floor<double>(double value) {
  59. static_assert(sizeof(double) == 8, "bad double size");
  60. if(
  61. value >= 9007199254740992
  62. || value <= std::numeric_limits<int64_t>::min()
  63. || value != value
  64. ) {
  65. return value;
  66. }
  67. int64_t ret = value;
  68. double ret_d = ret;
  69. if(value == ret_d || value >= 0) {
  70. return ret;
  71. } else {
  72. return ret-1;
  73. }
  74. }
  75. template<typename T>
  76. T sign(T);
  77. template<>
  78. float sign<float>(float value) {
  79. static_assert(sizeof(float) == 4, "bad float size");
  80. if(!value) return 0;
  81. union {
  82. float fp;
  83. uint32_t ab;
  84. } p;
  85. p.fp = value;
  86. p.ab &= 0x7fFFffFF;
  87. return value/p.fp;
  88. }
  89. template<>
  90. double sign<double>(double value) {
  91. static_assert(sizeof(double) == 8, "bad double size");
  92. if(!value) return 0;
  93. union {
  94. double fp;
  95. uint64_t ab;
  96. } p;
  97. p.fp = value;
  98. p.ab &= 0x7fFFffFFffFFffFF;
  99. return value/p.fp;
  100. }
  101. template<size_t steps, typename T, size_t accuracy = 1000000>
  102. T sin_taylor(T value) {
  103. const T acc = T{1}/T{accuracy};
  104. T B = value;
  105. T C = 1;
  106. T ret = B/C;
  107. for(size_t i = 1; (i < steps) && (abs<>(B/C) > acc); ++i) {
  108. B *= -1*value*value;
  109. C *= 2*i*(2*i+1);
  110. ret += B/C;
  111. }
  112. return ret;
  113. }
  114. float sin(float v) {
  115. v += pi<float>;
  116. v = v - 2*pi<float>*floor(v/(2*pi<float>));
  117. v -= pi<float>;
  118. float s = sign(v);
  119. v *= s;
  120. return sin_taylor<10>(v)*s;
  121. }
  122. double sin(double v) {
  123. v += pi<double>;
  124. v = v - 2*pi<double>*floor(v/(2*pi<double>));
  125. v -= pi<double>;
  126. float s = sign(v);
  127. v *= s;
  128. return sin_taylor<10>(v)*s;
  129. }
  130. // TODO: replace with an actual implementation
  131. float cos(float v) {
  132. return sin(v+pi<float>/2);
  133. }
  134. // TODO: replace with an actual implementation
  135. double cos(double v) {
  136. return sin(v+pi<double>/2);
  137. }
  138. // TODO: replace with an actual implementation
  139. float tan(float v) {
  140. return sin(v)/cos(v);
  141. }
  142. // TODO: replace with an actual implementation
  143. double tan(double v) {
  144. return sin(v)/cos(v);
  145. }
  146. template<size_t cycles = 5>
  147. float isqrt(float v) {
  148. int32_t i;
  149. float x2, y;
  150. constexpr float threehalfs = 1.5F;
  151. x2 = v * 0.5F;
  152. y = v;
  153. i = * ( int32_t * ) &y;
  154. i = 0x5F375A86 - ( i >> 1 );
  155. y = * ( float * ) &i;
  156. gp::repeat(cycles, [&](){
  157. y = y * ( threehalfs - ( x2 * y * y ) );
  158. });
  159. return y;
  160. }
  161. template<size_t cycles = 5>
  162. double isqrt(double v) {
  163. int64_t i;
  164. double x2, y;
  165. constexpr double threehalfs = 1.5F;
  166. x2 = v * 0.5F;
  167. y = v;
  168. i = * ( int64_t * ) &y;
  169. i = 0x5FE6EB50C7B537A9 - ( i >> 1 );
  170. y = * ( double * ) &i;
  171. gp::repeat(cycles, [&](){
  172. y = y * ( threehalfs - ( x2 * y * y ) );
  173. });
  174. return y;
  175. }
  176. float fast_isqrt(float v) {return isqrt<1>(v);}
  177. double fast_isqrt(double v) {return isqrt<1>(v);}
  178. }