#include <float.h>
#ifdef __i386__
#include <ieeefp.h>
#endif
#include "fpmath.h"
#include "math.h"
#include "math_private.h"
#if LDBL_MANT_DIG == 64
#define EXP_LARGE 34
#define EXP_TINY -34
#elif LDBL_MANT_DIG == 113
#define EXP_LARGE 58
#define EXP_TINY -58
#else
#error "Unsupported long double format"
#endif
#if LDBL_MAX_EXP != 0x4000
#error "Unsupported long double format"
#endif
#define BIAS (LDBL_MAX_EXP - 1)
static const double
one = 1.00000000000000000000e+00,
huge= 1.00000000000000000000e+300;
#if LDBL_MANT_DIG == 64
static const union IEEEl2bits
u_ln2 = LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309417e-1L);
#define ln2 u_ln2.e
#elif LDBL_MANT_DIG == 113
static const long double
ln2 = 6.93147180559945309417232121458176568e-1L;
#else
#error "Unsupported long double format"
#endif
long double
asinhl(long double x)
{
long double t, w;
uint16_t hx, ix;
ENTERI();
GET_LDBL_EXPSIGN(hx, x);
ix = hx & 0x7fff;
if (ix >= 0x7fff) RETURNI(x+x);
if (ix < BIAS + EXP_TINY) {
if (huge + x > one) RETURNI(x);
}
if (ix >= BIAS + EXP_LARGE) {
w = logl(fabsl(x))+ln2;
} else if (ix >= 0x4000) {
t = fabsl(x);
w = logl(2.0*t+one/(sqrtl(x*x+one)+t));
} else {
t = x*x;
w =log1pl(fabsl(x)+t/(one+sqrtl(one+t)));
}
RETURNI((hx & 0x8000) == 0 ? w : -w);
}