166 lines
3.0 KiB
C
166 lines
3.0 KiB
C
/* asinh.c
|
||
*
|
||
* Inverse hyperbolic sine
|
||
*
|
||
*
|
||
*
|
||
* SYNOPSIS:
|
||
*
|
||
* double x, y, asinh();
|
||
*
|
||
* y = asinh( x );
|
||
*
|
||
*
|
||
*
|
||
* DESCRIPTION:
|
||
*
|
||
* Returns inverse hyperbolic sine of argument.
|
||
*
|
||
* If |x| < 0.5, the function is approximated by a rational
|
||
* form x + x**3 P(x)/Q(x). Otherwise,
|
||
*
|
||
* asinh(x) = log( x + sqrt(1 + x*x) ).
|
||
*
|
||
*
|
||
*
|
||
* ACCURACY:
|
||
*
|
||
* Relative error:
|
||
* arithmetic domain # trials peak rms
|
||
* DEC -3,3 75000 4.6e-17 1.1e-17
|
||
* IEEE -1,1 30000 3.7e-16 7.8e-17
|
||
* IEEE 1,3 30000 2.5e-16 6.7e-17
|
||
*
|
||
*/
|
||
|
||
/* asinh.c */
|
||
|
||
/*
|
||
Cephes Math Library Release 2.8: June, 2000
|
||
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
||
*/
|
||
|
||
|
||
#include "mconf.h"
|
||
|
||
#ifdef UNK
|
||
const static double P[] = {
|
||
-4.33231683752342103572E-3,
|
||
-5.91750212056387121207E-1,
|
||
-4.37390226194356683570E0,
|
||
-9.09030533308377316566E0,
|
||
-5.56682227230859640450E0
|
||
};
|
||
const static double Q[] = {
|
||
/* 1.00000000000000000000E0,*/
|
||
1.28757002067426453537E1,
|
||
4.86042483805291788324E1,
|
||
6.95722521337257608734E1,
|
||
3.34009336338516356383E1
|
||
};
|
||
#endif
|
||
|
||
#ifdef DEC
|
||
static unsigned short P[] = {
|
||
0136215,0173033,0110410,0105475,
|
||
0140027,0076361,0020056,0164520,
|
||
0140613,0173401,0160136,0053142,
|
||
0141021,0070744,0000503,0176261,
|
||
0140662,0021550,0073106,0133351
|
||
};
|
||
static unsigned short Q[] = {
|
||
/* 0040200,0000000,0000000,0000000,*/
|
||
0041116,0001336,0034120,0173054,
|
||
0041502,0065300,0013144,0021231,
|
||
0041613,0022376,0035516,0153063,
|
||
0041405,0115216,0054265,0004557
|
||
};
|
||
#endif
|
||
|
||
#ifdef IBMPC
|
||
static unsigned short P[] = {
|
||
0x1168,0x7221,0xbec3,0xbf71,
|
||
0xdd2a,0x2405,0xef9e,0xbfe2,
|
||
0xcacc,0x3c0b,0x7ee0,0xc011,
|
||
0x7f96,0x8028,0x2e3c,0xc022,
|
||
0xd6dd,0x0ec8,0x446d,0xc016
|
||
};
|
||
static unsigned short Q[] = {
|
||
/* 0x0000,0x0000,0x0000,0x3ff0,*/
|
||
0x1ec5,0xc70a,0xc05b,0x4029,
|
||
0x8453,0x02cc,0x4d58,0x4048,
|
||
0xdac6,0xc769,0x649f,0x4051,
|
||
0xa12e,0xcb16,0xb351,0x4040
|
||
};
|
||
#endif
|
||
|
||
#ifdef MIEEE
|
||
static unsigned short P[] = {
|
||
0xbf71,0xbec3,0x7221,0x1168,
|
||
0xbfe2,0xef9e,0x2405,0xdd2a,
|
||
0xc011,0x7ee0,0x3c0b,0xcacc,
|
||
0xc022,0x2e3c,0x8028,0x7f96,
|
||
0xc016,0x446d,0x0ec8,0xd6dd
|
||
};
|
||
static unsigned short Q[] = {
|
||
0x4029,0xc05b,0xc70a,0x1ec5,
|
||
0x4048,0x4d58,0x02cc,0x8453,
|
||
0x4051,0x649f,0xc769,0xdac6,
|
||
0x4040,0xb351,0xcb16,0xa12e
|
||
};
|
||
#endif
|
||
|
||
#ifdef ANSIPROT
|
||
extern double polevl ( double, void *, int );
|
||
extern double p1evl ( double, void *, int );
|
||
extern double sqrt ( double );
|
||
extern double log ( double );
|
||
#else
|
||
double log(), sqrt(), polevl(), p1evl();
|
||
#endif
|
||
extern double LOGE2, INFINITY;
|
||
|
||
double asinh(xx)
|
||
double xx;
|
||
{
|
||
double a, z, x;
|
||
int sign;
|
||
|
||
#ifdef MINUSZERO
|
||
if( xx == 0.0 )
|
||
return(xx);
|
||
#endif
|
||
if( xx < 0.0 )
|
||
{
|
||
sign = -1;
|
||
x = -xx;
|
||
}
|
||
else
|
||
{
|
||
sign = 1;
|
||
x = xx;
|
||
}
|
||
|
||
if( x > 1.0e8 )
|
||
{
|
||
#ifdef INFINITIES
|
||
if( x == INFINITY )
|
||
return(xx);
|
||
#endif
|
||
return( sign * (log(x) + LOGE2) );
|
||
}
|
||
|
||
z = x * x;
|
||
if( x < 0.5 )
|
||
{
|
||
a = ( polevl(z, P, 4)/p1evl(z, Q, 4) ) * z;
|
||
a = a * x + x;
|
||
if( sign < 0 )
|
||
a = -a;
|
||
return(a);
|
||
}
|
||
|
||
a = sqrt( z + 1.0 );
|
||
return( sign * log(x + a) );
|
||
}
|