LibM: Add the gamma family of functions
This commit is contained in:
parent
7aac174bc8
commit
93c554f6bd
Notes:
sideshowbarker
2024-07-18 21:21:39 +09:00
Author: https://github.com/RealKC Commit: https://github.com/SerenityOS/serenity/commit/93c554f6bd5 Pull-request: https://github.com/SerenityOS/serenity/pull/5792
2 changed files with 91 additions and 0 deletions
|
@ -312,6 +312,34 @@ static FloatT internal_copysign(FloatT x, FloatT y) NOEXCEPT
|
|||
return ex.d;
|
||||
}
|
||||
|
||||
template<typename FloatT>
|
||||
static FloatT internal_gamma(FloatT x) NOEXCEPT
|
||||
{
|
||||
if (isnan(x))
|
||||
return (FloatT)NAN;
|
||||
|
||||
if (x < (FloatT)0 && (((long long)x == x) || isinf(x)))
|
||||
return (FloatT)NAN;
|
||||
|
||||
if (isinf(x))
|
||||
return INFINITY;
|
||||
|
||||
using Extractor = FloatExtractor<FloatT>;
|
||||
if ((long long)x == x) {
|
||||
// These constants were obtained through use of WolframAlpha, they are (in order): 20!, 18!, 10!
|
||||
constexpr auto max_factorial_that_fits = (Extractor::mantissa_bits == FloatExtractor<long double>::mantissa_bits ? 2'432'902'008'176'640'000ull : (Extractor::mantissa_bits == FloatExtractor<double>::mantissa_bits ? 6'402'373'705'728'000ull : (Extractor::mantissa_bits == FloatExtractor<float>::mantissa_bits ? 3'628'800ull : 0ull)));
|
||||
static_assert(max_factorial_that_fits != 0, "internal_gamma needs to be aware of the integer factorial that fits in this floating point type.");
|
||||
unsigned long long result = 1;
|
||||
for (; result < max_factorial_that_fits; result++)
|
||||
result *= result + 1;
|
||||
return (FloatT)result;
|
||||
}
|
||||
|
||||
// Approximation taken from: <https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5840229/>
|
||||
// Web archive link: <https://web.archive.org/web/20210314174210/https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5840229/>
|
||||
return sqrtl(M_TAU * x) * powl(x / M_E, x) * powl(x * sinhl(1.0l / x), x / 2.0l) * expl((7.0l / 324.0l) * (1.0l / (powl(x, 3.0l) * (35.0l * powl(x, 2.0l) + 33.0l)))) - 1.0l;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
float nanf(const char* s) NOEXCEPT
|
||||
|
@ -994,6 +1022,59 @@ double gamma(double x) NOEXCEPT
|
|||
return sqrt(2.0 * M_PI / x) * pow(x / M_E, x);
|
||||
}
|
||||
|
||||
long double tgammal(long double value) NOEXCEPT
|
||||
{
|
||||
return internal_gamma(value);
|
||||
}
|
||||
|
||||
double tgamma(double value) NOEXCEPT
|
||||
{
|
||||
return internal_gamma(value);
|
||||
}
|
||||
|
||||
float tgammaf(float value) NOEXCEPT
|
||||
{
|
||||
return internal_gamma(value);
|
||||
}
|
||||
|
||||
int signgam = 0;
|
||||
|
||||
long double lgammal(long double value) NOEXCEPT
|
||||
{
|
||||
return lgammal_r(value, &signgam);
|
||||
}
|
||||
|
||||
double lgamma(double value) NOEXCEPT
|
||||
{
|
||||
return lgamma_r(value, &signgam);
|
||||
}
|
||||
|
||||
float lgammaf(float value) NOEXCEPT
|
||||
{
|
||||
return lgammaf_r(value, &signgam);
|
||||
}
|
||||
|
||||
long double lgammal_r(long double value, int* sign) NOEXCEPT
|
||||
{
|
||||
long double result = logl(internal_gamma(value));
|
||||
*sign = signbit(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
double lgamma_r(double value, int* sign) NOEXCEPT
|
||||
{
|
||||
double result = log(internal_gamma(value));
|
||||
*sign = signbit(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
float lgammaf_r(float value, int* sign) NOEXCEPT
|
||||
{
|
||||
float result = logf(internal_gamma(value));
|
||||
*sign = signbit(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
long double expm1l(long double x) NOEXCEPT
|
||||
{
|
||||
return expl(x) - 1;
|
||||
|
|
|
@ -179,6 +179,16 @@ long double erfcl(long double) NOEXCEPT;
|
|||
double erfc(double) NOEXCEPT;
|
||||
float erfcf(float) NOEXCEPT;
|
||||
double gamma(double) NOEXCEPT;
|
||||
long double tgammal(long double) NOEXCEPT;
|
||||
double tgamma(double) NOEXCEPT;
|
||||
float tgammaf(float) NOEXCEPT;
|
||||
long double lgammal(long double) NOEXCEPT;
|
||||
double lgamma(double) NOEXCEPT;
|
||||
float lgammaf(float) NOEXCEPT;
|
||||
long double lgammal_r(long double, int*) NOEXCEPT;
|
||||
double lgamma_r(double, int*) NOEXCEPT;
|
||||
float lgammaf_r(float, int*) NOEXCEPT;
|
||||
extern int signgam;
|
||||
|
||||
/* Nearest integer floating point operations */
|
||||
long double ceill(long double) NOEXCEPT;
|
||||
|
|
Loading…
Add table
Reference in a new issue