* Makefile:

. Hook coshl, sinhl, and tanhl into libm.
  . Create symbolic links for corresponding manpages.
  . While here remove a nearby extraneous space.

* Symbol.map:
* src/math.h:
  . Move coshl, sinhl, and tanhl to their proper locations.

* man/cosh.3:
* man/sinh.3:
* man/tanh.3:
  . Update the manpages.

* src/e_cosh.c:
* src/e_sinh.c:
* src/s_tanh.c:
  . Add weak reference for LBDL_MANT_DIG==53 targets.

* src/imprecise.c:
  . Remove the coshl, sinhl, and tanhl kludge.

* src/e_coshl.c:
  . ld80 and ld128 implementation of coshl().

* src/e_sinhl.c:
  . ld80 and ld128 implementation of sinhl().

* src/s_tanhl.c:
  . ld80 and ld128 implementation of tanhl().

Obtained from:	bde (mostly), das and kargl
This commit is contained in:
Steve Kargl 2013-12-30 01:06:21 +00:00
parent 5f63fbd67f
commit a48e1f224c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=260067
13 changed files with 480 additions and 27 deletions

View File

@ -96,13 +96,14 @@ COMMON_SRCS+= s_copysignl.c s_fabsl.c s_llrintl.c s_lrintl.c s_modfl.c
.if ${LDBL_PREC} != 53 .if ${LDBL_PREC} != 53
# If long double != double use these; otherwise, we alias the double versions. # If long double != double use these; otherwise, we alias the double versions.
COMMON_SRCS+= e_acoshl.c e_acosl.c e_asinl.c e_atan2l.c e_atanhl.c \ COMMON_SRCS+= e_acoshl.c e_acosl.c e_asinl.c e_atan2l.c e_atanhl.c \
e_fmodl.c e_hypotl.c e_remainderl.c e_sqrtl.c \ e_coshl.c e_fmodl.c e_hypotl.c \
e_remainderl.c e_sinhl.c e_sqrtl.c \
invtrig.c k_cosl.c k_sinl.c k_tanl.c \ invtrig.c k_cosl.c k_sinl.c k_tanl.c \
s_asinhl.c s_atanl.c s_cbrtl.c s_ceill.c s_cosl.c s_cprojl.c \ s_asinhl.c s_atanl.c s_cbrtl.c s_ceill.c s_cosl.c s_cprojl.c \
s_csqrtl.c s_exp2l.c s_expl.c s_floorl.c s_fmal.c \ s_csqrtl.c s_exp2l.c s_expl.c s_floorl.c s_fmal.c \
s_frexpl.c s_logbl.c s_logl.c s_nanl.c s_nextafterl.c \ s_frexpl.c s_logbl.c s_logl.c s_nanl.c s_nextafterl.c \
s_nexttoward.c s_remquol.c s_rintl.c s_roundl.c s_scalbnl.c \ s_nexttoward.c s_remquol.c s_rintl.c s_roundl.c s_scalbnl.c \
s_sinl.c s_tanl.c s_truncl.c w_cabsl.c s_sinl.c s_tanhl.c s_tanl.c s_truncl.c w_cabsl.c
.endif .endif
# C99 complex functions # C99 complex functions
@ -160,7 +161,7 @@ MLINKS+=cimag.3 cimagf.3 cimag.3 cimagl.3 \
cimag.3 creal.3 cimag.3 crealf.3 cimag.3 creall.3 cimag.3 creal.3 cimag.3 crealf.3 cimag.3 creall.3
MLINKS+=copysign.3 copysignf.3 copysign.3 copysignl.3 MLINKS+=copysign.3 copysignf.3 copysign.3 copysignl.3
MLINKS+=cos.3 cosf.3 cos.3 cosl.3 MLINKS+=cos.3 cosf.3 cos.3 cosl.3
MLINKS+=cosh.3 coshf.3 MLINKS+=cosh.3 coshf.3 cosh.3 coshl.3
MLINKS+=csqrt.3 csqrtf.3 csqrt.3 csqrtl.3 MLINKS+=csqrt.3 csqrtf.3 csqrt.3 csqrtl.3
MLINKS+=erf.3 erfc.3 erf.3 erff.3 erf.3 erfcf.3 MLINKS+=erf.3 erfc.3 erf.3 erff.3 erf.3 erfcf.3
MLINKS+=exp.3 expm1.3 exp.3 expm1f.3 exp.3 expm1l.3 exp.3 pow.3 exp.3 powf.3 \ MLINKS+=exp.3 expm1.3 exp.3 expm1f.3 exp.3 expm1l.3 exp.3 pow.3 exp.3 powf.3 \
@ -208,11 +209,11 @@ MLINKS+=round.3 roundf.3 round.3 roundl.3
MLINKS+=scalbn.3 scalbln.3 scalbn.3 scalblnf.3 scalbn.3 scalblnl.3 MLINKS+=scalbn.3 scalbln.3 scalbn.3 scalblnf.3 scalbn.3 scalblnl.3
MLINKS+=scalbn.3 scalbnf.3 scalbn.3 scalbnl.3 MLINKS+=scalbn.3 scalbnf.3 scalbn.3 scalbnl.3
MLINKS+=sin.3 sinf.3 sin.3 sinl.3 MLINKS+=sin.3 sinf.3 sin.3 sinl.3
MLINKS+=sinh.3 sinhf.3 MLINKS+=sinh.3 sinhf.3 sinh.3 sinhl.3
MLINKS+=sqrt.3 cbrt.3 sqrt.3 cbrtf.3 sqrt.3 cbrtl.3 sqrt.3 sqrtf.3 \ MLINKS+=sqrt.3 cbrt.3 sqrt.3 cbrtf.3 sqrt.3 cbrtl.3 sqrt.3 sqrtf.3 \
sqrt.3 sqrtl.3 sqrt.3 sqrtl.3
MLINKS+=tan.3 tanf.3 tan.3 tanl.3 MLINKS+=tan.3 tanf.3 tan.3 tanl.3
MLINKS+=tanh.3 tanhf.3 MLINKS+=tanh.3 tanhf.3 tanh.3 tanhl.3
MLINKS+=trunc.3 truncf.3 trunc.3 truncl.3 MLINKS+=trunc.3 truncf.3 trunc.3 truncl.3
.include <bsd.lib.mk> .include <bsd.lib.mk>

