#include "fp_private.h"
#include "fenv_private.h"
extern const unsigned short SqrtTable[];
static const double kPiBy2Tail = 6.1232339957367660e-17; static const hexdouble kPiu = HEXDOUBLE(0x400921fb, 0x54442d18);
#define INVERSE_TRIGONOMETRIC_NAN "34"
static struct kBlock {
const double k2ToM26 ; const double kPiBy2 ; const double kPiBy2Tail ; const double kMinNormal ;
const double a14 ;
const double a13 ;
const double a12 ;
const double a11 ;
const double a10 ;
const double a9 ;
const double a8 ;
const double a7 ;
const double a6 ;
const double a5 ;
const double a4 ;
const double a3 ;
const double a2 ;
const double a1 ;
const double a0 ;
const double aa11 ;
const double aa10 ;
const double aa9 ;
const double aa8 ;
const double aa7 ;
const double aa6 ;
const double aa5 ;
const double aa4 ;
const double aa3 ;
const double aa2 ;
const double aa1 ;
const double aa0 ;
} kBlock =
{
0x1.0p-26, 1.570796326794896619231322, 6.1232339957367660e-17, 0x1.0p-1022,
0.03085091303188211304259,
-0.02425125216179617744614,
0.02273334623573271023373,
0.0002983797813053653120360,
0.008819738782817955152102,
0.008130738583790024803650,
0.009793486386035222577675,
0.01154901189590083099584,
0.01396501522140471126730,
0.01735275722383019335276,
0.02237215928757573539490,
0.03038194444121688698408,
0.04464285714288482921087,
0.07499999999999990640378,
0.1666666666666666667191,
0.0002983797813053653120360,
0.008819738782817955152102,
0.008130738583790024803650,
0.009793486386035222577675,
0.01154901189590083099584,
0.01396501522140471126730,
0.01735275722383019335276,
0.02237215928757573539490,
0.03038194444121688698408,
0.04464285714288482921087,
0.07499999999999990640378,
0.1666666666666666667191
};
double asin (double x)
{
hexdouble cD, yD ,gD , fpenv;
double absx, x2, x3, x4, temp1, temp2, u, v;
double g, y, d, y2, e;
register int index;
register uint32_t ghead, yhead, rnddir;
register double FPR_env, FPR_z, FPR_half, FPR_one, FPR_k2ToM26, FPR_cD, FPR_yD, FPR_kMinNormal, FPR_kPiBy2, FPR_kPiBy2Tail;
register struct kBlock *pK;
pK = &kBlock;
FPR_z = 0.0; FPR_half = 0.5;
FPR_k2ToM26 = pK->k2ToM26; FPR_kMinNormal = pK->kMinNormal;
FPR_kPiBy2 = pK->kPiBy2; FPR_one = 1.0;
if (unlikely(x != x)) return ( copysign ( nan ( INVERSE_TRIGONOMETRIC_NAN ), x ) );
absx = __FABS( x );
FEGETENVD ( FPR_env ); __ENSURE( FPR_z, FPR_half, FPR_k2ToM26 ); __ENSURE( FPR_one, FPR_kMinNormal, FPR_kPiBy2 ); FPR_cD = __FNMSUB( FPR_half, absx, FPR_half );
FESETENVD ( FPR_z );
x2 = __FMUL( x, x ); cD.d = FPR_cD;
if ( absx <= FPR_half )
{ if (unlikely( absx < FPR_k2ToM26 ))
{ if ( absx == FPR_z )
{ FESETENVD ( FPR_env );
return ( x );
}
fpenv.d = FPR_env;
__NOOP;
__NOOP;
__NOOP;
rnddir = fpenv.i.lo & FE_ALL_RND; FPR_yD = x;
if (((rnddir == FE_DOWNWARD) && (x < FPR_z)) || ((rnddir == FE_UPWARD) && (x > FPR_z)))
{
yD.d = FPR_yD;
__NOOP;
__NOOP;
__NOOP;
yD.i.lo += 1u;
if (yD.i.lo == 0u)
yD.i.hi += 1u;
__NOOP;
__NOOP;
__NOOP;
FPR_yD = yD.d;
absx = __FABS( FPR_yD );
}
FESETENVD ( FPR_env ); __PROG_INEXACT( FPR_kPiBy2 );
if (absx < FPR_kMinNormal) __PROG_UF_INEXACT( FPR_kMinNormal );
return ( FPR_yD ); }
{
register double r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
register double r10, r11, r12, r13, r14;
r14 = pK->a14; r13 = pK->a13;
temp1 = __FMADD( r14, x2, r13 ); x4 = __FMUL( x2, x2 );
x3 = __FMUL( x, x2 ); __NOOP;
r11 = pK->a11; r12 = pK->a12;
r9 = pK->a9; r10 = pK->a10;
temp1 = __FMADD( temp1, x4, r11 ); __NOOP;
temp1 = __FMADD( temp1, x4, r9 ); temp2 = __FMADD( r12, x4, r10 );
r7 = pK->a7; r8 = pK->a8;
r5 = pK->a5; r6 = pK->a6;
temp1 = __FMADD( temp1, x4, r7 ); temp2 = __FMADD( temp2, x4, r8 );
temp1 = __FMADD( temp1, x4, r5 ); temp2 = __FMADD( temp2, x4, r6 );
r3 = pK->a3; r4 = pK->a4;
r1 = pK->a1; r2 = pK->a2;
temp1 = __FMADD( temp1, x4, r3 ); temp2 = __FMADD( temp2, x4, r4 );
temp1 = __FMADD( temp1, x4, r1 ); temp2 = __FMADD( temp2, x4, r2 );
r0 = pK->a0; __NOOP;
temp2 = __FMADD( temp2, x2, temp1 );
temp1 = __FMADD( x2, temp2, r0 );
}
FESETENVD ( FPR_env ); __PROG_INEXACT( FPR_kPiBy2 );
return (__FMADD( x3, temp1, x ));
}
if (absx < FPR_one)
{ register double FPR_gD, FPR_two;
register double r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
register double r10, r11, r12, r13, r14;
register uint32_t GPR_p, GPR_q, GPR_r, GPR_s, GPR_t;
x2 = FPR_cD; x4 = __FMUL( FPR_cD, FPR_cD); GPR_t = cD.i.hi; r0 = pK->aa0;
GPR_s = GPR_t + 0x3ff00000u; __NOOP;
r14 = pK->a14; r13 = pK->a13;
r12 = pK->a12; r11 = pK->a11;
gD.i.lo = 0u;
index = (GPR_t >> 13) & 0xffu;
GPR_p = SqrtTable[index];
temp1 = __FMADD( r13, x4, r11 ); temp2 = __FMADD( r14, x4, r12 );
r10 = pK->a10; r9 = pK->a9;
GPR_r = ((0xff00u & GPR_p) << 4);
ghead = (GPR_s >> 1) & 0x7ff00000u;
gD.i.hi = ghead + GPR_r;
r8 = pK->a8; r7 = pK->aa7;
yhead = 0x7fc00000u - ghead;
yD.i.lo = 0u; GPR_q = ((0xffu & GPR_p) << 12);
yD.i.hi = yhead + GPR_q;
r6 = pK->aa6; r5 = pK->aa5;
temp1 = __FMADD( temp1, x4, r9 ); temp2 = __FMADD( temp2, x4, r10 );
temp1 = __FMADD( temp1, x4, r7 ); temp2 = __FMADD( temp2, x4, r8 );
r4 = pK->aa4; r3 = pK->aa3;
r2 = pK->aa2; r1 = pK->aa1;
temp1 = __FMADD( temp1, x4, r5 ); temp2 = __FMADD( temp2, x4, r6 );
temp1 = __FMADD( temp1, x4, r3 ); temp2 = __FMADD( temp2, x4, r4 );
FPR_two = 2.0;
FPR_gD = gD.d; y = yD.d;
temp1 = __FMADD( temp1, x4, r1 ); temp2 = __FMADD( temp2, x4, r2 );
d = __FNMSUB( FPR_gD, FPR_gD, FPR_cD ); FPR_kPiBy2Tail = pK->kPiBy2Tail;
g = __FMADD( y, d, FPR_gD ); y2 = y + y; e = __FNMSUB( y, g, FPR_half ); d = __FNMSUB( g, g, FPR_cD );
y = __FMADD( e, y2, y); temp1 = __FMADD( x2, temp2, temp1 ); g = __FMADD( y, d, g ); y2 = y + y;
e = __FNMSUB( y, g, FPR_half ); d = __FNMSUB( g, g, FPR_cD );
y = __FMADD( e, y2, y ); temp1 = __FMADD( x2, temp1, r0 ); g = __FMADD( y, d, g); d = __FNMSUB( g, g, FPR_cD ); u = __FNMSUB( FPR_two, g, FPR_kPiBy2 ); d = __FMUL( d, y ); v = __FNMSUB( FPR_two, g, (FPR_kPiBy2 - u) ); g = __FMUL( g, x2 ); d = __FNMSUB( FPR_half, FPR_kPiBy2Tail, d );
temp2 = __FNMSUB( FPR_half, v, d );
temp2 = __FMADD( g, temp1, temp2 );
FESETENVD ( FPR_env ); __PROG_INEXACT( FPR_kPiBy2 );
if (x > FPR_z)
{ return __FNMSUB( FPR_two, temp2, u );
}
else
return __FMSUB( FPR_two, temp2, u );
}
if (absx == FPR_one)
{
FPR_kPiBy2Tail = pK->kPiBy2Tail;
FESETENVD (FPR_env); if (x > FPR_z)
return __FMADD( x, FPR_kPiBy2Tail, FPR_kPiBy2 );
else
return __FMSUB( x, FPR_kPiBy2Tail, FPR_kPiBy2 );
}
fpenv.d = FPR_env;
__NOOP;
__NOOP;
__NOOP;
fpenv.i.lo |= SET_INVALID;
FESETENVD_GRP (fpenv.d);
return ( nan ( INVERSE_TRIGONOMETRIC_NAN ) );
}
double acos(double x)
{
hexdouble cD, yD, gD, fpenv;
double absx, x2, x3, x4, temp1, temp2, s, u, v, w;
double g, y, d, y2, e;
int index;
uint32_t ghead, yhead;
register double FPR_env, FPR_z, FPR_half, FPR_one, FPR_k2ToM26, FPR_cD, FPR_kMinNormal, FPR_kPiBy2, FPR_kPiBy2Tail;
register struct kBlock *pK;
pK = &kBlock;
FPR_z = 0.0; FPR_half = 0.5;
FPR_k2ToM26 = pK->k2ToM26; FPR_kMinNormal = pK->kMinNormal;
FPR_kPiBy2 = pK->kPiBy2; FPR_one = 1.0;
if (unlikely(x != x)) return ( copysign ( nan ( INVERSE_TRIGONOMETRIC_NAN ), x ) );
absx = __FABS(x);
FEGETENVD ( FPR_env ); __ENSURE( FPR_z, FPR_half, FPR_k2ToM26 ); __ENSURE( FPR_one, FPR_kMinNormal, FPR_kPiBy2 ); FPR_cD = __FNMSUB( FPR_half, absx, FPR_half );
FESETENVD ( FPR_z );
x2 = __FMUL( x, x ); cD.d = FPR_cD;
if ( absx <= FPR_half )
{ register double r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
register double r10, r11, r12, r13, r14;
r14 = pK->a14; r13 = pK->a13;
temp1 = __FMADD( r14, x2, r13 ); x4 = __FMUL( x2, x2 );
x3 = __FMUL( x, x2 ); u = FPR_kPiBy2 - x; r11 = pK->a11; r12 = pK->a12;
r9 = pK->a9; r10 = pK->a10;
temp1 = __FMADD( temp1, x4, r11 ); __NOOP;
temp1 = __FMADD( temp1, x4, r9 ); temp2 = __FMADD( r12, x4, r10 );
r7 = pK->a7; r8 = pK->a8;
r5 = pK->a5; r6 = pK->a6;
temp1 = __FMADD( temp1, x4, r7 ); temp2 = __FMADD( temp2, x4, r8 );
temp1 = __FMADD( temp1, x4, r5 ); temp2 = __FMADD( temp2, x4, r6 );
r3 = pK->a3; r4 = pK->a4;
r1 = pK->a1; r2 = pK->a2;
temp1 = __FMADD( temp1, x4, r3 ); temp2 = __FMADD( temp2, x4, r4 );
temp1 = __FMADD( temp1, x4, r1 ); temp2 = __FMADD( temp2, x4, r2 );
r0 = pK->a0; FPR_kPiBy2Tail = pK->kPiBy2Tail;
temp1 = __FMADD( x2, temp2, temp1 );
v = FPR_kPiBy2 - u - x; temp1 = __FMADD( x2, temp1, pK->a0 );
w = __FNMSUB( x3, temp1, (v + FPR_kPiBy2Tail) );
FESETENVD ( FPR_env ); __PROG_INEXACT( FPR_kPiBy2 );
return ( u + w );
}
if ( absx < FPR_one )
{ register double FPR_gD, FPR_two;
register double r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
register double r10, r11, r12, r13, r14;
register uint32_t GPR_p, GPR_q, GPR_r, GPR_s, GPR_t;
x2 = FPR_cD; x4 = __FMUL( x2, x2);
GPR_t = cD.i.hi; r0 = pK->aa0;
GPR_s = GPR_t + 0x3ff00000u; __NOOP;
r14 = pK->a14; r13 = pK->a13;
r12 = pK->a12; r11 = pK->aa11;
gD.i.lo = 0u;
index = (GPR_t >> 13) & 0xffu;
GPR_p = SqrtTable[index];
temp1 = __FMADD( r13, x4, r11 ); temp2 = __FMADD( r14, x4, r12 );
r10 = pK->aa10; r9 = pK->aa9;
GPR_r = ((0xff00u & GPR_p) << 4);
ghead = (GPR_s >> 1) & 0x7ff00000u;
gD.i.hi = ghead + GPR_r;
r8 = pK->aa8; r7 = pK->aa7;
yhead = 0x7fc00000u - ghead;
yD.i.lo = 0u; GPR_q = ((0xffu & GPR_p) << 12);
yD.i.hi = yhead + GPR_q;
r6 = pK->aa6; r5 = pK->aa5;
temp1 = __FMADD( temp1, x4, r9 ); temp2 = __FMADD( temp2, x4, r10 );
temp1 = __FMADD( temp1, x4, r7 ); temp2 = __FMADD( temp2, x4, r8 );
r4 = pK->aa4; r3 = pK->aa3;
r2 = pK->aa2; r1 = pK->aa1;
temp1 = __FMADD( temp1, x4, r5 ); temp2 = __FMADD( temp2, x4, r6 );
temp1 = __FMADD( temp1, x4, r3 ); temp2 = __FMADD( temp2, x4, r4 );
FPR_two = 2.0;
FPR_gD = gD.d; y = yD.d;
temp1 = __FMADD( temp1, x4, r1 ); temp2 = __FMADD( temp2, x4, r2 );
d = __FNMSUB( FPR_gD, FPR_gD, x2 );
g = __FMADD( y, d, FPR_gD ); y2 = y + y; e = __FNMSUB( y, g, FPR_half ); d = __FNMSUB( g, g, x2 );
y = __FMADD( e, y2, y); temp1 = __FMADD( x2, temp2, temp1 ); g = __FMADD( y, d, g ); y2 = y + y; e = __FNMSUB( y, g, FPR_half ); d = __FNMSUB( g, g, x2 );
y = __FMADD( e, y2, y ); g = __FMADD( y, d, g); d = __FNMSUB( g, g, x2 ); y2 = g + g;
if (x > FPR_z)
{ s = __FMADD( __FMUL( g, x2 ), __FMADD( x2, temp1, pK->aa0), d );
FESETENVD ( FPR_env ); __PROG_INEXACT( FPR_kPiBy2 );
return __FMADD( FPR_two, s, y2); } else
{ register double q,r,ss,t;
u = __FMSUB( FPR_two, FPR_kPiBy2, y2 ); r = d - kPiBy2Tail;
ss = __FMADD( x2, temp1, pK->aa0 );
t = __FMUL( g, x2 );
v = __FMSUB( FPR_two, FPR_kPiBy2, u ) - y2; q = __FNMSUB( FPR_half, v, r );
s = __FMADD( ss, t, q );
FESETENVD ( FPR_env ); __PROG_INEXACT( FPR_kPiBy2 );
return __FNMSUB( FPR_two, s, u); } }
if ( x == FPR_one )
{
FESETENVD ( FPR_env ); return ( FPR_z );
}
if ( x == -1.0 )
{
FESETENVD ( FPR_env ); __PROG_INEXACT( FPR_kPiBy2 );
return (kPiu.d + 2.0*kPiBy2Tail);
}
fpenv.d = FPR_env;
__NOOP;
__NOOP;
__NOOP;
fpenv.i.lo |= SET_INVALID;
FESETENVD_GRP ( fpenv.d );
return ( nan ( INVERSE_TRIGONOMETRIC_NAN ) );
}