mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-10 07:10:06 +00:00
Fix tan, tanl for large inputs.
This commit is contained in:
parent
6a1bd2a100
commit
11b90b9f50
19
ChangeLog
19
ChangeLog
@ -1,3 +1,22 @@
|
||||
2012-03-16 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #13851]
|
||||
[BZ #13854]
|
||||
* sysdeps/ieee754/dbl-64/s_tan.c (tan): Use
|
||||
libc_feholdexcept_setround_53bit and libc_feupdateenv_53bit.
|
||||
* sysdeps/ieee754/ldbl-96/k_tanl.c: New file.
|
||||
* sysdeps/ieee754/ldbl-96/s_tanl.c: Include <errno.h>.
|
||||
(__tanl): Set errno for infinite argument.
|
||||
* sysdeps/i386/fpu/mptan.c: Remove.
|
||||
* sysdeps/i386/fpu/s_tan.S: Likewise.
|
||||
* sysdeps/i386/fpu/s_tanl.S: Likewise.
|
||||
* sysdeps/x86_64/fpu/k_tanl.c: Likewise.
|
||||
* sysdeps/x86_64/fpu/s_tanl.S: Likewise.
|
||||
* math/libm-test.inc (tan_test): Add more tests and enable more
|
||||
tests for double and long double.
|
||||
* sysdeps/i386/fpu/libm-test-ulps: Update.
|
||||
* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
|
||||
|
||||
2012-03-16 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* sysdeps/x86_64/elf/start.S: Include <sysdep.h>.
|
||||
|
2
NEWS
2
NEWS
@ -15,7 +15,7 @@ Version 2.16
|
||||
13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533, 13547, 13551,
|
||||
13552, 13553, 13555, 13559, 13566, 13583, 13618, 13637, 13656, 13658,
|
||||
13673, 13695, 13704, 13706, 13726, 13738, 13786, 13792, 13806, 13840,
|
||||
13841, 13844, 13846, 13851, 13852
|
||||
13841, 13844, 13846, 13851, 13852, 13854
|
||||
|
||||
* ISO C11 support:
|
||||
|
||||
|
@ -6796,11 +6796,16 @@ tan_test (void)
|
||||
TEST_f_f (tan, M_PI_4l, 1);
|
||||
TEST_f_f (tan, 0.75L, 0.931596459944072461165202756573936428L);
|
||||
|
||||
#ifdef TEST_FLOAT
|
||||
/* Enable for double and long double once x86 and x86-64
|
||||
implementations are fixed. */
|
||||
TEST_f_f (tan, 0x1p65, -0.0472364872359047946798414219288370688827L);
|
||||
TEST_f_f (tan, -0x1p65, 0.0472364872359047946798414219288370688827L);
|
||||
|
||||
#ifndef TEST_FLOAT
|
||||
TEST_f_f (tan, 1e22, -1.628778225606898878549375936939548513545L);
|
||||
TEST_f_f (tan, 0x1p1023, -0.6814476476066215012854144040167365190368L);
|
||||
#endif
|
||||
|
||||
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
|
||||
TEST_f_f (tan, 0x1p16383L, 0.422722393732022337800504160054440141575L);
|
||||
#endif
|
||||
|
||||
END (tan);
|
||||
|
@ -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
|
||||
|
@ -1 +0,0 @@
|
||||
/* Not needed. */
|
@ -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)
|
@ -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)
|
@ -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;
|
||||
}
|
||||
|
||||
|
137
sysdeps/ieee754/ldbl-96/k_tanl.c
Normal file
137
sysdeps/ieee754/ldbl-96/k_tanl.c
Normal file
@ -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);
|
||||
}
|
@ -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 {
|
||||
|
@ -1 +0,0 @@
|
||||
/* Not needed. */
|
@ -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
|
||||
|
@ -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)
|
Loading…
Reference in New Issue
Block a user