math.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/Platform.h>
  27. #include <AK/StdLibExtras.h>
  28. #include <LibC/assert.h>
  29. #include <math.h>
  30. #include <stdint.h>
  31. #include <stdlib.h>
  32. template<size_t>
  33. constexpr double e_to_power();
  34. template<>
  35. constexpr double e_to_power<0>() { return 1; }
  36. template<size_t exponent>
  37. constexpr double e_to_power() { return M_E * e_to_power<exponent - 1>(); }
  38. template<size_t>
  39. constexpr size_t factorial();
  40. template<>
  41. constexpr size_t factorial<0>() { return 1; }
  42. template<size_t value>
  43. constexpr size_t factorial() { return value * factorial<value - 1>(); }
  44. template<size_t>
  45. constexpr size_t product_even();
  46. template<>
  47. constexpr size_t product_even<2>() { return 2; }
  48. template<size_t value>
  49. constexpr size_t product_even() { return value * product_even<value - 2>(); }
  50. template<size_t>
  51. constexpr size_t product_odd();
  52. template<>
  53. constexpr size_t product_odd<1>() { return 1; }
  54. template<size_t value>
  55. constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
  56. enum class RoundingMode {
  57. ToZero,
  58. Up,
  59. Down,
  60. ToEven
  61. };
  62. template<typename T>
  63. union FloatExtractor;
  64. #if ARCH(I386) || ARCH(X86_64)
  65. // This assumes long double is 80 bits, which is true with GCC on Intel platforms
  66. template<>
  67. union FloatExtractor<long double> {
  68. static const int mantissa_bits = 64;
  69. static const unsigned long long mantissa_max = ~0u;
  70. static const int exponent_bias = 16383;
  71. static const int exponent_bits = 15;
  72. static const unsigned exponent_max = 32767;
  73. struct {
  74. unsigned long long mantissa;
  75. unsigned exponent : 15;
  76. unsigned sign : 1;
  77. };
  78. long double d;
  79. };
  80. #endif
  81. template<>
  82. union FloatExtractor<double> {
  83. static const int mantissa_bits = 52;
  84. static const unsigned long long mantissa_max = (1ull << 52) - 1;
  85. static const int exponent_bias = 1023;
  86. static const int exponent_bits = 11;
  87. static const unsigned exponent_max = 2047;
  88. struct {
  89. unsigned long long mantissa : 52;
  90. unsigned exponent : 11;
  91. unsigned sign : 1;
  92. };
  93. double d;
  94. };
  95. template<>
  96. union FloatExtractor<float> {
  97. static const int mantissa_bits = 23;
  98. static const unsigned mantissa_max = (1 << 23) - 1;
  99. static const int exponent_bias = 127;
  100. static const int exponent_bits = 8;
  101. static const unsigned exponent_max = 255;
  102. struct {
  103. unsigned long long mantissa : 23;
  104. unsigned exponent : 8;
  105. unsigned sign : 1;
  106. };
  107. float d;
  108. };
  109. // This is much branchier than it really needs to be
  110. template<typename FloatType>
  111. static FloatType internal_to_integer(FloatType x, RoundingMode rounding_mode)
  112. {
  113. if (!isfinite(x))
  114. return x;
  115. using Extractor = FloatExtractor<decltype(x)>;
  116. Extractor extractor;
  117. extractor.d = x;
  118. auto unbiased_exponent = extractor.exponent - Extractor::exponent_bias;
  119. bool round = false;
  120. bool guard = false;
  121. if (unbiased_exponent < 0) {
  122. // it was easier to special case [0..1) as it saves us from
  123. // handling subnormals, underflows, etc
  124. if (unbiased_exponent == -1) {
  125. round = true;
  126. }
  127. guard = extractor.mantissa != 0;
  128. extractor.mantissa = 0;
  129. extractor.exponent = 0;
  130. } else {
  131. if (unbiased_exponent >= Extractor::mantissa_bits)
  132. return x;
  133. auto dead_bitcount = Extractor::mantissa_bits - unbiased_exponent;
  134. auto dead_mask = (1ull << dead_bitcount) - 1;
  135. auto dead_bits = extractor.mantissa & dead_mask;
  136. extractor.mantissa &= ~dead_mask;
  137. auto guard_mask = dead_mask >> 1;
  138. guard = (dead_bits & guard_mask) != 0;
  139. round = (dead_bits & ~guard_mask) != 0;
  140. }
  141. bool should_round = false;
  142. switch (rounding_mode) {
  143. case RoundingMode::ToEven:
  144. should_round = round;
  145. break;
  146. case RoundingMode::Up:
  147. if (!extractor.sign)
  148. should_round = guard || round;
  149. break;
  150. case RoundingMode::Down:
  151. if (extractor.sign)
  152. should_round = guard || round;
  153. break;
  154. case RoundingMode::ToZero:
  155. break;
  156. }
  157. if (should_round) {
  158. // We could do this ourselves, but this saves us from manually
  159. // handling overflow.
  160. if (extractor.sign)
  161. extractor.d -= 1.0;
  162. else
  163. extractor.d += 1.0;
  164. }
  165. return extractor.d;
  166. }
  167. // This is much branchier than it really needs to be
  168. template<typename FloatType>
  169. static FloatType internal_nextafter(FloatType x, bool up)
  170. {
  171. if (!isfinite(x))
  172. return x;
  173. using Extractor = FloatExtractor<decltype(x)>;
  174. Extractor extractor;
  175. extractor.d = x;
  176. if (x == 0) {
  177. if (!extractor.sign) {
  178. extractor.mantissa = 1;
  179. extractor.sign = !up;
  180. return extractor.d;
  181. }
  182. if (up) {
  183. extractor.sign = false;
  184. extractor.mantissa = 1;
  185. return extractor.d;
  186. }
  187. extractor.mantissa = 1;
  188. extractor.sign = up != extractor.sign;
  189. return extractor.d;
  190. }
  191. if (up != extractor.sign) {
  192. extractor.mantissa++;
  193. if (!extractor.mantissa) {
  194. // no need to normalize the mantissa as we just hit a power
  195. // of two.
  196. extractor.exponent++;
  197. if (extractor.exponent == Extractor::exponent_max) {
  198. extractor.exponent = Extractor::exponent_max - 1;
  199. extractor.mantissa = Extractor::mantissa_max;
  200. }
  201. }
  202. return extractor.d;
  203. }
  204. if (!extractor.mantissa) {
  205. if (extractor.exponent) {
  206. extractor.exponent--;
  207. extractor.mantissa = Extractor::mantissa_max;
  208. } else {
  209. extractor.d = 0;
  210. }
  211. return extractor.d;
  212. }
  213. extractor.mantissa--;
  214. if (extractor.mantissa != Extractor::mantissa_max)
  215. return extractor.d;
  216. if (extractor.exponent) {
  217. extractor.exponent--;
  218. // normalize
  219. extractor.mantissa <<= 1;
  220. } else {
  221. if (extractor.sign) {
  222. // Negative infinity
  223. extractor.mantissa = 0;
  224. extractor.exponent = Extractor::exponent_max;
  225. }
  226. }
  227. return extractor.d;
  228. }
  229. template<typename FloatT>
  230. static int internal_ilogb(FloatT x) NOEXCEPT
  231. {
  232. if (x == 0)
  233. return FP_ILOGB0;
  234. if (isnan(x))
  235. return FP_ILOGNAN;
  236. if (!isfinite(x))
  237. return INT_MAX;
  238. using Extractor = FloatExtractor<FloatT>;
  239. Extractor extractor;
  240. extractor.d = x;
  241. return (int)extractor.exponent - Extractor::exponent_bias;
  242. }
  243. extern "C" {
  244. double trunc(double x) NOEXCEPT
  245. {
  246. return internal_to_integer(x, RoundingMode::ToZero);
  247. }
  248. double cos(double angle) NOEXCEPT
  249. {
  250. return sin(angle + M_PI_2);
  251. }
  252. float cosf(float angle) NOEXCEPT
  253. {
  254. return sinf(angle + M_PI_2);
  255. }
  256. // This can also be done with a taylor expansion, but for
  257. // now this works pretty well (and doesn't mess anything up
  258. // in quake in particular, which is very Floating-Point precision
  259. // heavy)
  260. double sin(double angle) NOEXCEPT
  261. {
  262. double ret = 0.0;
  263. __asm__(
  264. "fsin"
  265. : "=t"(ret)
  266. : "0"(angle));
  267. return ret;
  268. }
  269. float sinf(float angle) NOEXCEPT
  270. {
  271. float ret = 0.0f;
  272. __asm__(
  273. "fsin"
  274. : "=t"(ret)
  275. : "0"(angle));
  276. return ret;
  277. }
  278. double pow(double x, double y) NOEXCEPT
  279. {
  280. // FIXME: Please fix me. I am naive.
  281. if (isnan(y))
  282. return y;
  283. if (y == 0)
  284. return 1;
  285. if (x == 0)
  286. return 0;
  287. if (y == 1)
  288. return x;
  289. int y_as_int = (int)y;
  290. if (y == (double)y_as_int) {
  291. double result = x;
  292. for (int i = 0; i < fabs(y) - 1; ++i)
  293. result *= x;
  294. if (y < 0)
  295. result = 1.0 / result;
  296. return result;
  297. }
  298. return exp2(y * log2(x));
  299. }
  300. float powf(float x, float y) NOEXCEPT
  301. {
  302. return (float)pow(x, y);
  303. }
  304. double ldexp(double x, int exp) NOEXCEPT
  305. {
  306. return x * exp2(exp);
  307. }
  308. float ldexpf(float x, int exp) NOEXCEPT
  309. {
  310. return x * exp2f(exp);
  311. }
  312. double tanh(double x) NOEXCEPT
  313. {
  314. if (x > 0) {
  315. double exponentiated = exp(2 * x);
  316. return (exponentiated - 1) / (exponentiated + 1);
  317. }
  318. double plusX = exp(x);
  319. double minusX = 1 / plusX;
  320. return (plusX - minusX) / (plusX + minusX);
  321. }
  322. static double ampsin(double angle) NOEXCEPT
  323. {
  324. double looped_angle = fmod(M_PI + angle, M_TAU) - M_PI;
  325. double looped_angle_squared = looped_angle * looped_angle;
  326. double quadratic_term;
  327. if (looped_angle > 0) {
  328. quadratic_term = -looped_angle_squared;
  329. } else {
  330. quadratic_term = looped_angle_squared;
  331. }
  332. double linear_term = M_PI * looped_angle;
  333. return quadratic_term + linear_term;
  334. }
  335. double tan(double angle) NOEXCEPT
  336. {
  337. return ampsin(angle) / ampsin(M_PI_2 + angle);
  338. }
  339. double sqrt(double x) NOEXCEPT
  340. {
  341. double res;
  342. __asm__("fsqrt"
  343. : "=t"(res)
  344. : "0"(x));
  345. return res;
  346. }
  347. float sqrtf(float x) NOEXCEPT
  348. {
  349. float res;
  350. __asm__("fsqrt"
  351. : "=t"(res)
  352. : "0"(x));
  353. return res;
  354. }
  355. double sinh(double x) NOEXCEPT
  356. {
  357. double exponentiated = exp(x);
  358. if (x > 0)
  359. return (exponentiated * exponentiated - 1) / 2 / exponentiated;
  360. return (exponentiated - 1 / exponentiated) / 2;
  361. }
  362. double log10(double x) NOEXCEPT
  363. {
  364. double ret = 0.0;
  365. __asm__(
  366. "fldlg2\n"
  367. "fld %%st(1)\n"
  368. "fyl2x\n"
  369. "fstp %%st(1)"
  370. : "=t"(ret)
  371. : "0"(x));
  372. return ret;
  373. }
  374. double log(double x) NOEXCEPT
  375. {
  376. double ret = 0.0;
  377. __asm__(
  378. "fldln2\n"
  379. "fld %%st(1)\n"
  380. "fyl2x\n"
  381. "fstp %%st(1)"
  382. : "=t"(ret)
  383. : "0"(x));
  384. return ret;
  385. }
  386. float logf(float x) NOEXCEPT
  387. {
  388. return (float)log(x);
  389. }
  390. double fmod(double index, double period) NOEXCEPT
  391. {
  392. return index - trunc(index / period) * period;
  393. }
  394. float fmodf(float index, float period) NOEXCEPT
  395. {
  396. return index - trunc(index / period) * period;
  397. }
  398. double exp(double exponent) NOEXCEPT
  399. {
  400. double res = 0;
  401. __asm__("fldl2e\n"
  402. "fmulp\n"
  403. "fld1\n"
  404. "fld %%st(1)\n"
  405. "fprem\n"
  406. "f2xm1\n"
  407. "faddp\n"
  408. "fscale\n"
  409. "fstp %%st(1)"
  410. : "=t"(res)
  411. : "0"(exponent));
  412. return res;
  413. }
  414. float expf(float exponent) NOEXCEPT
  415. {
  416. return (float)exp(exponent);
  417. }
  418. double exp2(double exponent) NOEXCEPT
  419. {
  420. double res = 0;
  421. __asm__("fld1\n"
  422. "fld %%st(1)\n"
  423. "fprem\n"
  424. "f2xm1\n"
  425. "faddp\n"
  426. "fscale\n"
  427. "fstp %%st(1)"
  428. : "=t"(res)
  429. : "0"(exponent));
  430. return res;
  431. }
  432. float exp2f(float exponent) NOEXCEPT
  433. {
  434. return (float)exp2(exponent);
  435. }
  436. double cosh(double x) NOEXCEPT
  437. {
  438. double exponentiated = exp(-x);
  439. if (x < 0)
  440. return (1 + exponentiated * exponentiated) / 2 / exponentiated;
  441. return (1 / exponentiated + exponentiated) / 2;
  442. }
  443. double atan2(double y, double x) NOEXCEPT
  444. {
  445. if (x > 0)
  446. return atan(y / x);
  447. if (x == 0) {
  448. if (y > 0)
  449. return M_PI_2;
  450. if (y < 0)
  451. return -M_PI_2;
  452. return 0;
  453. }
  454. if (y >= 0)
  455. return atan(y / x) + M_PI;
  456. return atan(y / x) - M_PI;
  457. }
  458. float atan2f(float y, float x) NOEXCEPT
  459. {
  460. return (float)atan2(y, x);
  461. }
  462. double atan(double x) NOEXCEPT
  463. {
  464. if (x < 0)
  465. return -atan(-x);
  466. if (x > 1)
  467. return M_PI_2 - atan(1 / x);
  468. double squared = x * x;
  469. 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)))))));
  470. }
  471. double asin(double x) NOEXCEPT
  472. {
  473. if (x > 1 || x < -1)
  474. return NAN;
  475. if (x > 0.5 || x < -0.5)
  476. return 2 * atan(x / (1 + sqrt(1 - x * x)));
  477. double squared = x * x;
  478. double value = x;
  479. double i = x * squared;
  480. value += i * product_odd<1>() / product_even<2>() / 3;
  481. i *= squared;
  482. value += i * product_odd<3>() / product_even<4>() / 5;
  483. i *= squared;
  484. value += i * product_odd<5>() / product_even<6>() / 7;
  485. i *= squared;
  486. value += i * product_odd<7>() / product_even<8>() / 9;
  487. i *= squared;
  488. value += i * product_odd<9>() / product_even<10>() / 11;
  489. i *= squared;
  490. value += i * product_odd<11>() / product_even<12>() / 13;
  491. return value;
  492. }
  493. float asinf(float x) NOEXCEPT
  494. {
  495. return (float)asin(x);
  496. }
  497. double acos(double x) NOEXCEPT
  498. {
  499. return M_PI_2 - asin(x);
  500. }
  501. float acosf(float x) NOEXCEPT
  502. {
  503. return M_PI_2 - asinf(x);
  504. }
  505. double fabs(double value) NOEXCEPT
  506. {
  507. return value < 0 ? -value : value;
  508. }
  509. int ilogbl(long double x) NOEXCEPT
  510. {
  511. return internal_ilogb(x);
  512. }
  513. int ilogb(double x) NOEXCEPT
  514. {
  515. return internal_ilogb(x);
  516. }
  517. int ilogbf(float x) NOEXCEPT
  518. {
  519. return internal_ilogb(x);
  520. }
  521. long double logbl(long double x) NOEXCEPT
  522. {
  523. return ilogbl(x);
  524. }
  525. double logb(double x) NOEXCEPT
  526. {
  527. return ilogb(x);
  528. }
  529. float logbf(float x) NOEXCEPT
  530. {
  531. return ilogbf(x);
  532. }
  533. double log2(double x) NOEXCEPT
  534. {
  535. double ret = 0.0;
  536. __asm__(
  537. "fld1\n"
  538. "fld %%st(1)\n"
  539. "fyl2x\n"
  540. "fstp %%st(1)"
  541. : "=t"(ret)
  542. : "0"(x));
  543. return ret;
  544. }
  545. float log2f(float x) NOEXCEPT
  546. {
  547. return log2(x);
  548. }
  549. long double log2l(long double x) NOEXCEPT
  550. {
  551. return log2(x);
  552. }
  553. double frexp(double, int*) NOEXCEPT
  554. {
  555. VERIFY_NOT_REACHED();
  556. return 0;
  557. }
  558. float frexpf(float, int*) NOEXCEPT
  559. {
  560. VERIFY_NOT_REACHED();
  561. return 0;
  562. }
  563. long double frexpl(long double, int*) NOEXCEPT
  564. {
  565. VERIFY_NOT_REACHED();
  566. return 0;
  567. }
  568. double round(double value) NOEXCEPT
  569. {
  570. return internal_to_integer(value, RoundingMode::ToEven);
  571. }
  572. float roundf(float value) NOEXCEPT
  573. {
  574. return internal_to_integer(value, RoundingMode::ToEven);
  575. }
  576. float floorf(float value) NOEXCEPT
  577. {
  578. return internal_to_integer(value, RoundingMode::Down);
  579. }
  580. double floor(double value) NOEXCEPT
  581. {
  582. return internal_to_integer(value, RoundingMode::Down);
  583. }
  584. double rint(double value) NOEXCEPT
  585. {
  586. // This should be the current rounding mode
  587. return internal_to_integer(value, RoundingMode::ToEven);
  588. }
  589. float ceilf(float value) NOEXCEPT
  590. {
  591. return internal_to_integer(value, RoundingMode::Up);
  592. }
  593. double ceil(double value) NOEXCEPT
  594. {
  595. return internal_to_integer(value, RoundingMode::Up);
  596. }
  597. double modf(double x, double* intpart) NOEXCEPT
  598. {
  599. double integer_part = internal_to_integer(x, RoundingMode::ToZero);
  600. *intpart = integer_part;
  601. auto fraction = x - integer_part;
  602. if (signbit(fraction) != signbit(x))
  603. fraction = -fraction;
  604. return fraction;
  605. }
  606. double gamma(double x) NOEXCEPT
  607. {
  608. // Stirling approximation
  609. return sqrt(2.0 * M_PI / x) * pow(x / M_E, x);
  610. }
  611. double expm1(double x) NOEXCEPT
  612. {
  613. return exp(x) - 1;
  614. }
  615. double cbrt(double x) NOEXCEPT
  616. {
  617. if (isinf(x) || x == 0)
  618. return x;
  619. if (x < 0)
  620. return -cbrt(-x);
  621. double r = x;
  622. double ex = 0;
  623. while (r < 0.125) {
  624. r *= 8;
  625. ex--;
  626. }
  627. while (r > 1.0) {
  628. r *= 0.125;
  629. ex++;
  630. }
  631. r = (-0.46946116 * r + 1.072302) * r + 0.3812513;
  632. while (ex < 0) {
  633. r *= 0.5;
  634. ex++;
  635. }
  636. while (ex > 0) {
  637. r *= 2;
  638. ex--;
  639. }
  640. r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
  641. r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
  642. r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
  643. r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
  644. return r;
  645. }
  646. double log1p(double x) NOEXCEPT
  647. {
  648. return log(1 + x);
  649. }
  650. double acosh(double x) NOEXCEPT
  651. {
  652. return log(x + sqrt(x * x - 1));
  653. }
  654. double asinh(double x) NOEXCEPT
  655. {
  656. return log(x + sqrt(x * x + 1));
  657. }
  658. double atanh(double x) NOEXCEPT
  659. {
  660. return log((1 + x) / (1 - x)) / 2.0;
  661. }
  662. double hypot(double x, double y) NOEXCEPT
  663. {
  664. return sqrt(x * x + y * y);
  665. }
  666. double erf(double x) NOEXCEPT
  667. {
  668. // algorithm taken from Abramowitz and Stegun (no. 26.2.17)
  669. double t = 1 / (1 + 0.47047 * fabs(x));
  670. double poly = t * (0.3480242 + t * (-0.958798 + t * 0.7478556));
  671. double answer = 1 - poly * exp(-x * x);
  672. if (x < 0)
  673. return -answer;
  674. return answer;
  675. }
  676. double erfc(double x) NOEXCEPT
  677. {
  678. return 1 - erf(x);
  679. }
  680. double nextafter(double x, double target) NOEXCEPT
  681. {
  682. if (x == target)
  683. return target;
  684. return internal_nextafter(x, target >= x);
  685. }
  686. float nextafterf(float x, float target) NOEXCEPT
  687. {
  688. if (x == target)
  689. return target;
  690. return internal_nextafter(x, target >= x);
  691. }
  692. long double nextafterl(long double, long double) NOEXCEPT
  693. {
  694. TODO();
  695. }
  696. double nexttoward(double x, long double target) NOEXCEPT
  697. {
  698. if (x == target)
  699. return target;
  700. return internal_nextafter(x, target >= x);
  701. }
  702. float nexttowardf(float x, long double target) NOEXCEPT
  703. {
  704. if (x == target)
  705. return target;
  706. return internal_nextafter(x, target >= x);
  707. }
  708. long double nexttowardl(long double, long double) NOEXCEPT
  709. {
  710. TODO();
  711. }
  712. double copysign(double x, double y)
  713. {
  714. using Extractor = FloatExtractor<decltype(x)>;
  715. Extractor ex, ey;
  716. ex.d = x;
  717. ey.d = y;
  718. ex.sign = ey.sign;
  719. return ex.d;
  720. }
  721. }