mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
AK/Math: Rely on lgamma to implement gamma
Note that the current implementation of lgamma doesn't work for negative values of x. But given that Stirling's approximation is also only defined for positive values of x, this patch don't change anything in that regard.
This commit is contained in:
1 parent
2830bdc9e8
commit
5184c07e01
2 files changed
+8
-6
No files matched your search
+7
-2
@@ -312,8 +312,13 @@ constexpr T tgamma(T x)
|
||||
return static_cast<T>(result);
|
||||
}
|
||||
|
||||
// Stirling approximation
|
||||
return sqrt(2.0 * Pi<T> / x) * pow(x / E<T>, x);
|
||||
// FIXME: We need to implement something custom to get a correctly rounded
|
||||
// gamma function.
|
||||
// In the meantime, relying on lgamma provides acceptable results. For double,
|
||||
// on [0, inf] this has a max ULP of 1449. Forwarding to the same-type functions
|
||||
// isn't enough to get a good precision, CORE-MATH uses double-double approximations
|
||||
// for both exp and lgamma to pull that trick for f64 and x > 4.
|
||||
return exp(lgamma(x));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -323,10 +323,7 @@ TEST_CASE(gamma)
|
||||
EXPECT(isnan(tgamma(-INFINITY)));
|
||||
EXPECT(isnan(tgamma(-5)));
|
||||
|
||||
// TODO: Stirling approximation is not precise for small values.
|
||||
// Eyeballed from the graph on https://en.wikipedia.org/wiki/Stirling%27s_approximation,
|
||||
// we should use another approximation for x < 2.
|
||||
// EXPECT_APPROXIMATE(tgamma(0.5), sqrt(M_PI));
|
||||
EXPECT_APPROXIMATE_WITH_ERROR(tgamma(0.5), sqrt(M_PI), 1e-10);
|
||||
EXPECT_EQ(tgammal(21.0l), 2'432'902'008'176'640'000.0l);
|
||||
EXPECT_EQ(tgamma(19.0), 6'402'373'705'728'000.0);
|
||||
EXPECT_EQ(tgammaf(11.0f), 3628800.0f);
|
||||
|
||||
Reference in new issue
Block a user