View File

@ -260,6 +260,7 @@ FBSD_1.3 {
ccosf; ccosf;
ccosh; ccosh;
ccoshf; ccoshf;
coshl;
ctan; ctan;
ctanf; ctanf;
ctanh; ctanh;
@ -270,13 +271,12 @@ FBSD_1.3 {
log1pl; log1pl;
log2l; log2l;
logl; logl;
sinhl;
tanhl;
/* Implemented as weak aliases for imprecise versions */ /* Implemented as weak aliases for imprecise versions */
coshl;
erfcl; erfcl;
erfl; erfl;
lgammal; lgammal;
powl; powl;
sinhl;
tanhl;
tgammal; tgammal;
}; };

View File

@ -28,12 +28,13 @@
.\" from: @(#)cosh.3 5.1 (Berkeley) 5/2/91 .\" from: @(#)cosh.3 5.1 (Berkeley) 5/2/91
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd January 14, 2005 .Dd August 17, 2013
.Dt COSH 3 .Dt COSH 3
.Os .Os
.Sh NAME .Sh NAME
.Nm cosh , .Nm cosh ,
.Nm coshf .Nm coshf ,
.Nm coshl
.Nd hyperbolic cosine functions .Nd hyperbolic cosine functions
.Sh LIBRARY .Sh LIBRARY
.Lb libm .Lb libm
@ -43,11 +44,14 @@
.Fn cosh "double x" .Fn cosh "double x"
.Ft float .Ft float
.Fn coshf "float x" .Fn coshf "float x"
.Ft long double
.Fn coshl "long double x"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn cosh .Fn cosh ,
.Fn coshf ,
and the and the
.Fn coshf .Fn coshl
functions compute the hyperbolic cosine of functions compute the hyperbolic cosine of
.Fa x . .Fa x .
.Sh SEE ALSO .Sh SEE ALSO

