summaryrefslogtreecommitdiff
path: root/src/math/tanl.c
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2013-05-18 12:34:00 +0000
committerSzabolcs Nagy <nsz@port70.net>2013-05-18 12:34:00 +0000
commit1d5ba3bb5a3f55e10db05219638cfcd967d65417 (patch)
tree4cf78f97777619d73e91ba3c1431aadc434b3fe8 /src/math/tanl.c
parent22730d65608db06500cc6e0be4aaec03238f996b (diff)
downloadmusl-1d5ba3bb5a3f55e10db05219638cfcd967d65417.tar.gz
math: tan cleanups
* use unsigned arithmetics on the representation * store arg reduction quotient in unsigned (so n%2 would work like n&1) * use different convention to pass the arg reduction bit to __tan (this argument used to be 1 for even and -1 for odd reduction which meant obscure bithacks, the new n&1 is cleaner) * raise inexact and underflow flags correctly for small x (tanl(x) may still raise spurious underflow for small but normal x) (this exception raising code increases codesize a bit, similar fixes are needed in many other places, it may worth investigating at some point if the inexact and underflow flags are worth raising correctly as this is not strictly required by the standard) * tanf manual reduction optimization is kept for now * tanl code path is cleaned up to follow similar logic to tan and tanf
Diffstat (limited to 'src/math/tanl.c')
-rw-r--r--src/math/tanl.c37
1 files changed, 11 insertions, 26 deletions
diff --git a/src/math/tanl.c b/src/math/tanl.c
index 0194eaf7..3b51e011 100644
--- a/src/math/tanl.c
+++ b/src/math/tanl.c
@@ -41,42 +41,27 @@ long double tanl(long double x)
long double tanl(long double x)
{
union IEEEl2bits z;
- int e0, s;
long double y[2];
- long double hi, lo;
+ unsigned n;
z.e = x;
- s = z.bits.sign;
z.bits.sign = 0;
- /* If x = +-0 or x is subnormal, then tan(x) = x. */
- if (z.bits.exp == 0)
- return x;
-
/* If x = NaN or Inf, then tan(x) = NaN. */
- if (z.bits.exp == 32767)
+ if (z.bits.exp == 0x7fff)
return (x - x) / (x - x);
- /* Optimize the case where x is already within range. */
+ /* |x| < (double)pi/4 */
if (z.e < M_PI_4) {
- hi = __tanl(z.e, 0, 0);
- return s ? -hi : hi;
+ /* x = +-0 or x is subnormal */
+ if (z.bits.exp == 0)
+ /* inexact and underflow if x!=0 */
+ return x + x*0x1p-120f;
+ /* can raise spurious underflow */
+ return __tanl(x, 0, 0);
}
- e0 = __rem_pio2l(x, y);
- hi = y[0];
- lo = y[1];
-
- switch (e0 & 3) {
- case 0:
- case 2:
- hi = __tanl(hi, lo, 0);
- break;
- case 1:
- case 3:
- hi = __tanl(hi, lo, 1);
- break;
- }
- return hi;
+ n = __rem_pio2l(x, y);
+ return __tanl(y[0], y[1], n&1);
}
#endif