#include "math.h"
#include "math_private.h"
#define _CC (0x1p12F + 1)
#define _ROOT sqrtf
volatile static const float tiny = 1.e-30;
static const float half = 0.5f, one = 1.f, qrtr = 0.25f;
static const float x0 = 0.625, x1 = 0.875, x2 = 1.5;
static const float
invpihi = 3.18309873e-01f,
invpilo = 1.28412765e-08f,
a0hi = 1.77807689e-01f,
a0lo = -4.22372093e-09f,
a1hi = 2.28810698e-01f,
a1lo = -2.42890708e-09f,
a2hi = 3.12832952e-01f,
a2lo = 6.64328592e-09f;
static inline float
__r(float xs)
{
static const float
R0 = -1.06103294e-01f,
R1 = -6.81197494e-02f,
R2 = -1.61480496e-03f,
S1 = 1.24201322e+00f,
S2 = 3.31868112e-01f;
float r, s;
r = R0 + (R1 + R2 * xs) * xs;
s = 1 + (S1 + S2 * xs) * xs;
return (xs * (r / s));
}
float
atanpif(float x)
{
float ax, hi, lo, xh, xl, y, zh, zl;
uint32_t hx, ix;
GET_FLOAT_WORD(hx, x);
ix = hx & 0x7fffffff;
if (ix >= 0x7f800000) {
if (ix > 0x7f800000)
return (x + x);
return ((hx & 0x80000000) ? -half : half);
}
SET_FLOAT_WORD(ax, ix);
if (ix <= 0x3f000000) {
if (ix < 0x39000000) {
if (ix < 0x03800000) {
if (ix == 0)
return (x);
ax *= 0x1p25f;
_XMUL(ax, 0, invpihi, invpilo, hi, lo);
y = (hi + lo) * 0x1p-25f;
} else {
_XMUL(ax, 0, invpihi, invpilo, hi, lo);
y = hi + lo;
}
} else {
y = __r(ax * ax);
_XADD(invpihi, invpilo, y, 0, xh, xl);
_XMUL(ax, 0, xh, xl, hi, lo);
y = hi + lo;
}
} else if (ix < 0x3f800000) {
if (ix < 0x3f400000) {
x = (ax - x0) / (1 + x0 * ax);
y = __r(x * x);
_XADD(invpihi, invpilo, y, 0, xh, xl);
_XMUL(x, 0, xh, xl, hi, lo);
_XADD(a0hi, a0lo, hi, lo, y, xl);
} else {
x = (ax - x1) / (1 + x1 * ax);
y = __r(x * x);
_XADD(invpihi, invpilo, y, 0, xh, xl);
_XMUL(x, 0, xh, xl, hi, lo);
_XADD(a1hi, a1lo, hi, lo, y, xl);
}
} else if (ix < 0x40000000) {
if (ix == 0x3f800000)
return ((hx & 0x80000000) ? -qrtr : qrtr);
x = (ax - x2) / (1 + x2 * ax);
y = __r(x * x);
_XADD(invpihi, invpilo, y, 0, xh, xl);
_XMUL(x, 0, xh, xl, hi, lo);
_XADD(a2hi, a2lo, hi, lo, y, xl);
} else {
x = 1 / ax;
y = __r(x * x);
_XADD(invpihi, invpilo, y, 0, xh, xl);
_XMUL(x, 0, xh, xl, hi, lo);
_XADD(half, 0, -hi, -lo, y, x);
}
return ((hx & 0x80000000) ? -y : y);
}