View File

@ -42,11 +42,14 @@
.Fn sinh "double x" .Fn sinh "double x"
.Ft float .Ft float
.Fn sinhf "float x" .Fn sinhf "float x"
.Ft long double
.Fn sinhl "long double x"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn sinh .Fn sinh ,
.Fn sinhf ,
and the and the
.Fn sinhf .Fn sinhl
functions compute the hyperbolic sine of functions compute the hyperbolic sine of
.Fa x . .Fa x .
.Sh SEE ALSO .Sh SEE ALSO

View File

@ -28,12 +28,13 @@
.\" from: @(#)tanh.3 5.1 (Berkeley) 5/2/91 .\" from: @(#)tanh.3 5.1 (Berkeley) 5/2/91
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd May 2, 1991 .Dd August 17, 2013
.Dt TANH 3 .Dt TANH 3
.Os .Os
.Sh NAME .Sh NAME
.Nm tanh , .Nm tanh ,
.Nm tanhf .Nm tanhf ,
.Nm tanhl
.Nd hyperbolic tangent functions .Nd hyperbolic tangent functions
.Sh LIBRARY .Sh LIBRARY
.Lb libm .Lb libm
@ -43,20 +44,24 @@
.Fn tanh "double x" .Fn tanh "double x"
.Ft float .Ft float
.Fn tanhf "float x" .Fn tanhf "float x"
.Ft long double
.Fn tanhl "long double x"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn tanh .Fn tanh ,
.Fn tanhf ,
and the and the
.Fn tanhf .Fn tanhl
functions compute the hyperbolic tangent of functions compute the hyperbolic tangent of
.Fa x . .Fa x .
For a discussion of error due to roundoff, see For a discussion of error due to roundoff, see
.Xr math 3 . .Xr math 3 .
.Sh RETURN VALUES .Sh RETURN VALUES
The The
.Fn tanh .Fn tanh ,
.Fn tanhf ,
and the and the
.Fn tanhf .Fn tanhl
functions return the hyperbolic tangent value. functions return the hyperbolic tangent value.
.Sh SEE ALSO .Sh SEE ALSO
.Xr acos 3 , .Xr acos 3 ,

View File

@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
* only cosh(0)=1 is exact for finite x. * only cosh(0)=1 is exact for finite x.
*/ */
#include <float.h>
#include "math.h" #include "math.h"
#include "math_private.h" #include "math_private.h"
@ -77,3 +79,7 @@ __ieee754_cosh(double x)
/* |x| > overflowthresold, cosh(x) overflow */ /* |x| > overflowthresold, cosh(x) overflow */
return huge*huge; return huge*huge;
} }
#if (LDBL_MANT_DIG == 53)
__weak_reference(cosh, coshl);
#endif

130
lib/msun/src/e_coshl.c Normal file
View File

