@MrAl
Here's a C function it then generated for me:
Here's a C function it then generated for me:
C:
#include <math.h>
/*
* Compute sin(x) using Newton refinement on arcsin(s) = x.
*
* Iteration:
* s_{n+1} = s_n + (x - asin(s_n)) * sqrt(1 - s_n*s_n)
*
* This converges quadratically once s_n is close.
*
* Initial seed:
* For small |x|, s0 = x is good.
* For larger x, reduce to [-pi/2, pi/2] and use s0 = x.
*
* No call to sin() anywhere.
*/
double sin_newton(double x, int iters)
{
// Range reduction to [-pi, pi]
const double TWO_PI = 6.283185307179586476925286766559;
x = fmod(x, TWO_PI);
if (x > M_PI) x -= TWO_PI;
else if (x < -M_PI) x += TWO_PI;
// Further reduce to [-pi/2, pi/2] using symmetry
int sign = 1;
if (x > M_PI_2) { x = M_PI - x; }
if (x < -M_PI_2) { x = -M_PI - x; sign = -1; }
// Initial approximation: s0 = x (good for |x| <= pi/2)
double s = x;
for (int k = 0; k < iters; ++k) {
double theta = asin(s); // inverse step
double e = x - theta; // angle error
double c = sqrt(1.0 - s*s); // cos(theta)
s = s + e * c; // Newton update
}
return sign * s;
}
