math.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include <LibC/assert.h>
  2. #include <LibM/math.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. template<size_t>
  6. constexpr double e_to_power();
  7. template<>
  8. constexpr double e_to_power<0>() { return 1; }
  9. template<size_t exponent>
  10. constexpr double e_to_power() { return M_E * e_to_power<exponent - 1>(); }
  11. template<size_t>
  12. constexpr size_t factorial();
  13. template<>
  14. constexpr size_t factorial<0>() { return 1; }
  15. template<size_t value>
  16. constexpr size_t factorial() { return value * factorial<value - 1>(); }
  17. template<size_t>
  18. constexpr size_t product_even();
  19. template<>
  20. constexpr size_t product_even<2>() { return 2; }
  21. template<size_t value>
  22. constexpr size_t product_even() { return value * product_even<value - 2>(); }
  23. template<size_t>
  24. constexpr size_t product_odd();
  25. template<>
  26. constexpr size_t product_odd<1>() { return 1; }
  27. template<size_t value>
  28. constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
  29. extern "C" {
  30. double trunc(double x)
  31. {
  32. return (int64_t)x;
  33. }
  34. double cos(double angle)
  35. {
  36. return sin(angle + M_PI_2);
  37. }
  38. // This can also be done with a taylor expansion, but for
  39. // now this works pretty well (and doesn't mess anything up
  40. // in quake in particular, which is very Floating-Point precision
  41. // heavy)
  42. double sin(double angle)
  43. {
  44. double ret = 0.0;
  45. __asm__(
  46. "fsin"
  47. : "=t"(ret)
  48. : "0"(angle));
  49. return ret;
  50. }
  51. double pow(double x, double y)
  52. {
  53. //FIXME: Extremely unlikely to be standards compliant.
  54. return exp(y * log(x));
  55. }
  56. double ldexp(double, int exp)
  57. {
  58. (void)exp;
  59. ASSERT_NOT_REACHED();
  60. return 0;
  61. }
  62. double tanh(double x)
  63. {
  64. if (x > 0) {
  65. double exponentiated = exp(2 * x);
  66. return (exponentiated - 1) / (exponentiated + 1);
  67. }
  68. double plusX = exp(x);
  69. double minusX = 1 / plusX;
  70. return (plusX - minusX) / (plusX + minusX);
  71. }
  72. double ampsin(double angle)
  73. {
  74. double looped_angle = fmod(M_PI + angle, M_TAU) - M_PI;
  75. double looped_angle_squared = looped_angle * looped_angle;
  76. double quadratic_term;
  77. if (looped_angle > 0) {
  78. quadratic_term = -looped_angle_squared;
  79. } else {
  80. quadratic_term = looped_angle_squared;
  81. }
  82. double linear_term = M_PI * looped_angle;
  83. return quadratic_term + linear_term;
  84. }
  85. double tan(double angle)
  86. {
  87. return ampsin(angle) / ampsin(M_PI_2 + angle);
  88. }
  89. double sqrt(double x)
  90. {
  91. double res;
  92. __asm__("fsqrt"
  93. : "=t"(res)
  94. : "0"(x));
  95. return res;
  96. }
  97. double sinh(double x)
  98. {
  99. double exponentiated = exp(x);
  100. if (x > 0)
  101. return (exponentiated * exponentiated - 1) / 2 / exponentiated;
  102. return (exponentiated - 1 / exponentiated) / 2;
  103. }
  104. double log10(double x)
  105. {
  106. return log(x) / M_LN10;
  107. }
  108. double log(double x)
  109. {
  110. if (x < 0)
  111. return __builtin_nan("");
  112. if (x == 0)
  113. return -__builtin_huge_val();
  114. double y = 1 + 2 * (x - 1) / (x + 1);
  115. double exponentiated = exp(y);
  116. y = y + 2 * (x - exponentiated) / (x + exponentiated);
  117. exponentiated = exp(y);
  118. y = y + 2 * (x - exponentiated) / (x + exponentiated);
  119. exponentiated = exp(y);
  120. return y + 2 * (x - exponentiated) / (x + exponentiated);
  121. }
  122. double fmod(double index, double period)
  123. {
  124. return index - trunc(index / period) * period;
  125. }
  126. double exp(double exponent)
  127. {
  128. double result = 1;
  129. if (exponent >= 1) {
  130. size_t integer_part = (size_t)exponent;
  131. if (integer_part & 1)
  132. result *= e_to_power<1>();
  133. if (integer_part & 2)
  134. result *= e_to_power<2>();
  135. if (integer_part > 3) {
  136. if (integer_part & 4)
  137. result *= e_to_power<4>();
  138. if (integer_part & 8)
  139. result *= e_to_power<8>();
  140. if (integer_part & 16)
  141. result *= e_to_power<16>();
  142. if (integer_part & 32)
  143. result *= e_to_power<32>();
  144. if (integer_part >= 64)
  145. return __builtin_huge_val();
  146. }
  147. exponent -= integer_part;
  148. } else if (exponent < 0)
  149. return 1 / exp(-exponent);
  150. double taylor_series_result = 1 + exponent;
  151. double taylor_series_numerator = exponent * exponent;
  152. taylor_series_result += taylor_series_numerator / factorial<2>();
  153. taylor_series_numerator *= exponent;
  154. taylor_series_result += taylor_series_numerator / factorial<3>();
  155. taylor_series_numerator *= exponent;
  156. taylor_series_result += taylor_series_numerator / factorial<4>();
  157. taylor_series_numerator *= exponent;
  158. taylor_series_result += taylor_series_numerator / factorial<5>();
  159. return result * taylor_series_result;
  160. }
  161. double cosh(double x)
  162. {
  163. double exponentiated = exp(-x);
  164. if (x < 0)
  165. return (1 + exponentiated * exponentiated) / 2 / exponentiated;
  166. return (1 / exponentiated + exponentiated) / 2;
  167. }
  168. double atan2(double y, double x)
  169. {
  170. if (x > 0)
  171. return atan(y / x);
  172. if (x == 0) {
  173. if (y > 0)
  174. return M_PI_2;
  175. if (y < 0)
  176. return -M_PI_2;
  177. return 0;
  178. }
  179. if (y >= 0)
  180. return atan(y / x) + M_PI;
  181. return atan(y / x) - M_PI;
  182. }
  183. double atan(double x)
  184. {
  185. if (x < 0)
  186. return -atan(-x);
  187. if (x > 1)
  188. return M_PI_2 - atan(1 / x);
  189. double squared = x * x;
  190. return x / (1 + 1 * 1 * squared / (3 + 2 * 2 * squared / (5 + 3 * 3 * squared / (7 + 4 * 4 * squared / (9 + 5 * 5 * squared / (11 + 6 * 6 * squared / (13 + 7 * 7 * squared)))))));
  191. }
  192. double asin(double x)
  193. {
  194. if (x > 1 || x < -1)
  195. return __builtin_nan("");
  196. if (x > 0.5 || x < -0.5)
  197. return 2 * atan(x / (1 + sqrt(1 - x * x)));
  198. double squared = x * x;
  199. double value = x;
  200. double i = x * squared;
  201. value += i * product_odd<1>() / product_even<2>() / 3;
  202. i *= squared;
  203. value += i * product_odd<3>() / product_even<4>() / 5;
  204. i *= squared;
  205. value += i * product_odd<5>() / product_even<6>() / 7;
  206. i *= squared;
  207. value += i * product_odd<7>() / product_even<8>() / 9;
  208. i *= squared;
  209. value += i * product_odd<9>() / product_even<10>() / 11;
  210. i *= squared;
  211. value += i * product_odd<11>() / product_even<12>() / 13;
  212. return value;
  213. }
  214. double acos(double x)
  215. {
  216. return M_PI_2 - asin(x);
  217. }
  218. double fabs(double value)
  219. {
  220. return value < 0 ? -value : value;
  221. }
  222. double log2(double x)
  223. {
  224. return log(x) / M_LN2;
  225. }
  226. float log2f(float x)
  227. {
  228. return log2(x);
  229. }
  230. long double log2l(long double x)
  231. {
  232. return log2(x);
  233. }
  234. double frexp(double, int*)
  235. {
  236. ASSERT_NOT_REACHED();
  237. return 0;
  238. }
  239. float frexpf(float, int*)
  240. {
  241. ASSERT_NOT_REACHED();
  242. return 0;
  243. }
  244. long double frexpl(long double, int*)
  245. {
  246. ASSERT_NOT_REACHED();
  247. return 0;
  248. }
  249. float roundf(float value)
  250. {
  251. // FIXME: Please fix me. I am naive.
  252. if (value >= 0.0f)
  253. return (float)(int)(value + 0.5f);
  254. return (float)(int)(value - 0.5f);
  255. }
  256. float ceilf(float value)
  257. {
  258. // FIXME: Please fix me. I am naive.
  259. int as_int = (int)value;
  260. if (value == (float)as_int) {
  261. return (float)as_int;
  262. }
  263. return as_int + 1;
  264. }
  265. double modf(double x, double* intpart)
  266. {
  267. *intpart = (double)((int)(x));
  268. return x - (int)x;
  269. }
  270. }