diff --git a/maths/fast.hpp b/maths/fast.hpp index e9dfe108..9a8c0ef5 100644 --- a/maths/fast.hpp +++ b/maths/fast.hpp @@ -21,9 +21,11 @@ namespace cruft::maths::fast { return std::fma (b, t, a) + std::fma (d, t, c) * t2; } - // approximates sin over the range [0; pi/4] using a polynomial. + // approximates sin over the range [-2pi, 2pi] using a polynomial + // approximation over [0; pi/4] // // the relative error should be on the order of 1e-6. + // the absolute error should be maximally around 1e-5 // // sollya: // display=hexadecimal; @@ -38,15 +40,21 @@ namespace cruft::maths::fast { constexpr float sin (float x) noexcept { - CHECK_LT (x, 2 * pi); - CHECK_GT (x, -2 * pi); + CHECK_LE (x, 2 * pi); + CHECK_GE (x, -2 * pi); - // flip negative angles due to having an even function - float neg = x < 0 ? x *= -1, -1 : 1; + // Push values into the range [0, 2pi] + if (x < 0) + x += 2 * pi; - // reduce the angle due to the period - int periods = static_cast (x / 2 / pi); - x -= periods * 2 * pi; + // Values in the range [pi, 2pi] are the negation of [0, pi] + float neg = x > pi ? -1 : 1; + if (x > pi) + x -= pi; + + // Values in [0,pi] are symmetric about pi/2 + if (x > pi / 2) + x = pi - x; // 1,3,5,7: 1, -0x1.555546p-3f, 0x1.11077ap-7f, -0x1.9954e8p-13f; // 1,3,5,7,9: 1, -0x1.555556p-3f, 0x1.11115cp-7f, -0x1.a0403ap-13f, 0x1.75dc26p-19f;