aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflatmush <flatmush@d3e1167c-abe1-51d5-8199-f9061ebe54e4>2011-02-28 11:24:38 +0000
committerflatmush <flatmush@d3e1167c-abe1-51d5-8199-f9061ebe54e4>2011-02-28 11:24:38 +0000
commitae58c98283e883898692c9484b62cc1a9ee749e5 (patch)
treec37d04eded77616deb99ac0a922d53fd46d8a170
parent8737eb5fe2796f1f550a131e8566d8d667f3024a (diff)
downloadlibfixmath-ae58c98283e883898692c9484b62cc1a9ee749e5.tar.gz
Added 32-bit division option, it is less accurate (inaccuracy of ~0.0035%) and very slow (750% of float) but it does work.
Changed tan to be saturated (i.e. tan(pi/4) = fix16_max rather than divide by zero error), may revert or implement as stan later.
-rw-r--r--libfixmath/fix16.c35
-rw-r--r--libfixmath/fix16_trig.c2
2 files changed, 36 insertions, 1 deletions
diff --git a/libfixmath/fix16.c b/libfixmath/fix16.c
index 2e3b6d5..88131d8 100644
--- a/libfixmath/fix16.c
+++ b/libfixmath/fix16.c
@@ -88,6 +88,7 @@ fix16_t fix16_smul(fix16_t inArg0, fix16_t inArg1) {
fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1) {
+ #ifndef FIXMATH_NO_64BIT
int64_t tempResult = inArg0;
tempResult <<= 16;
#ifndef FIXMATH_NO_ROUNDING
@@ -95,6 +96,21 @@ fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1) {
#endif
tempResult /= inArg1;
return tempResult;
+ #else
+ int32_t res = (inArg0 / inArg1) << 16;
+ int32_t mod = inArg0 % inArg1;
+ uintptr_t i;
+ for(i = 0; i < 16; i++) {
+ mod <<= 1;
+ res += (mod / inArg1) << (15 - i);
+ mod %= inArg1;
+ }
+ #ifndef FIXMATH_NO_ROUNDING
+ if((mod << 1) / inArg1)
+ res++;
+ #endif
+ return res;
+ #endif
}
fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) {
@@ -103,6 +119,7 @@ fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) {
return fix16_MIN;
return fix16_MAX;
}
+ #ifndef FIXMATH_NO_64BIT
int64_t tempResult = inArg0;
tempResult <<= 16;
#ifndef FIXMATH_NO_ROUNDING
@@ -114,6 +131,24 @@ fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) {
if(tempResult > fix16_MAX)
return fix16_MAX;
return tempResult;
+ #else
+ int32_t res = (inArg0 / inArg1);
+ if((res < -32768) || (res >= 32768))
+ return (res < 0 ? fix16_MIN : fix16_MAX);
+ res <<= 16;
+ int32_t mod = inArg0 % inArg1;
+ uintptr_t i;
+ for(i = 0; i < 16; i++) {
+ mod <<= 1;
+ res += (mod / inArg1) << (15 - i);
+ mod %= inArg1;
+ }
+ #ifndef FIXMATH_NO_ROUNDING
+ if((mod << 1) / inArg1)
+ res++;
+ #endif
+ return res;
+ #endif
}
diff --git a/libfixmath/fix16_trig.c b/libfixmath/fix16_trig.c
index 278a3bd..5d98872 100644
--- a/libfixmath/fix16_trig.c
+++ b/libfixmath/fix16_trig.c
@@ -115,7 +115,7 @@ fix16_t fix16_cos(fix16_t inAngle) {
}
fix16_t fix16_tan(fix16_t inAngle) {
- return fix16_div(fix16_sin(inAngle), fix16_cos(inAngle));
+ return fix16_sdiv(fix16_sin(inAngle), fix16_cos(inAngle));
}
fix16_t fix16_asin(fix16_t inValue) {