Serenity Operating System
at master 1155 lines 26 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2021, Mițca Dumitru <dumitru0mitca@gmail.com> 4 * Copyright (c) 2022, the SerenityOS developers. 5 * Copyright (c) 2022, Leon Albrecht <leon.a@serenityos.org> 6 * 7 * SPDX-License-Identifier: BSD-2-Clause 8 */ 9 10#include <AK/BuiltinWrappers.h> 11#include <AK/ExtraMathConstants.h> 12#include <AK/FloatingPoint.h> 13#ifndef AK_ARCH_AARCH64 14# include <AK/FPControl.h> 15#endif 16#include <AK/Math.h> 17#include <AK/Platform.h> 18#include <AK/StdLibExtras.h> 19#include <assert.h> 20#include <fenv.h> 21#include <math.h> 22#include <stdint.h> 23 24#if defined(AK_COMPILER_CLANG) 25# pragma clang diagnostic push 26# pragma clang diagnostic ignored "-Wdouble-promotion" 27#endif 28 29template<size_t> 30constexpr double e_to_power(); 31template<> 32constexpr double e_to_power<0>() { return 1; } 33template<size_t exponent> 34constexpr double e_to_power() { return M_E * e_to_power<exponent - 1>(); } 35 36template<size_t> 37constexpr size_t factorial(); 38template<> 39constexpr size_t factorial<0>() { return 1; } 40template<size_t value> 41constexpr size_t factorial() { return value * factorial<value - 1>(); } 42 43template<size_t> 44constexpr size_t product_even(); 45template<> 46constexpr size_t product_even<2>() { return 2; } 47template<size_t value> 48constexpr size_t product_even() { return value * product_even<value - 2>(); } 49 50template<size_t> 51constexpr size_t product_odd(); 52template<> 53constexpr size_t product_odd<1>() { return 1; } 54template<size_t value> 55constexpr size_t product_odd() { return value * product_odd<value - 2>(); } 56 57enum class RoundingMode { 58 ToZero = FE_TOWARDZERO, 59 Up = FE_UPWARD, 60 Down = FE_DOWNWARD, 61 ToEven = FE_TONEAREST 62}; 63 64// This is much branchier than it really needs to be 65template<typename FloatType> 66static FloatType internal_to_integer(FloatType x, RoundingMode rounding_mode) 67{ 68 if (!isfinite(x)) 69 return x; 70 71 using Extractor = FloatExtractor<decltype(x)>; 72 Extractor extractor; 73 extractor.d = x; 74 75 auto unbiased_exponent = extractor.exponent - Extractor::exponent_bias; 76 77 bool has_half_fraction = false; 78 bool has_nonhalf_fraction = false; 79 if (unbiased_exponent < 0) { 80 // it was easier to special case [0..1) as it saves us from 81 // handling subnormals, underflows, etc 82 if (unbiased_exponent == -1) { 83 has_half_fraction = true; 84 } 85 86 has_nonhalf_fraction = unbiased_exponent < -1 || extractor.mantissa != 0; 87 extractor.mantissa = 0; 88 extractor.exponent = 0; 89 } else { 90 if (unbiased_exponent >= Extractor::mantissa_bits) 91 return x; 92 93 auto dead_bitcount = Extractor::mantissa_bits - unbiased_exponent; 94 auto dead_mask = (1ull << dead_bitcount) - 1; 95 auto dead_bits = extractor.mantissa & dead_mask; 96 extractor.mantissa &= ~dead_mask; 97 98 auto nonhalf_fraction_mask = dead_mask >> 1; 99 has_nonhalf_fraction = (dead_bits & nonhalf_fraction_mask) != 0; 100 has_half_fraction = (dead_bits & ~nonhalf_fraction_mask) != 0; 101 } 102 103 bool should_round = false; 104 switch (rounding_mode) { 105 case RoundingMode::ToEven: 106 should_round = has_half_fraction; 107 break; 108 case RoundingMode::Up: 109 if (!extractor.sign) 110 should_round = has_nonhalf_fraction || has_half_fraction; 111 break; 112 case RoundingMode::Down: 113 if (extractor.sign) 114 should_round = has_nonhalf_fraction || has_half_fraction; 115 break; 116 case RoundingMode::ToZero: 117 break; 118 } 119 120 if (should_round) { 121 // We could do this ourselves, but this saves us from manually 122 // handling overflow. 123 if (extractor.sign) 124 extractor.d -= static_cast<FloatType>(1.0); 125 else 126 extractor.d += static_cast<FloatType>(1.0); 127 } 128 129 return extractor.d; 130} 131 132// This is much branchier than it really needs to be 133template<typename FloatType> 134static FloatType internal_nextafter(FloatType x, bool up) 135{ 136 if (!isfinite(x)) 137 return x; 138 using Extractor = FloatExtractor<decltype(x)>; 139 Extractor extractor; 140 extractor.d = x; 141 if (x == 0) { 142 if (!extractor.sign) { 143 extractor.mantissa = 1; 144 extractor.sign = !up; 145 return extractor.d; 146 } 147 if (up) { 148 extractor.sign = false; 149 extractor.mantissa = 1; 150 return extractor.d; 151 } 152 extractor.mantissa = 1; 153 extractor.sign = up != extractor.sign; 154 return extractor.d; 155 } 156 if (up != extractor.sign) { 157 extractor.mantissa++; 158 if (!extractor.mantissa) { 159 // no need to normalize the mantissa as we just hit a power 160 // of two. 161 extractor.exponent++; 162 if (extractor.exponent == Extractor::exponent_max) { 163 extractor.exponent = Extractor::exponent_max - 1; 164 extractor.mantissa = Extractor::mantissa_max; 165 } 166 } 167 return extractor.d; 168 } 169 170 if (!extractor.mantissa) { 171 if (extractor.exponent) { 172 extractor.exponent--; 173 extractor.mantissa = Extractor::mantissa_max; 174 } else { 175 extractor.d = 0; 176 } 177 return extractor.d; 178 } 179 180 extractor.mantissa--; 181 if (extractor.mantissa != Extractor::mantissa_max) 182 return extractor.d; 183 if (extractor.exponent) { 184 extractor.exponent--; 185 // normalize 186 extractor.mantissa <<= 1; 187 } else { 188 if (extractor.sign) { 189 // Negative infinity 190 extractor.mantissa = 0; 191 extractor.exponent = Extractor::exponent_max; 192 } 193 } 194 return extractor.d; 195} 196 197template<typename FloatT> 198static int internal_ilogb(FloatT x) NOEXCEPT 199{ 200 if (x == 0) 201 return FP_ILOGB0; 202 203 if (isnan(x)) 204 return FP_ILOGNAN; 205 206 if (!isfinite(x)) 207 return INT_MAX; 208 209 using Extractor = FloatExtractor<FloatT>; 210 211 Extractor extractor; 212 extractor.d = x; 213 214 return (int)extractor.exponent - Extractor::exponent_bias; 215} 216 217template<typename FloatT> 218static FloatT internal_modf(FloatT x, FloatT* intpart) NOEXCEPT 219{ 220 FloatT integer_part = internal_to_integer(x, RoundingMode::ToZero); 221 *intpart = integer_part; 222 auto fraction = x - integer_part; 223 if (signbit(fraction) != signbit(x)) 224 fraction = -fraction; 225 return fraction; 226} 227 228template<typename FloatT> 229static FloatT internal_scalbn(FloatT x, int exponent) NOEXCEPT 230{ 231 if (x == 0 || !isfinite(x) || isnan(x) || exponent == 0) 232 return x; 233 234 using Extractor = FloatExtractor<FloatT>; 235 Extractor extractor; 236 extractor.d = x; 237 238 if (extractor.exponent != 0) { 239 extractor.exponent = clamp((int)extractor.exponent + exponent, 0, (int)Extractor::exponent_max); 240 return extractor.d; 241 } 242 243 unsigned leading_mantissa_zeroes = extractor.mantissa == 0 ? 32 : count_leading_zeroes(extractor.mantissa); 244 int shift = min((int)leading_mantissa_zeroes, exponent); 245 exponent = max(exponent - shift, 0); 246 247 extractor.exponent <<= shift; 248 extractor.exponent = exponent + 1; 249 250 return extractor.d; 251} 252 253template<typename FloatT> 254static FloatT internal_copysign(FloatT x, FloatT y) NOEXCEPT 255{ 256 using Extractor = FloatExtractor<FloatT>; 257 Extractor ex, ey; 258 ex.d = x; 259 ey.d = y; 260 ex.sign = ey.sign; 261 return ex.d; 262} 263 264template<typename FloatT> 265static FloatT internal_gamma(FloatT x) NOEXCEPT 266{ 267 if (isnan(x)) 268 return (FloatT)NAN; 269 270 if (x == (FloatT)0.0) 271 return signbit(x) ? (FloatT)-INFINITY : (FloatT)INFINITY; 272 273 if (x < (FloatT)0 && (rintl(x) == x || isinf(x))) 274 return (FloatT)NAN; 275 276 if (isinf(x)) 277 return (FloatT)INFINITY; 278 279 using Extractor = FloatExtractor<FloatT>; 280 // These constants were obtained through use of WolframAlpha 281 constexpr long long max_integer_whose_factorial_fits = (Extractor::mantissa_bits == FloatExtractor<long double>::mantissa_bits ? 20 : (Extractor::mantissa_bits == FloatExtractor<double>::mantissa_bits ? 18 : (Extractor::mantissa_bits == FloatExtractor<float>::mantissa_bits ? 10 : 0))); 282 static_assert(max_integer_whose_factorial_fits != 0, "internal_gamma needs to be aware of the integer factorial that fits in this floating point type."); 283 if ((int)x == x && x <= max_integer_whose_factorial_fits + 1) { 284 long long result = 1; 285 for (long long cursor = 2; cursor < (long long)x; cursor++) 286 result *= cursor; 287 return (FloatT)result; 288 } 289 290 // Stirling approximation 291 return sqrtl(2.0 * M_PIl / static_cast<long double>(x)) * powl(static_cast<long double>(x) / M_El, static_cast<long double>(x)); 292} 293 294extern "C" { 295 296float nanf(char const* s) NOEXCEPT 297{ 298 return __builtin_nanf(s); 299} 300 301double nan(char const* s) NOEXCEPT 302{ 303 return __builtin_nan(s); 304} 305 306long double nanl(char const* s) NOEXCEPT 307{ 308 return __builtin_nanl(s); 309} 310 311#define MAKE_AK_BACKED1(name) \ 312 long double name##l(long double arg) NOEXCEPT \ 313 { \ 314 return AK::name<long double>(arg); \ 315 } \ 316 double name(double arg) NOEXCEPT \ 317 { \ 318 return AK::name<double>(arg); \ 319 } \ 320 float name##f(float arg) NOEXCEPT \ 321 { \ 322 return AK::name<float>(arg); \ 323 } 324#define MAKE_AK_BACKED2(name) \ 325 long double name##l(long double arg1, long double arg2) NOEXCEPT \ 326 { \ 327 return AK::name<long double>(arg1, arg2); \ 328 } \ 329 double name(double arg1, double arg2) NOEXCEPT \ 330 { \ 331 return AK::name<double>(arg1, arg2); \ 332 } \ 333 float name##f(float arg1, float arg2) NOEXCEPT \ 334 { \ 335 return AK::name<float>(arg1, arg2); \ 336 } 337 338MAKE_AK_BACKED1(sin); 339MAKE_AK_BACKED1(cos); 340MAKE_AK_BACKED1(tan); 341MAKE_AK_BACKED1(asin); 342MAKE_AK_BACKED1(acos); 343MAKE_AK_BACKED1(atan); 344MAKE_AK_BACKED1(sinh); 345MAKE_AK_BACKED1(cosh); 346MAKE_AK_BACKED1(tanh); 347MAKE_AK_BACKED1(asinh); 348MAKE_AK_BACKED1(acosh); 349MAKE_AK_BACKED1(atanh); 350MAKE_AK_BACKED1(sqrt); 351MAKE_AK_BACKED1(cbrt); 352MAKE_AK_BACKED1(log); 353MAKE_AK_BACKED1(log2); 354MAKE_AK_BACKED1(log10); 355MAKE_AK_BACKED1(exp); 356MAKE_AK_BACKED1(exp2); 357MAKE_AK_BACKED1(fabs); 358 359MAKE_AK_BACKED2(atan2); 360MAKE_AK_BACKED2(hypot); 361MAKE_AK_BACKED2(fmod); 362MAKE_AK_BACKED2(pow); 363MAKE_AK_BACKED2(remainder); 364 365long double truncl(long double x) NOEXCEPT 366{ 367#ifndef AK_ARCH_AARCH64 368 if (fabsl(x) < LONG_LONG_MAX) { 369 // This is 1.6 times faster than the implementation using the "internal_to_integer" 370 // helper (on x86_64) 371 // https://quick-bench.com/q/xBmxuY8am9qibSYVna90Y6PIvqA 372 u64 temp; 373 asm( 374 "fisttpq %[temp]\n" 375 "fildq %[temp]" 376 : "+t"(x) 377 : [temp] "m"(temp)); 378 return x; 379 } 380#endif 381 382 return internal_to_integer(x, RoundingMode::ToZero); 383} 384 385double trunc(double x) NOEXCEPT 386{ 387#ifndef AK_ARCH_AARCH64 388 if (fabs(x) < LONG_LONG_MAX) { 389 u64 temp; 390 asm( 391 "fisttpq %[temp]\n" 392 "fildq %[temp]" 393 : "+t"(x) 394 : [temp] "m"(temp)); 395 return x; 396 } 397#endif 398 399 return internal_to_integer(x, RoundingMode::ToZero); 400} 401 402float truncf(float x) NOEXCEPT 403{ 404#ifndef AK_ARCH_AARCH64 405 if (fabsf(x) < LONG_LONG_MAX) { 406 u64 temp; 407 asm( 408 "fisttpq %[temp]\n" 409 "fildq %[temp]" 410 : "+t"(x) 411 : [temp] "m"(temp)); 412 return x; 413 } 414#endif 415 416 return internal_to_integer(x, RoundingMode::ToZero); 417} 418 419long double rintl(long double value) 420{ 421#ifdef AK_ARCH_AARCH64 422 (void)value; 423 TODO_AARCH64(); 424#else 425 long double res; 426 asm( 427 "frndint\n" 428 : "=t"(res) 429 : "0"(value)); 430 return res; 431#endif 432} 433double rint(double value) 434{ 435#ifdef AK_ARCH_AARCH64 436 (void)value; 437 TODO_AARCH64(); 438#else 439 double res; 440 asm( 441 "frndint\n" 442 : "=t"(res) 443 : "0"(value)); 444 return res; 445#endif 446} 447float rintf(float value) 448{ 449#ifdef AK_ARCH_AARCH64 450 (void)value; 451 TODO_AARCH64(); 452#else 453 float res; 454 asm( 455 "frndint\n" 456 : "=t"(res) 457 : "0"(value)); 458 return res; 459#endif 460} 461 462long lrintl(long double value) 463{ 464#ifdef AK_ARCH_AARCH64 465 (void)value; 466 TODO_AARCH64(); 467#else 468 long res; 469 asm( 470 "fistpl %0\n" 471 : "+m"(res) 472 : "t"(value) 473 : "st"); 474 return res; 475#endif 476} 477long lrint(double value) 478{ 479#ifdef AK_ARCH_AARCH64 480 (void)value; 481 TODO_AARCH64(); 482#else 483 long res; 484 asm( 485 "fistpl %0\n" 486 : "+m"(res) 487 : "t"(value) 488 : "st"); 489 return res; 490#endif 491} 492long lrintf(float value) 493{ 494#ifdef AK_ARCH_AARCH64 495 (void)value; 496 TODO_AARCH64(); 497#else 498 long res; 499 asm( 500 "fistpl %0\n" 501 : "+m"(res) 502 : "t"(value) 503 : "st"); 504 return res; 505#endif 506} 507 508long long llrintl(long double value) 509{ 510#ifdef AK_ARCH_AARCH64 511 (void)value; 512 TODO_AARCH64(); 513#else 514 long long res; 515 asm( 516 "fistpq %0\n" 517 : "+m"(res) 518 : "t"(value) 519 : "st"); 520 return res; 521#endif 522} 523long long llrint(double value) 524{ 525#ifdef AK_ARCH_AARCH64 526 (void)value; 527 TODO_AARCH64(); 528#else 529 long long res; 530 asm( 531 "fistpq %0\n" 532 : "+m"(res) 533 : "t"(value) 534 : "st"); 535 return res; 536#endif 537} 538long long llrintf(float value) 539{ 540#ifdef AK_ARCH_AARCH64 541 (void)value; 542 TODO_AARCH64(); 543#else 544 long long res; 545 asm( 546 "fistpq %0\n" 547 : "+m"(res) 548 : "t"(value) 549 : "st"); 550 return res; 551#endif 552} 553 554// On systems where FLT_RADIX == 2, ldexp is equivalent to scalbn 555long double ldexpl(long double x, int exp) NOEXCEPT 556{ 557 return internal_scalbn(x, exp); 558} 559 560double ldexp(double x, int exp) NOEXCEPT 561{ 562 return internal_scalbn(x, exp); 563} 564 565float ldexpf(float x, int exp) NOEXCEPT 566{ 567 return internal_scalbn(x, exp); 568} 569 570[[maybe_unused]] static long double ampsin(long double angle) NOEXCEPT 571{ 572 long double looped_angle = fmodl(M_PI + angle, M_TAU) - M_PI; 573 long double looped_angle_squared = looped_angle * looped_angle; 574 575 long double quadratic_term; 576 if (looped_angle > 0) { 577 quadratic_term = -looped_angle_squared; 578 } else { 579 quadratic_term = looped_angle_squared; 580 } 581 582 long double linear_term = M_PI * looped_angle; 583 584 return quadratic_term + linear_term; 585} 586 587int ilogbl(long double x) NOEXCEPT 588{ 589 return internal_ilogb(x); 590} 591 592int ilogb(double x) NOEXCEPT 593{ 594 return internal_ilogb(x); 595} 596 597int ilogbf(float x) NOEXCEPT 598{ 599 return internal_ilogb(x); 600} 601 602long double logbl(long double x) NOEXCEPT 603{ 604 return ilogbl(x); 605} 606 607double logb(double x) NOEXCEPT 608{ 609 return ilogb(x); 610} 611 612float logbf(float x) NOEXCEPT 613{ 614 return ilogbf(x); 615} 616 617double frexp(double x, int* exp) NOEXCEPT 618{ 619 *exp = (x == 0) ? 0 : (1 + ilogb(x)); 620 return scalbn(x, -(*exp)); 621} 622 623float frexpf(float x, int* exp) NOEXCEPT 624{ 625 *exp = (x == 0) ? 0 : (1 + ilogbf(x)); 626 return scalbnf(x, -(*exp)); 627} 628 629long double frexpl(long double x, int* exp) NOEXCEPT 630{ 631 *exp = (x == 0) ? 0 : (1 + ilogbl(x)); 632 return scalbnl(x, -(*exp)); 633} 634 635#if !(ARCH(X86_64)) 636 637double round(double value) NOEXCEPT 638{ 639 return internal_to_integer(value, RoundingMode::ToEven); 640} 641 642float roundf(float value) NOEXCEPT 643{ 644 return internal_to_integer(value, RoundingMode::ToEven); 645} 646 647long double roundl(long double value) NOEXCEPT 648{ 649 return internal_to_integer(value, RoundingMode::ToEven); 650} 651 652long lroundf(float value) NOEXCEPT 653{ 654 return internal_to_integer(value, RoundingMode::ToEven); 655} 656 657long lround(double value) NOEXCEPT 658{ 659 return internal_to_integer(value, RoundingMode::ToEven); 660} 661 662long lroundl(long double value) NOEXCEPT 663{ 664 return internal_to_integer(value, RoundingMode::ToEven); 665} 666 667long long llroundf(float value) NOEXCEPT 668{ 669 return internal_to_integer(value, RoundingMode::ToEven); 670} 671 672long long llround(double value) NOEXCEPT 673{ 674 return internal_to_integer(value, RoundingMode::ToEven); 675} 676 677long long llroundd(long double value) NOEXCEPT 678{ 679 return internal_to_integer(value, RoundingMode::ToEven); 680} 681 682float floorf(float value) NOEXCEPT 683{ 684 return internal_to_integer(value, RoundingMode::Down); 685} 686 687double floor(double value) NOEXCEPT 688{ 689 return internal_to_integer(value, RoundingMode::Down); 690} 691 692long double floorl(long double value) NOEXCEPT 693{ 694 return internal_to_integer(value, RoundingMode::Down); 695} 696 697float ceilf(float value) NOEXCEPT 698{ 699 return internal_to_integer(value, RoundingMode::Up); 700} 701 702double ceil(double value) NOEXCEPT 703{ 704 return internal_to_integer(value, RoundingMode::Up); 705} 706 707long double ceill(long double value) NOEXCEPT 708{ 709 return internal_to_integer(value, RoundingMode::Up); 710} 711 712#else 713 714double round(double x) NOEXCEPT 715{ 716 // Note: This is break-tie-away-from-zero, so not the hw's understanding of 717 // "nearest", which would be towards even. 718 if (x == 0.) 719 return x; 720 if (x > 0.) 721 return floor(x + .5); 722 return ceil(x - .5); 723} 724 725float roundf(float x) NOEXCEPT 726{ 727 if (x == 0.f) 728 return x; 729 if (x > 0.f) 730 return floorf(x + .5f); 731 return ceilf(x - .5f); 732} 733 734long double roundl(long double x) NOEXCEPT 735{ 736 if (x == 0.L) 737 return x; 738 if (x > 0.L) 739 return floorl(x + .5L); 740 return ceill(x - .5L); 741} 742 743long lroundf(float value) NOEXCEPT 744{ 745 return static_cast<long>(roundf(value)); 746} 747 748long lround(double value) NOEXCEPT 749{ 750 return static_cast<long>(round(value)); 751} 752 753long lroundl(long double value) NOEXCEPT 754{ 755 return static_cast<long>(roundl(value)); 756} 757 758long long llroundf(float value) NOEXCEPT 759{ 760 return static_cast<long long>(roundf(value)); 761} 762 763long long llround(double value) NOEXCEPT 764{ 765 return static_cast<long long>(round(value)); 766} 767 768long long llroundd(long double value) NOEXCEPT 769{ 770 return static_cast<long long>(roundl(value)); 771} 772 773float floorf(float value) NOEXCEPT 774{ 775 AK::X87RoundingModeScope scope { AK::RoundingMode::DOWN }; 776 asm("frndint" 777 : "+t"(value)); 778 return value; 779} 780 781double floor(double value) NOEXCEPT 782{ 783 AK::X87RoundingModeScope scope { AK::RoundingMode::DOWN }; 784 asm("frndint" 785 : "+t"(value)); 786 return value; 787} 788 789long double floorl(long double value) NOEXCEPT 790{ 791 AK::X87RoundingModeScope scope { AK::RoundingMode::DOWN }; 792 asm("frndint" 793 : "+t"(value)); 794 return value; 795} 796 797float ceilf(float value) NOEXCEPT 798{ 799 AK::X87RoundingModeScope scope { AK::RoundingMode::UP }; 800 asm("frndint" 801 : "+t"(value)); 802 return value; 803} 804 805double ceil(double value) NOEXCEPT 806{ 807 AK::X87RoundingModeScope scope { AK::RoundingMode::UP }; 808 asm("frndint" 809 : "+t"(value)); 810 return value; 811} 812 813long double ceill(long double value) NOEXCEPT 814{ 815 AK::X87RoundingModeScope scope { AK::RoundingMode::UP }; 816 asm("frndint" 817 : "+t"(value)); 818 return value; 819} 820 821#endif 822 823long double modfl(long double x, long double* intpart) NOEXCEPT 824{ 825 return internal_modf(x, intpart); 826} 827 828double modf(double x, double* intpart) NOEXCEPT 829{ 830 return internal_modf(x, intpart); 831} 832 833float modff(float x, float* intpart) NOEXCEPT 834{ 835 return internal_modf(x, intpart); 836} 837 838double gamma(double x) NOEXCEPT 839{ 840 // Stirling approximation 841 return sqrt(2.0 * M_PI / x) * pow(x / M_E, x); 842} 843 844long double tgammal(long double value) NOEXCEPT 845{ 846 return internal_gamma(value); 847} 848 849double tgamma(double value) NOEXCEPT 850{ 851 return internal_gamma(value); 852} 853 854float tgammaf(float value) NOEXCEPT 855{ 856 return internal_gamma(value); 857} 858 859int signgam = 0; 860 861long double lgammal(long double value) NOEXCEPT 862{ 863 return lgammal_r(value, &signgam); 864} 865 866double lgamma(double value) NOEXCEPT 867{ 868 return lgamma_r(value, &signgam); 869} 870 871float lgammaf(float value) NOEXCEPT 872{ 873 return lgammaf_r(value, &signgam); 874} 875 876long double lgammal_r(long double value, int* sign) NOEXCEPT 877{ 878 if (value == 1.0 || value == 2.0) 879 return 0.0; 880 if (isinf(value) || value == 0.0) 881 return INFINITY; 882 long double result = logl(internal_gamma(value)); 883 *sign = signbit(result) ? -1 : 1; 884 return result; 885} 886 887double lgamma_r(double value, int* sign) NOEXCEPT 888{ 889 if (value == 1.0 || value == 2.0) 890 return 0.0; 891 if (isinf(value) || value == 0.0) 892 return INFINITY; 893 double result = log(internal_gamma(value)); 894 *sign = signbit(result) ? -1 : 1; 895 return result; 896} 897 898float lgammaf_r(float value, int* sign) NOEXCEPT 899{ 900 if (value == 1.0f || value == 2.0f) 901 return 0.0; 902 if (isinf(value) || value == 0.0f) 903 return INFINITY; 904 float result = logf(internal_gamma(value)); 905 *sign = signbit(result) ? -1 : 1; 906 return result; 907} 908 909long double expm1l(long double x) NOEXCEPT 910{ 911 return expl(x) - 1; 912} 913 914double expm1(double x) NOEXCEPT 915{ 916 return exp(x) - 1; 917} 918 919float expm1f(float x) NOEXCEPT 920{ 921 return expf(x) - 1; 922} 923 924long double log1pl(long double x) NOEXCEPT 925{ 926 return logl(1 + x); 927} 928 929double log1p(double x) NOEXCEPT 930{ 931 return log(1 + x); 932} 933 934float log1pf(float x) NOEXCEPT 935{ 936 return logf(1 + x); 937} 938 939long double erfl(long double x) NOEXCEPT 940{ 941 // algorithm taken from Abramowitz and Stegun (no. 26.2.17) 942 long double t = 1 / (1 + 0.47047l * fabsl(x)); 943 long double poly = t * (0.3480242l + t * (-0.958798l + t * 0.7478556l)); 944 long double answer = 1 - poly * expl(-x * x); 945 if (x < 0) 946 return -answer; 947 948 return answer; 949} 950 951double erf(double x) NOEXCEPT 952{ 953 return (double)erfl(x); 954} 955 956float erff(float x) NOEXCEPT 957{ 958 return (float)erf(x); 959} 960 961long double erfcl(long double x) NOEXCEPT 962{ 963 return 1 - erfl(x); 964} 965 966double erfc(double x) NOEXCEPT 967{ 968 return 1 - erf(x); 969} 970 971float erfcf(float x) NOEXCEPT 972{ 973 return 1 - erff(x); 974} 975 976double nextafter(double x, double target) NOEXCEPT 977{ 978 if (x == target) 979 return target; 980 return internal_nextafter(x, target >= x); 981} 982 983float nextafterf(float x, float target) NOEXCEPT 984{ 985 if (x == target) 986 return target; 987 return internal_nextafter(x, target >= x); 988} 989 990long double nextafterl(long double x, long double target) NOEXCEPT 991{ 992 return internal_nextafter(x, target >= x); 993} 994 995double nexttoward(double x, long double target) NOEXCEPT 996{ 997 if (x == target) 998 return target; 999 return internal_nextafter(x, target >= x); 1000} 1001 1002float nexttowardf(float x, long double target) NOEXCEPT 1003{ 1004 if (x == target) 1005 return target; 1006 return internal_nextafter(x, target >= x); 1007} 1008 1009long double nexttowardl(long double x, long double target) NOEXCEPT 1010{ 1011 if (x == target) 1012 return target; 1013 return internal_nextafter(x, target >= x); 1014} 1015 1016float copysignf(float x, float y) NOEXCEPT 1017{ 1018 return internal_copysign(x, y); 1019} 1020 1021double copysign(double x, double y) NOEXCEPT 1022{ 1023 return internal_copysign(x, y); 1024} 1025 1026long double copysignl(long double x, long double y) NOEXCEPT 1027{ 1028 return internal_copysign(x, y); 1029} 1030 1031float scalbnf(float x, int exponent) NOEXCEPT 1032{ 1033 return internal_scalbn(x, exponent); 1034} 1035 1036double scalbn(double x, int exponent) NOEXCEPT 1037{ 1038 return internal_scalbn(x, exponent); 1039} 1040 1041long double scalbnl(long double x, int exponent) NOEXCEPT 1042{ 1043 return internal_scalbn(x, exponent); 1044} 1045 1046float scalbnlf(float x, long exponent) NOEXCEPT 1047{ 1048 return internal_scalbn(x, exponent); 1049} 1050 1051double scalbln(double x, long exponent) NOEXCEPT 1052{ 1053 return internal_scalbn(x, exponent); 1054} 1055 1056long double scalblnl(long double x, long exponent) NOEXCEPT 1057{ 1058 return internal_scalbn(x, exponent); 1059} 1060 1061long double fmaxl(long double x, long double y) NOEXCEPT 1062{ 1063 if (isnan(x)) 1064 return y; 1065 if (isnan(y)) 1066 return x; 1067 1068 return x > y ? x : y; 1069} 1070 1071double fmax(double x, double y) NOEXCEPT 1072{ 1073 if (isnan(x)) 1074 return y; 1075 if (isnan(y)) 1076 return x; 1077 1078 return x > y ? x : y; 1079} 1080 1081float fmaxf(float x, float y) NOEXCEPT 1082{ 1083 if (isnan(x)) 1084 return y; 1085 if (isnan(y)) 1086 return x; 1087 1088 return x > y ? x : y; 1089} 1090 1091long double fminl(long double x, long double y) NOEXCEPT 1092{ 1093 if (isnan(x)) 1094 return y; 1095 if (isnan(y)) 1096 return x; 1097 1098 return x < y ? x : y; 1099} 1100 1101double fmin(double x, double y) NOEXCEPT 1102{ 1103 if (isnan(x)) 1104 return y; 1105 if (isnan(y)) 1106 return x; 1107 1108 return x < y ? x : y; 1109} 1110 1111float fminf(float x, float y) NOEXCEPT 1112{ 1113 if (isnan(x)) 1114 return y; 1115 if (isnan(y)) 1116 return x; 1117 1118 return x < y ? x : y; 1119} 1120 1121// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fma.html 1122long double fmal(long double x, long double y, long double z) NOEXCEPT 1123{ 1124 return (x * y) + z; 1125} 1126 1127double fma(double x, double y, double z) NOEXCEPT 1128{ 1129 return (x * y) + z; 1130} 1131 1132float fmaf(float x, float y, float z) NOEXCEPT 1133{ 1134 return (x * y) + z; 1135} 1136 1137long double nearbyintl(long double value) NOEXCEPT 1138{ 1139 return internal_to_integer(value, RoundingMode { fegetround() }); 1140} 1141 1142double nearbyint(double value) NOEXCEPT 1143{ 1144 return internal_to_integer(value, RoundingMode { fegetround() }); 1145} 1146 1147float nearbyintf(float value) NOEXCEPT 1148{ 1149 return internal_to_integer(value, RoundingMode { fegetround() }); 1150} 1151} 1152 1153#if defined(AK_COMPILER_CLANG) 1154# pragma clang diagnostic pop 1155#endif