#include "math.h"
#include "fp_private.h"
#if (__WANT_LONG_DOUBLE_FORMAT__ - 0L == 128L)
#include "DD.h"
static const DblDbl kLn2DD = {{0x3fe62e42, 0xfefa39ef,
0x3c7abc9e, 0x3b39803f}};
static const Float kInfF = {0x7f800000};
long double fabsl(long double x);
long double logl(long double x);
long double sqrtl(long double x);
long double log1pl(long double x);
long double copysignl(long double x, long double y);
long double acoshl(long double x)
{
DblDbl xDD;
long double y;
uint32_t xhi;
double fpenv;
xDD.f = x;
xhi = xDD.i[0];
if ((xDD.d[0] != xDD.d[0]) || (xDD.d[0] == kInfF.f))
return x;
FEGETENVD(fpenv);
FESETENVD(0.0);
if (x >= 1.0L) {
if (xhi > 0x5fefffffu) { y = logl(x) + kLn2DD.f;
FESETENVD(fpenv);
return y;
}
else if (xhi > 0x3ff40000u) { y = logl(2.0L*x - 1.0L/(x + sqrtl(x*x -1.0L)));
FESETENVD(fpenv);
return y;
}
else { y = x - 1.0L;
y = y + sqrtl(y * (2.0L + y));
y = log1pl(y);
FESETENVD(fpenv);
return y;
}
}
xDD.i[0] = 0x7ff80000u; xDD.i[1] = 0u;
xDD.i[2] = 0x7ff80000u;
xDD.i[3] = 0u;
FESETENVD(fpenv);
return (xDD.f); }
long double asinhl(long double x)
{
DblDbl xDD;
long double absx, y;
uint32_t xhi;
double fpenv;
xDD.f = x;
absx = fabsl(x);
xhi = xDD.i[0] & 0x7fffffffu;
if (xhi >= 0x7ff00000u) return x;
if (xhi < 0x29900000u) return x;
FEGETENVD(fpenv);
FESETENVD(0.0);
if (xhi <= 0x3ff55555u) { y = 1.0L / absx;
y = log1pl(absx + absx/(y + sqrtl(1.0L + y*y)));
}
else if (xhi < 0x5ff00000u) y = logl(2.0L*absx + 1.0/(absx + sqrtl(1.0L + absx*absx)));
else y = logl(absx) + kLn2DD.f;
y = copysignl(y,x);
FESETENVD(fpenv);
return y; }
long double atanhl(long double x)
{
DblDbl xDD;
long double absx, y;
uint32_t xhi;
double fpenv;
xDD.f = x;
absx = fabsl(x); xhi = xDD.i[0] & 0x7fffffffu;
if (xDD.d[0] != xDD.d[0]) return x;
if (xhi < 0x29900000u) { return x;
}
FEGETENVD(fpenv);
FESETENVD(0.0);
if (absx <= 1.0L) { y = 0.5L * log1pl(2.0L*absx / (1.0L - absx));
y = copysignl(y,x);
FESETENVD(fpenv);
return y;
}
else { y = log1pl(-absx);
FESETENVD(fpenv);
return y;
}
}
#endif