112 lines
1.5 KiB
C
112 lines
1.5 KiB
C
|
|
// These unions are necessary to put the constants in .rodata rather than .data.
|
|
// TODO: is it possible to remove them somehow?
|
|
|
|
typedef union {
|
|
/* 0x0 */ double d;
|
|
/* 0x0 */ struct
|
|
{
|
|
/* 0x0 */ unsigned int hi;
|
|
/* 0x4 */ unsigned int lo;
|
|
} word;
|
|
} du;
|
|
|
|
typedef union {
|
|
/* 0x0 */ float f;
|
|
/* 0x0 */ unsigned int i;
|
|
} fu;
|
|
|
|
static const du P[5] = {{1.0},
|
|
{-0.16666659550427756},
|
|
{0.008333066246082155},
|
|
{-1.980960290193795E-4},
|
|
{2.605780637968037E-6}};
|
|
|
|
static const du rpi = {0.3183098861837907};
|
|
|
|
static const du pihi = {
|
|
3.1415926218032837};
|
|
|
|
static const du pilo = {
|
|
3.178650954705639E-8};
|
|
|
|
static const fu zero = {0.0};
|
|
extern const fu NAN;
|
|
|
|
float sinf(float x)
|
|
{
|
|
double dx; // double x
|
|
double xsq; // x squared
|
|
double poly;
|
|
double dn;
|
|
int n;
|
|
double result;
|
|
int ix; // int x
|
|
int xpt;
|
|
|
|
ix = *(int *)&x;
|
|
xpt = (ix >> 22) & 0x1FF;
|
|
|
|
if (xpt < 255)
|
|
{
|
|
dx = x;
|
|
if (xpt >= 230)
|
|
{
|
|
xsq = dx * dx;
|
|
|
|
poly = (((((P[4].d * xsq) + P[3].d) * xsq) + P[2].d) * xsq) + P[1].d;
|
|
|
|
result = ((dx * xsq) * poly) + dx;
|
|
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
return x;
|
|
}
|
|
}
|
|
|
|
if (xpt < 310)
|
|
{
|
|
dx = x;
|
|
|
|
dn = dx * rpi.d;
|
|
|
|
if (dn >= 0)
|
|
{
|
|
n = dn + 0.5;
|
|
}
|
|
else
|
|
{
|
|
n = dn - 0.5;
|
|
}
|
|
|
|
dn = n;
|
|
|
|
dx -= dn * pihi.d;
|
|
dx -= dn * pilo.d;
|
|
|
|
xsq = dx * dx;
|
|
|
|
poly = (((((P[4].d * xsq) + P[3].d) * xsq) + P[2].d) * xsq) + P[1].d;
|
|
|
|
result = ((dx * xsq) * poly) + dx;
|
|
|
|
if ((n & 0x1) == 0)
|
|
{
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
return -(float)result;
|
|
}
|
|
}
|
|
|
|
if (x != x)
|
|
{
|
|
return NAN.f;
|
|
}
|
|
|
|
return zero.f;
|
|
}
|