diff options
author | Joseph Myers <joseph@codesourcery.com> | 2012-03-16 20:05:04 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2012-03-16 20:05:37 +0000 |
commit | 11b90b9f504df5b2da91ce3a06c1657d99e4a95f (patch) | |
tree | 838df025f383c47096e24ac377aa45d48d9200b7 /sysdeps | |
parent | 6a1bd2a100c958d30bbfe8c9b8f9071d24b7c3f4 (diff) | |
download | glibc-11b90b9f504df5b2da91ce3a06c1657d99e4a95f.tar glibc-11b90b9f504df5b2da91ce3a06c1657d99e4a95f.tar.gz glibc-11b90b9f504df5b2da91ce3a06c1657d99e4a95f.tar.bz2 glibc-11b90b9f504df5b2da91ce3a06c1657d99e4a95f.zip |
Fix tan, tanl for large inputs.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/i386/fpu/libm-test-ulps | 20 | ||||
-rw-r--r-- | sysdeps/i386/fpu/mptan.c | 1 | ||||
-rw-r--r-- | sysdeps/i386/fpu/s_tan.S | 55 | ||||
-rw-r--r-- | sysdeps/i386/fpu/s_tanl.S | 55 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/s_tan.c | 4 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-96/k_tanl.c | 137 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-96/s_tanl.c | 11 | ||||
-rw-r--r-- | sysdeps/x86_64/fpu/k_tanl.c | 1 | ||||
-rw-r--r-- | sysdeps/x86_64/fpu/libm-test-ulps | 28 | ||||
-rw-r--r-- | sysdeps/x86_64/fpu/s_tanl.S | 45 |
10 files changed, 193 insertions, 164 deletions
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps index 6f090e1417..d83b2339ca 100644 --- a/sysdeps/i386/fpu/libm-test-ulps +++ b/sysdeps/i386/fpu/libm-test-ulps @@ -1539,6 +1539,12 @@ idouble: 1 ldouble: 7 # tan +Test "tan (0x1p16383) == 0.422722393732022337800504160054440141575": +ildouble: 1 +ldouble: 1 +Test "tan (1e22) == -1.628778225606898878549375936939548513545": +ildouble: 1 +ldouble: 1 Test "tan (pi/4) == 1": double: 1 float: 1 @@ -1551,9 +1557,13 @@ double: 1 float: 2 idouble: 1 ifloat: 2 +ildouble: 1 +ldouble: 1 Test "tan_downward (10) == 0.6483608274590866712591249330098086768169": float: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "tan_downward (2) == -2.1850398632615189916433061023136825434320": double: 1 float: 1 @@ -1614,9 +1624,13 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "tan_towardzero (10) == 0.6483608274590866712591249330098086768169": float: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "tan_towardzero (2) == -2.1850398632615189916433061023136825434320": ildouble: 1 ldouble: 1 @@ -1681,8 +1695,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 -ildouble: 1 -ldouble: 1 +ildouble: 2 +ldouble: 2 Test "tan_upward (6) == -0.2910061913847491570536995888681755428312": ildouble: 1 ldouble: 1 @@ -2366,6 +2380,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Function: "tan_downward": double: 1 diff --git a/sysdeps/i386/fpu/mptan.c b/sysdeps/i386/fpu/mptan.c deleted file mode 100644 index 1cc8931700..0000000000 --- a/sysdeps/i386/fpu/mptan.c +++ /dev/null @@ -1 +0,0 @@ -/* Not needed. */ diff --git a/sysdeps/i386/fpu/s_tan.S b/sysdeps/i386/fpu/s_tan.S deleted file mode 100644 index b35bb835de..0000000000 --- a/sysdeps/i386/fpu/s_tan.S +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Written by J.T. Conklin <jtc@netbsd.org>. - * Fixed errno handling by Ulrich Drepper <drepper@redhat.com>. - * Public domain. - */ - -#define __need_Emath -#include <bits/errno.h> -#include <machine/asm.h> - -RCSID("$NetBSD: s_tan.S,v 1.5 1995/05/09 00:30:00 jtc Exp $") - -ENTRY(__tan) - fldl 4(%esp) - fxam - fstsw %ax - movb $0x45, %dh - andb %ah, %dh - cmpb $0x05, %dh - je 3f -4: fptan - fnstsw %ax - testl $0x400,%eax - jnz 1f - fstp %st(0) - ret -1: fldpi - fadd %st(0) - fxch %st(1) -2: fprem1 - fstsw %ax - testl $0x400,%eax - jnz 2b - fstp %st(1) - fptan - fstp %st(0) - ret -3: -#ifdef PIC - pushl %ebx - cfi_adjust_cfa_offset (4) - cfi_rel_offset (ebx, 0) - LOAD_PIC_REG (bx) - call __errno_location@PLT - movl $EDOM, (%eax) - popl %ebx - cfi_adjust_cfa_offset (-4) - cfi_restore (ebx) -#else - call __errno_location@PLT - movl $EDOM, (%eax) -#endif - jmp 4b -END (__tan) -weak_alias (__tan, tan) diff --git a/sysdeps/i386/fpu/s_tanl.S b/sysdeps/i386/fpu/s_tanl.S deleted file mode 100644 index 151b77113f..0000000000 --- a/sysdeps/i386/fpu/s_tanl.S +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Written by J.T. Conklin <jtc@netbsd.org>. - * Public domain. - * - * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. - * Fixed errno handling by Ulrich Drepper <drepper@redhat.com>. - */ - -#define __need_Emath -#include <bits/errno.h> -#include <machine/asm.h> - -ENTRY(__tanl) - fldt 4(%esp) - fxam - fstsw %ax - movb $0x45, %dh - andb %ah, %dh - cmpb $0x05, %dh - je 3f -4: fptan - fnstsw %ax - testl $0x400,%eax - jnz 1f - fstp %st(0) - ret -1: fldpi - fadd %st(0) - fxch %st(1) -2: fprem1 - fstsw %ax - testl $0x400,%eax - jnz 2b - fstp %st(1) - fptan - fstp %st(0) - ret -3: -#ifdef PIC - pushl %ebx - cfi_adjust_cfa_offset (4) - cfi_rel_offset (ebx, 0) - LOAD_PIC_REG (bx) - call __errno_location@PLT - movl $EDOM, (%eax) - popl %ebx - cfi_adjust_cfa_offset (-4) - cfi_restore (ebx) -#else - call __errno_location@PLT - movl $EDOM, (%eax) -#endif - jmp 4b -END (__tanl) -weak_alias (__tanl, tanl) diff --git a/sysdeps/ieee754/dbl-64/s_tan.c b/sysdeps/ieee754/dbl-64/s_tan.c index acff67c987..8eee383933 100644 --- a/sysdeps/ieee754/dbl-64/s_tan.c +++ b/sysdeps/ieee754/dbl-64/s_tan.c @@ -74,7 +74,7 @@ tan(double x) { int __branred(double, double *, double *); int __mpranred(double, mp_no *, int); - libc_feholdexcept_setround (&env, FE_TONEAREST); + libc_feholdexcept_setround_53bit (&env, FE_TONEAREST); /* x=+-INF, x=NaN */ num.d = x; ux = num.i[HIGH_HALF]; @@ -503,7 +503,7 @@ tan(double x) { goto ret; ret: - libc_feupdateenv (&env); + libc_feupdateenv_53bit (&env); return retval; } diff --git a/sysdeps/ieee754/ldbl-96/k_tanl.c b/sysdeps/ieee754/ldbl-96/k_tanl.c new file mode 100644 index 0000000000..31cd236aa2 --- /dev/null +++ b/sysdeps/ieee754/ldbl-96/k_tanl.c @@ -0,0 +1,137 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + Long double expansions are + Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov> + and are incorporated herein by permission of the author. The author + reserves the right to distribute this material elsewhere under different + copying permissions. These modifications are distributed here under + the following terms: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* __kernel_tanl( x, y, k ) + * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input k indicates whether tan (if k=1) or + * -1/tan (if k= -1) is returned. + * + * Algorithm + * 1. Since tan(-x) = -tan(x), we need only to consider positive x. + * 2. if x < 2^-33, return x with inexact if x!=0. + * 3. tan(x) is approximated by a rational form x + x^3 / 3 + x^5 R(x^2) + * on [0,0.67433]. + * + * Note: tan(x+y) = tan(x) + tan'(x)*y + * ~ tan(x) + (1+x*x)*y + * Therefore, for better accuracy in computing tan(x+y), let + * r = x^3 * R(x^2) + * then + * tan(x+y) = x + (x^3 / 3 + (x^2 *(r+y)+y)) + * + * 4. For x in [0.67433,pi/4], let y = pi/4 - x, then + * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) + * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) + */ + +#include <math.h> +#include <math_private.h> +static const long double + one = 1.0L, + pio4hi = 0xc.90fdaa22168c235p-4L, + pio4lo = -0x3.b399d747f23e32ecp-68L, + + /* tan x = x + x^3 / 3 + x^5 T(x^2)/U(x^2) + 0 <= x <= 0.6743316650390625 + Peak relative error 8.0e-36 */ + TH = 3.333333333333333333333333333333333333333E-1L, + T0 = -1.813014711743583437742363284336855889393E7L, + T1 = 1.320767960008972224312740075083259247618E6L, + T2 = -2.626775478255838182468651821863299023956E4L, + T3 = 1.764573356488504935415411383687150199315E2L, + T4 = -3.333267763822178690794678978979803526092E-1L, + + U0 = -1.359761033807687578306772463253710042010E8L, + U1 = 6.494370630656893175666729313065113194784E7L, + U2 = -4.180787672237927475505536849168729386782E6L, + U3 = 8.031643765106170040139966622980914621521E4L, + U4 = -5.323131271912475695157127875560667378597E2L; + /* 1.000000000000000000000000000000000000000E0 */ + + +long double +__kernel_tanl (long double x, long double y, int iy) +{ + long double z, r, v, w, s; + long double absx = fabsl (x); + int sign; + + if (absx < 0x1p-33) + { + if ((int) x == 0) + { /* generate inexact */ + if (x == 0 && iy == -1) + return one / fabsl (x); + else + return (iy == 1) ? x : -one / x; + } + } + if (absx >= 0.6743316650390625L) + { + if (signbit (x)) + { + x = -x; + y = -y; + sign = -1; + } + else + sign = 1; + z = pio4hi - x; + w = pio4lo - y; + x = z + w; + y = 0.0; + } + z = x * x; + r = T0 + z * (T1 + z * (T2 + z * (T3 + z * T4))); + v = U0 + z * (U1 + z * (U2 + z * (U3 + z * (U4 + z)))); + r = r / v; + + s = z * x; + r = y + z * (s * r + y); + r += TH * s; + w = x + r; + if (absx >= 0.6743316650390625L) + { + v = (long double) iy; + w = (v - 2.0 * (x - (w * w / (w + v) - r))); + if (sign < 0) + w = -w; + return w; + } + if (iy == 1) + return w; + else + return -1.0 / (x + r); +} diff --git a/sysdeps/ieee754/ldbl-96/s_tanl.c b/sysdeps/ieee754/ldbl-96/s_tanl.c index 3054601a50..3fbe4a8f6b 100644 --- a/sysdeps/ieee754/ldbl-96/s_tanl.c +++ b/sysdeps/ieee754/ldbl-96/s_tanl.c @@ -48,23 +48,28 @@ static char rcsid[] = "$NetBSD: $"; * TRIG(x) returns trig(x) nearly rounded */ +#include <errno.h> #include <math.h> #include <math_private.h> long double __tanl(long double x) { long double y[2],z=0.0; - int32_t n, se; + int32_t n, se, i0, i1; /* High word of x. */ - GET_LDOUBLE_EXP(se,x); + GET_LDOUBLE_WORDS(se,i0,i1,x); /* |x| ~< pi/4 */ se &= 0x7fff; if(se <= 0x3ffe) return __kernel_tanl(x,z,1); /* tan(Inf or NaN) is NaN */ - else if (se==0x7fff) return x-x; /* NaN */ + else if (se==0x7fff) { + if (i1 == 0 && i0 == 0x80000000) + __set_errno (EDOM); + return x-x; + } /* argument reduction needed */ else { diff --git a/sysdeps/x86_64/fpu/k_tanl.c b/sysdeps/x86_64/fpu/k_tanl.c deleted file mode 100644 index eea55a98d2..0000000000 --- a/sysdeps/x86_64/fpu/k_tanl.c +++ /dev/null @@ -1 +0,0 @@ -/* Not needed. */ diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps index 9a3fd6f8be..613ae579e9 100644 --- a/sysdeps/x86_64/fpu/libm-test-ulps +++ b/sysdeps/x86_64/fpu/libm-test-ulps @@ -1539,6 +1539,12 @@ ildouble: 7 ldouble: 7 # tan +Test "tan (0x1p16383) == 0.422722393732022337800504160054440141575": +ildouble: 1 +ldouble: 1 +Test "tan (1e22) == -1.628778225606898878549375936939548513545": +ildouble: 1 +ldouble: 1 Test "tan (pi/4) == 1": double: 1 idouble: 1 @@ -1547,12 +1553,19 @@ idouble: 1 Test "tan_downward (1) == 1.5574077246549022305069748074583601730873": float: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "tan_downward (10) == 0.6483608274590866712591249330098086768169": float: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "tan_downward (2) == -2.1850398632615189916433061023136825434320": float: 1 ifloat: 1 +Test "tan_downward (3) == -0.1425465430742778052956354105339134932261": +ildouble: 1 +ldouble: 1 Test "tan_downward (4) == 1.1578212823495775831373424182673239231198": ildouble: 1 ldouble: 1 @@ -1572,6 +1585,12 @@ float: 1 ifloat: 1 # tan_tonearest +Test "tan_tonearest (1) == 1.5574077246549022305069748074583601730873": +ildouble: 1 +ldouble: 1 +Test "tan_tonearest (2) == -2.1850398632615189916433061023136825434320": +ildouble: 1 +ldouble: 1 Test "tan_tonearest (6) == -0.2910061913847491570536995888681755428312": ildouble: 1 ldouble: 1 @@ -1583,9 +1602,14 @@ ildouble: 1 ldouble: 1 # tan_towardzero +Test "tan_towardzero (1) == 1.5574077246549022305069748074583601730873": +ildouble: 1 +ldouble: 1 Test "tan_towardzero (10) == 0.6483608274590866712591249330098086768169": float: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "tan_towardzero (2) == -2.1850398632615189916433061023136825434320": ildouble: 1 ldouble: 1 @@ -1636,6 +1660,8 @@ ldouble: 1 Test "tan_upward (5) == -3.3805150062465856369827058794473439087096": float: 1 ifloat: 1 +ildouble: 2 +ldouble: 2 Test "tan_upward (6) == -0.2910061913847491570536995888681755428312": ildouble: 1 ldouble: 1 @@ -2308,6 +2334,8 @@ ldouble: 27 Function: "tan": double: 1 idouble: 1 +ildouble: 1 +ldouble: 1 Function: "tan_downward": float: 1 diff --git a/sysdeps/x86_64/fpu/s_tanl.S b/sysdeps/x86_64/fpu/s_tanl.S deleted file mode 100644 index 6427e3f6f0..0000000000 --- a/sysdeps/x86_64/fpu/s_tanl.S +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Written by J.T. Conklin <jtc@netbsd.org>. - * Public domain. - * - * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. - * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>. - * Fixed errno handling by Ulrich Drepper <drepper@redhat.com>. - */ - -#define __need_Emath -#include <bits/errno.h> -#include <machine/asm.h> - -RCSID("$NetBSD: $") - -ENTRY(__tanl) - fldt 8(%rsp) - fxam - fstsw %ax - movb $0x45, %dh - andb %ah, %dh - cmpb $0x05, %dh - je 3f -4: fptan - fnstsw %ax - testl $0x400,%eax - jnz 1f - fstp %st(0) - ret -1: fldpi - fadd %st(0) - fxch %st(1) -2: fprem1 - fstsw %ax - testl $0x400,%eax - jnz 2b - fstp %st(1) - fptan - fstp %st(0) - ret -3: call __errno_location@PLT - movl $EDOM, (%rax) - jmp 4b -END (__tanl) -weak_alias (__tanl, tanl) |