@ -0,0 +1,130 @@
/* from: FreeBSD: head/lib/msun/src/e_coshl.c XXX */
/*
* ====================================================
* 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.
* ====================================================
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* See e_cosh.c for complete comments.
*
* Converted to long double by Bruce D. Evans.
*/
#include <float.h>
#ifdef __i386__
#include <ieeefp.h>
#endif
#include "fpmath.h"
#include "math.h"
#include "math_private.h"
#include "k_expl.h"
#if LDBL_MAX_EXP != 0x4000
/* We also require the usual expsign encoding. */
#error "Unsupported long double format"
#endif
#define BIAS (LDBL_MAX_EXP - 1)
static const volatile long double huge = 0x1p10000L, tiny = 0x1p-10000L;
#if LDBL_MANT_DIG == 64
/*
* Domain [-1, 1], range ~[-1.8211e-21, 1.8211e-21]:
* |cosh(x) - c(x)| < 2**-68.8
*/
static const union IEEEl2bits
C4u = LD80C(0xaaaaaaaaaaaaac78, -5, 4.16666666666666682297e-2L);
#define C4 C4u.e
static const double
C2 = 0.5,
C6 = 1.3888888888888616e-3, /* 0x16c16c16c16b99.0p-62 */
C8 = 2.4801587301767953e-5, /* 0x1a01a01a027061.0p-68 */
C10 = 2.7557319163300398e-7, /* 0x127e4fb6c9b55f.0p-74 */
C12 = 2.0876768371393075e-9, /* 0x11eed99406a3f4.0p-81 */
C14 = 1.1469537039374480e-11, /* 0x1938c67cd18c48.0p-89 */
C16 = 4.8473490896852041e-14; /* 0x1b49c429701e45.0p-97 */
#elif LDBL_MANT_DIG == 113
/*
* Domain [-1, 1], range ~[-2.3194e-37, 2.3194e-37]:
* |cosh(x) - c(x)| < 2**-121.69
*/
static const long double
C4 = 4.16666666666666666666666666666666225e-2L, /* 0x1555555555555555555555555554e.0p-117L */
C6 = 1.38888888888888888888888888889434831e-3L, /* 0x16c16c16c16c16c16c16c16c1dd7a.0p-122L */
C8 = 2.48015873015873015873015871870962089e-5L, /* 0x1a01a01a01a01a01a01a017af2756.0p-128L */
C10 = 2.75573192239858906525574318600800201e-7L, /* 0x127e4fb7789f5c72ef01c8a040640.0p-134L */
C12 = 2.08767569878680989791444691755468269e-9L, /* 0x11eed8eff8d897b543d0679607399.0p-141L */
C14= 1.14707455977297247387801189650495351e-11L, /* 0x193974a8c07c9d24ae169a7fa9b54.0p-149L */
C16 = 4.77947733238737883626416876486279985e-14L; /* 0x1ae7f3e733b814d4e1b90f5727fe4.0p-157L */
static const double
C2 = 0.5,
C18 = 1.5619206968597871e-16, /* 0x16827863b9900b.0p-105 */
C20 = 4.1103176218528049e-19, /* 0x1e542ba3d3c269.0p-114 */
C22 = 8.8967926401641701e-22, /* 0x10ce399542a014.0p-122 */
C24 = 1.6116681626523904e-24, /* 0x1f2c981d1f0cb7.0p-132 */
C26 = 2.5022374732804632e-27; /* 0x18c7ecf8b2c4a0.0p-141 */
#else
#error "Unsupported long double format"
#endif /* LDBL_MANT_DIG == 64 */
/* log(2**16385 - 0.5) rounded towards up: */
static const float
o_threshold = 1.13572168e4; /* 0xb174de.0p-10 */
long double
coshl(long double x)
{
long double hi,lo,x2,x4;
double dx2;
uint16_t ix;
GET_LDBL_EXPSIGN(ix,x);
ix &= 0x7fff;
/* x is INF or NaN */
if(ix>=0x7fff) return x*x;
ENTERI();
/* |x| < 1, return 1 or c(x) */
if(ix<0x3fff) {
if (ix<BIAS-(LDBL_MANT_DIG+1)/2) /* |x| < TINY */
RETURNI(1+tiny); /* cosh(tiny) = 1(+) with inexact */
x2 = x*x;
#if LDBL_MANT_DIG == 64
x4 = x2*x2;
RETURNI(((C16*x2 + C14)*x4 + (C12*x2 + C10))*(x4*x4*x2) +
((C8*x2 + C6)*x2 + C4)*x4 + C2*x2 + 1);
#elif LDBL_MANT_DIG == 113
dx2 = x2;
RETURNI((((((((((((C26*dx2 + C24)*dx2 + C22)*dx2 +
C20)*x2 + C18)*x2 +
C16)*x2 + C14)*x2 + C12)*x2 + C10)*x2 + C8)*x2 + C6)*x2 +
C4)*(x2*x2) + C2*x2 + 1);
#endif
}
/* |x| in [1, 64), return accurate exp(|x|)/2+1/exp(|x|)/2 */
if (ix < 0x4005) {
k_hexpl(fabsl(x), &hi, &lo);
RETURNI(lo + 0.25/(hi + lo) + hi);
}
/* |x| in [64, o_threshold], return correctly-overflowing exp(|x|)/2 */
if (fabsl(x) <= o_threshold)
RETURNI(hexpl(fabsl(x)));
/* |x| > o_threshold, cosh(x) overflow */
RETURNI(huge*huge);
}

