summaryrefslogtreecommitdiff
path: root/src/math
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2012-12-16 20:22:17 +0100
committerSzabolcs Nagy <nsz@port70.net>2012-12-16 20:22:17 +0100
commitd8a7619e371ff0f226200f6316abb46dd1192f3d (patch)
tree3d7f33c730381b1563ce512ac0c1e1204f93e5a4 /src/math
parente42a977fe5dbe48ba45072ab82886e6b5a694487 (diff)
downloadmusl-d8a7619e371ff0f226200f6316abb46dd1192f3d.tar.gz
math: tgammal.c fixes
this is not a full rewrite just fixes to the special case logic: +-0 and non-integer x<INT_MIN inputs incorrectly raised invalid exception and for +-0 the return value was wrong so integer test and odd/even test for negative inputs are changed and a useless overflow test was removed
Diffstat (limited to 'src/math')
-rw-r--r--src/math/tgammal.c51
1 files changed, 23 insertions, 28 deletions
diff --git a/src/math/tgammal.c b/src/math/tgammal.c
index 86782a96..5c1a02a6 100644
--- a/src/math/tgammal.c
+++ b/src/math/tgammal.c
@@ -205,42 +205,36 @@ static long double stirf(long double x)
long double tgammal(long double x)
{
long double p, q, z;
- int i, sign;
- if (isnan(x))
- return NAN;
- if (x == INFINITY)
- return INFINITY;
- if (x == -INFINITY)
- return x - x;
+ if (!isfinite(x))
+ return x + INFINITY;
+
q = fabsl(x);
if (q > 13.0) {
- sign = 1;
- if (q > MAXGAML)
- goto goverf;
if (x < 0.0) {
p = floorl(q);
- if (p == q)
- return (x - x) / (x - x);
- i = p;
- if ((i & 1) == 0)
- sign = -1;
z = q - p;
- if (z > 0.5L) {
- p += 1.0;
- z = q - p;
- }
- z = q * sinl(PIL * z);
- z = fabsl(z) * stirf(q);
- if (z <= PIL/LDBL_MAX) {
-goverf:
- return sign * INFINITY;
+ if (z == 0)
+ return 0 / z;
+ if (q > MAXGAML) {
+ z = 0;
+ } else {
+ if (z > 0.5) {
+ p += 1.0;
+ z = q - p;
+ }
+ z = q * sinl(PIL * z);
+ z = fabsl(z) * stirf(q);
+ z = PIL/z;
}
- z = PIL/z;
+ if (0.5 * p == floorl(q * 0.5))
+ z = -z;
+ } else if (x > MAXGAML) {
+ z = x * 0x1p16383L;
} else {
z = stirf(x);
}
- return sign * z;
+ return z;
}
z = 1.0;
@@ -268,8 +262,9 @@ goverf:
return z;
small:
- if (x == 0.0)
- return (x - x) / (x - x);
+ /* z==1 if x was originally +-0 */
+ if (x == 0 && z != 1)
+ return x / x;
if (x < 0.0) {
x = -x;
q = z / (x * __polevll(x, SN, 8));