From 74bda7e6cc4a5426e6262dc6d6c2416abe3fb0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Tue, 30 Apr 2024 23:50:43 -0700 Subject: [PATCH] Added bx::sinCosApprox. --- include/bx/inline/math.inl | 14 ++++++++++++++ include/bx/math.h | 7 +++++++ tests/math_test.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/include/bx/inline/math.inl b/include/bx/inline/math.inl index f5b94c4..183887b 100644 --- a/include/bx/inline/math.inl +++ b/include/bx/inline/math.inl @@ -162,6 +162,20 @@ namespace bx return _a * _a; } + inline void sinCosApprox(float _a, float* _outSin, float* _outCos) + { + const float aa = _a - floor(_a/kPi2)*kPi2; + const float absA = abs(aa); + const float cosA = cos(absA); + const float cosASq = square(cosA); + const float tmp0 = sqrt(1.0f - cosASq); + const float tmp1 = aa > 0.0f && aa < kPi ? 1.0f : -1.0f; + const float sinA = mul(tmp0, tmp1); + + *_outSin = sinA; + *_outCos = cosA; + } + inline BX_CONST_FUNC float sin(float _a) { return cos(_a - kPiHalf); diff --git a/include/bx/math.h b/include/bx/math.h index c6e662a..808da6f 100644 --- a/include/bx/math.h +++ b/include/bx/math.h @@ -203,6 +203,13 @@ namespace bx /// BX_CONSTEXPR_FUNC float square(float _a); + /// Returns the both sine and cosine of the argument _a. + /// + /// @remarks The function calculates cosine, and then approximates sine based on the cosine + /// result. Therefore calculation of sine is less accurate than calling `bx::sin` function. + /// + void sinCosApprox(float _a, float* _outSin, float* _outCos); + /// Returns the sine of the argument _a. /// BX_CONST_FUNC float sin(float _a); diff --git a/tests/math_test.cpp b/tests/math_test.cpp index c98f4ee..55b7ae7 100644 --- a/tests/math_test.cpp +++ b/tests/math_test.cpp @@ -441,6 +441,36 @@ TEST_CASE("sin", "[math][libm]") } } +TEST_CASE("sinCos", "[math][libm]") +{ + bx::WriterI* writer = bx::getNullOut(); + bx::Error err; + + for (float xx = -100.0f; xx < 100.0f; xx += 0.1f) + { + float ss, cc; + bx::sinCosApprox(xx, &ss, &cc); + + bx::write(writer, &err, "sinCos(%f) == sin %f (expected: %f)\n", xx, ss, ::sinf(xx) ); + bx::write(writer, &err, "sinCos(%f) == cos %f (expected: %f)\n", xx, cc, ::cosf(xx) ); + REQUIRE(err.isOk() ); + REQUIRE(bx::isEqual(ss, ::sinf(xx), 0.001f) ); + REQUIRE(bx::isEqual(cc, ::cosf(xx), 0.00001f) ); + } + + for (float xx = -bx::kPi2; xx < bx::kPi2; xx += 0.0001f) + { + float ss, cc; + bx::sinCosApprox(xx, &ss, &cc); + + bx::write(writer, &err, "sinCos(%f) == sin %f (expected: %f)\n", xx, ss, ::sinf(xx) ); + bx::write(writer, &err, "sinCos(%f) == cos %f (expected: %f)\n", xx, cc, ::cosf(xx) ); + REQUIRE(err.isOk() ); + REQUIRE(bx::isEqual(ss, ::sinf(xx), 0.001f) ); + REQUIRE(bx::isEqual(cc, ::cosf(xx), 0.00001f) ); + } +} + TEST_CASE("sinh", "[math][libm]") { bx::WriterI* writer = bx::getNullOut();