View File

@ -32,6 +32,8 @@ __FBSDID("$FreeBSD$");
* only sinh(0)=0 is exact for finite x. * only sinh(0)=0 is exact for finite x.
*/ */
#include <float.h>
#include "math.h" #include "math.h"
#include "math_private.h" #include "math_private.h"
@ -71,3 +73,7 @@ __ieee754_sinh(double x)
/* |x| > overflowthresold, sinh(x) overflow */ /* |x| > overflowthresold, sinh(x) overflow */
return x*shuge; return x*shuge;
} }
#if (LDBL_MANT_DIG == 53)
__weak_reference(sinh, sinhl);
#endif

131
lib/msun/src/e_sinhl.c Normal file
View File

@ -0,0 +1,131 @@
/* from: FreeBSD: head/lib/msun/src/e_sinhl.c XXX */
/*
* ====================================================
* 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.
* ====================================================
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* See e_sinh.c for complete comments.
*
* Converted to long double by Bruce D. Evans.
*/
#include <float.h>
#ifdef __i386__
#include <ieeefp.h>
#endif
#include "fpmath.h"
#include "math.h"
#include "math_private.h"
#include "k_expl.h"
#if LDBL_MAX_EXP != 0x4000
/* We also require the usual expsign encoding. */
#error "Unsupported long double format"
#endif
#define BIAS (LDBL_MAX_EXP - 1)
static const long double shuge = 0x1p16383L;
#if LDBL_MANT_DIG == 64
/*
* Domain [-1, 1], range ~[-6.6749e-22, 6.6749e-22]:
* |sinh(x)/x - s(x)| < 2**-70.3
*/
static const union IEEEl2bits
S3u = LD80C(0xaaaaaaaaaaaaaaaa, -3, 1.66666666666666666658e-1L);
#define S3 S3u.e
static const double
S5 = 8.3333333333333332e-3, /* 0x11111111111111.0p-59 */
S7 = 1.9841269841270074e-4, /* 0x1a01a01a01a070.0p-65 */
S9 = 2.7557319223873889e-6, /* 0x171de3a5565fe6.0p-71 */
S11 = 2.5052108406704084e-8, /* 0x1ae6456857530f.0p-78 */
S13 = 1.6059042748655297e-10, /* 0x161245fa910697.0p-85 */
S15 = 7.6470006914396920e-13, /* 0x1ae7ce4eff2792.0p-93 */
S17 = 2.8346142308424267e-15; /* 0x19882ce789ffc6.0p-101 */
#elif LDBL_MANT_DIG == 113
/*
* Domain [-1, 1], range ~[-2.9673e-36, 2.9673e-36]:
* |sinh(x)/x - s(x)| < 2**-118.0
*/
static const long double
S3 = 1.66666666666666666666666666666666033e-1L, /* 0x1555555555555555555555555553b.0p-115L */
S5 = 8.33333333333333333333333333337643193e-3L, /* 0x111111111111111111111111180f5.0p-119L */
S7 = 1.98412698412698412698412697391263199e-4L, /* 0x1a01a01a01a01a01a01a0176aad11.0p-125L */
S9 = 2.75573192239858906525574406205464218e-6L, /* 0x171de3a556c7338faac243aaa9592.0p-131L */
S11 = 2.50521083854417187749675637460977997e-8L, /* 0x1ae64567f544e38fe59b3380d7413.0p-138L */
S13 = 1.60590438368216146368737762431552702e-10L, /* 0x16124613a86d098059c7620850fc2.0p-145L */
S15 = 7.64716373181980539786802470969096440e-13L, /* 0x1ae7f3e733b814193af09ce723043.0p-153L */
S17 = 2.81145725434775409870584280722701574e-15L; /* 0x1952c77030c36898c3fd0b6dfc562.0p-161L */
static const double
S19= 8.2206352435411005e-18, /* 0x12f49b4662b86d.0p-109 */
S21= 1.9572943931418891e-20, /* 0x171b8f2fab9628.0p-118 */
S23 = 3.8679983530666939e-23, /* 0x17617002b73afc.0p-127 */
S25 = 6.5067867911512749e-26; /* 0x1423352626048a.0p-136 */
#else
#error "Unsupported long double format"
#endif /* LDBL_MANT_DIG == 64 */
/* log(2**16385 - 0.5) rounded towards up: */
static const float
o_threshold = 1.13572168e4; /* 0xb174de.0p-10 */
long double
sinhl(long double x)
{
long double hi,lo,x2,x4;
double dx2,s;
int16_t ix,jx;
GET_LDBL_EXPSIGN(jx,x);
ix = jx&0x7fff;
/* x is INF or NaN */
if(ix>=0x7fff) return x+x;
ENTERI();
s = 1;
if (jx<0) s = -1;
/* |x| < 64, return x, s(x), or accurate s*(exp(|x|)/2-1/exp(|x|)/2) */
if (ix<0x4005) { /* |x|<64 */
if (ix<BIAS-(LDBL_MANT_DIG+1)/2) /* |x|<TINY */
if(shuge+x>1) RETURNI(x); /* sinh(tiny) = tiny with inexact */
if (ix<0x3fff) { /* |x|<1 */
x2 = x*x;
#if LDBL_MANT_DIG == 64
x4 = x2*x2;
RETURNI(((S17*x2 + S15)*x4 + (S13*x2 + S11))*(x2*x*x4*x4) +
((S9*x2 + S7)*x2 + S5)*(x2*x*x2) + S3*(x2*x) + x);
#elif LDBL_MANT_DIG == 113
dx2 = x2;
RETURNI(((((((((((S25*dx2 + S23)*dx2 +
S21)*x2 + S19)*x2 +
S17)*x2 + S15)*x2 + S13)*x2 + S11)*x2 + S9)*x2 + S7)*x2 +
S5)* (x2*x*x2) +
S3*(x2*x) + x);
#endif
}
k_hexpl(fabsl(x), &hi, &lo);
RETURNI(s*(lo - 0.25/(hi + lo) + hi));
}
/* |x| in [64, o_threshold], return correctly-overflowing s*exp(|x|)/2 */
if (fabsl(x) <= o_threshold)
RETURNI(s*hexpl(fabsl(x)));
/* |x| > o_threshold, sinh(x) overflow */
return x*shuge;
}

