// 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; }