aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflatmush <flatmush@d3e1167c-abe1-51d5-8199-f9061ebe54e4>2011-02-25 13:37:37 +0000
committerflatmush <flatmush@d3e1167c-abe1-51d5-8199-f9061ebe54e4>2011-02-25 13:37:37 +0000
commit0ecfa08dc392830ab4c52b5c8f26d412575583d4 (patch)
treeb9e74a926d5ad08770711bfb64e1a06c38201a29
parent10c82e1c1770f6c956e108d63af2ab9a57ce370d (diff)
downloadlibfixmath-0ecfa08dc392830ab4c52b5c8f26d412575583d4.tar.gz
Added a new faster version of the sin function, it loses 0.2% accuracy for a speed gain of 159%. The accuracy of the standard implementation is ~2.1% while this is ~2.3%.
This can be enabled using the FIXMATH_FAST_SIN macro.
-rw-r--r--libfixmath/fix16_trig.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/libfixmath/fix16_trig.c b/libfixmath/fix16_trig.c
index 67bf80f..17a5b88 100644
--- a/libfixmath/fix16_trig.c
+++ b/libfixmath/fix16_trig.c
@@ -26,6 +26,8 @@ fix16_t fix16_sin(fix16_t inAngle) {
fix16_t tempAngleSq = fix16_mul(tempAngle, tempAngle);
+
+ #ifndef FIXMATH_FAST_SIN // Most accurate version, accurate to ~2.1%
fix16_t tempOut = tempAngle;
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut -= (tempAngle / 6);
@@ -37,6 +39,48 @@ fix16_t fix16_sin(fix16_t inAngle) {
tempOut += (tempAngle / 362880);
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut -= (tempAngle / 39916800);
+ #else // Fast implementation, runs at 159% the speed of above 'accurate' version with an slightly lower accuracy of ~2.3%
+ fix16_t tempOut;
+ tempOut = fix16_mul(-13, tempAngleSq) + 546;
+ tempOut = fix16_mul(tempOut, tempAngleSq) - 10923;
+ tempOut = fix16_mul(tempOut, tempAngleSq) + 65536;
+ tempOut = fix16_mul(tempOut, tempAngle);
+ #endif
+
+ /*// Broken implementation, meant to be slightly faster and much more accurate than the above 'accurate' implementation.
+ int64_t tempAngleSq = tempAngle * tempAngle;
+ #ifndef FIXMATH_NO_ROUNDING
+ tempAngleSq += (fix16_one >> 1);
+ #endif
+ tempAngleSq >>= 16;
+
+ int64_t tempOut;
+ tempOut = (-108 * tempAngleSq) + 11836;
+ #ifndef FIXMATH_NO_ROUNDING
+ tempOut += (fix16_one >> 1);
+ #endif
+ tempOut >>= 16;
+
+ tempOut = (tempOut * tempAngleSq) - 852176;
+ #ifndef FIXMATH_NO_ROUNDING
+ tempOut += (fix16_one >> 1);
+ #endif
+ tempOut >>= 16;
+
+ tempOut = (tempOut * tempAngleSq) + 35791394;
+ #ifndef FIXMATH_NO_ROUNDING
+ tempOut += (fix16_one >> 1);
+ #endif
+ tempOut >>= 16;
+
+ tempOut = (tempOut * tempAngleSq) - 715827883;
+ #ifndef FIXMATH_NO_ROUNDING
+ tempOut += (fix16_one >> 1);
+ #endif
+ tempOut >>= 16;
+
+ tempOut = fix16_mul(tempOut, tempAngle) + tempAngle;
+ */
#ifndef FIXMATH_NO_CACHE
_fix16_sin_cache_index[tempIndex] = inAngle;