View File

@ -60,10 +60,7 @@ DECLARE_WEAK(powl);
long double imprecise_ ## f ## l(long double v) { return f(v); }\ long double imprecise_ ## f ## l(long double v) { return f(v); }\
DECLARE_WEAK(f ## l) DECLARE_WEAK(f ## l)
DECLARE_IMPRECISE(cosh);
DECLARE_IMPRECISE(erfc); DECLARE_IMPRECISE(erfc);
DECLARE_IMPRECISE(erf); DECLARE_IMPRECISE(erf);
DECLARE_IMPRECISE(lgamma); DECLARE_IMPRECISE(lgamma);
DECLARE_IMPRECISE(sinh);
DECLARE_IMPRECISE(tanh);
DECLARE_IMPRECISE(tgamma); DECLARE_IMPRECISE(tgamma);

View File

@ -451,6 +451,7 @@ long double atanl(long double);
long double cbrtl(long double); long double cbrtl(long double);
long double ceill(long double); long double ceill(long double);
long double copysignl(long double, long double) __pure2; long double copysignl(long double, long double) __pure2;
long double coshl(long double);
long double cosl(long double); long double cosl(long double);
long double exp2l(long double); long double exp2l(long double);
long double expl(long double); long double expl(long double);
@ -488,8 +489,10 @@ long double rintl(long double);
long double roundl(long double); long double roundl(long double);
long double scalblnl(long double, long); long double scalblnl(long double, long);
long double scalbnl(long double, int); long double scalbnl(long double, int);
long double sinhl(long double);
long double sinl(long double); long double sinl(long double);
long double sqrtl(long double); long double sqrtl(long double);
long double tanhl(long double);
long double tanl(long double); long double tanl(long double);
long double truncl(long double); long double truncl(long double);
@ -510,13 +513,10 @@ __END_DECLS
*/ */
__BEGIN_DECLS __BEGIN_DECLS
long double coshl(long double);
long double erfcl(long double); long double erfcl(long double);
long double erfl(long double); long double erfl(long double);
long double lgammal(long double); long double lgammal(long double);
long double powl(long double, long double); long double powl(long double, long double);
long double sinhl(long double);
long double tanhl(long double);
long double tgammal(long double); long double tgammal(long double);
__END_DECLS __END_DECLS

View File

@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
* only tanh(0)=0 is exact for finite argument. * only tanh(0)=0 is exact for finite argument.
*/ */
#include <float.h>
#include "math.h" #include "math.h"
#include "math_private.h" #include "math_private.h"
@ -75,3 +77,7 @@ tanh(double x)
} }
return (jx>=0)? z: -z; return (jx>=0)? z: -z;
} }
#if (LDBL_MANT_DIG == 53)
__weak_reference(tanh, tanhl);
#endif

164
lib/msun/src/s_tanhl.c Normal file
View File

@ -0,0 +1,164 @@
/* from: FreeBSD: head/lib/msun/src/s_tanhl.c XXX */
/* @(#)s_tanh.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* See s_tanh.c for complete comments.
*
* Converted to long double by Bruce D. Evans.
*/
#include <float.h>
#ifdef __i386__
#include <ieeefp.h>
#endif
#include "math.h"
#include "math_private.h"
#include "fpmath.h"
#include "k_expl.h"
#if LDBL_MAX_EXP != 0x4000
/* We also require the usual expsign encoding. */
#error "Unsupported long double format"
#endif
#define BIAS (LDBL_MAX_EXP - 1)
static const volatile double tiny = 1.0e-300;
static const double one = 1.0;
#if LDBL_MANT_DIG == 64
/*
* Domain [-0.25, 0.25], range ~[-1.6304e-22, 1.6304e-22]:
* |tanh(x)/x - t(x)| < 2**-72.3
*/
static const union IEEEl2bits
T3u = LD80C(0xaaaaaaaaaaaaaa9f, -2, -3.33333333333333333017e-1L);
#define T3 T3u.e
static const double
T5 = 1.3333333333333314e-1, /* 0x1111111111110a.0p-55 */
T7 = -5.3968253968210485e-2, /* -0x1ba1ba1ba1a1a1.0p-57 */
T9 = 2.1869488531393817e-2, /* 0x1664f488172022.0p-58 */
T11 = -8.8632352345964591e-3, /* -0x1226e34bc138d5.0p-59 */
T13 = 3.5921169709993771e-3, /* 0x1d6d371d3e400f.0p-61 */
T15 = -1.4555786415756001e-3, /* -0x17d923aa63814d.0p-62 */
T17 = 5.8645267876296793e-4, /* 0x13378589b85aa7.0p-63 */
T19 = -2.1121033571392224e-4; /* -0x1baf0af80c4090.0p-65 */
#elif LDBL_MANT_DIG == 113
/*
* Domain [-0.25, 0.25], range ~[-2.4211e-37, 2.4211e-37]:
* |tanh(x)/x - t(x)| < 2**121.6
*/
static const long double
T3 = -3.33333333333333333333333333333332980e-1L, /* -0x1555555555555555555555555554e.0p-114L */
T5 = 1.33333333333333333333333333332707260e-1L, /* 0x1111111111111111111111110ab7b.0p-115L */
T7 = -5.39682539682539682539682535723482314e-2L, /* -0x1ba1ba1ba1ba1ba1ba1ba17b5fc98.0p-117L */
T9 = 2.18694885361552028218693591149061717e-2L, /* 0x1664f4882c10f9f32d6b1a12a25e5.0p-118L */
T11 = -8.86323552990219656883762347736381851e-3L, /* -0x1226e355e6c23c8f5a5a0f386cb4d.0p-119L */
T13 = 3.59212803657248101358314398220822722e-3L, /* 0x1d6d3d0e157ddfb403ad3637442c6.0p-121L */
T15 = -1.45583438705131796512568010348874662e-3L; /* -0x17da36452b75e150c44cc34253b34.0p-122L */
static const double
T17 = 5.9002744094556621e-4, /* 0x1355824803668e.0p-63 */
T19 = -2.3912911424260516e-4, /* -0x1f57d7734c8dde.0p-65 */
T21 = 9.6915379535512898e-5, /* 0x1967e18ad6a6ca.0p-66 */
T23 = -3.9278322983156353e-5, /* -0x1497d8e6b75729.0p-67 */
T25 = 1.5918887220143869e-5, /* 0x10b1319998cafa.0p-68 */
T27 = -6.4514295231630956e-6, /* -0x1b0f2b71b218eb.0p-70 */
T29 = 2.6120754043964365e-6, /* 0x15e963a3cf3a39.0p-71 */
T31 = -1.0407567231003314e-6, /* -0x1176041e656869.0p-72 */
T33 = 3.4744117554063574e-7; /* 0x1750fe732cab9c.0p-74 */
#endif /* LDBL_MANT_DIG == 64 */
static inline long double
divl(long double a, long double b, long double c, long double d,
long double e, long double f)
{
long double inv, r, w;
float fr, fw;
uint32_t hx;
_2sumF(a, c);
b = b + c;
_2sumF(d, f);
e = e + f;
inv = 1 / (d + e);
r = (a + b) * inv;
fr = r;
r = fr;
fw = d + e;
e = d - fw + e;
d = fw;
r = r + (a - d * r + b - e * r) * inv;
return r;
}
long double
tanhl(long double x)
{
long double hi,lo,s,x2,x4,z;
double dx2;
int16_t jx,ix;
GET_LDBL_EXPSIGN(jx,x);
ix = jx&0x7fff;
/* x is INF or NaN */
if(ix>=0x7fff) {
if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */
else return one/x-one; /* tanh(NaN) = NaN */
}
ENTERI();
if (fabsl(x) < 40) { /* |x|<40 */
if (__predict_false(ix<BIAS-(LDBL_MANT_DIG+1)/2)) { /* |x|<TINY */
/* tanh(+-0) = +0; tanh(tiny) = tiny(-+) with inexact: */
return (x == 0 ? x : (0x1p200 * x - x) * 0x1p-200);
}
if (fabsl(x) < 0.25) { /* |x|<0.25 */
x2 = x*x;
#if LDBL_MANT_DIG == 64
x4 = x2*x2;
RETURNI(((T19*x2 + T17)*x4 + (T15*x2 + T13))*(x2*x*x2*x4*x4) +
((T11*x2 + T9)*x4 + (T7*x2 + T5))*(x2*x*x2) +
T3*(x2*x) + x);
#elif LDBL_MANT_DIG == 113
dx2 = x2;
RETURNI(((((((((((((((T33*dx2 + T31)*dx2 + T29)*dx2 + T27)*dx2 +
T25)*x2 + T23)*x2 + T21)*x2 + T19)*x2 + T17)*x2 +
T15)*x2 + T13)*x2 + T11)*x2 + T9)*x2 + T7)*x2 + T5)*
(x2*x*x2) +
T3*(x2*x) + x);
#endif
}
k_hexpl(2*fabsl(x), &hi, &lo);
if (fabsl(x) < 1.5) /* |x|<1.5 */
z = divl(hi, lo, -0.5, hi, lo, 0.5);
else
z = one - one/(lo+0.5+hi);
/* |x| >= 40, return +-1 */
} else {
z = one - tiny; /* raise inexact flag */
}
s = 1;
if (jx<0) s = -1;
RETURNI(s*z);
}