diff --git a/speeduino/maths.h b/speeduino/maths.h index 311086e7..598f5caf 100644 --- a/speeduino/maths.h +++ b/speeduino/maths.h @@ -1,6 +1,8 @@ #ifndef MATH_H #define MATH_H +#define USE_LIBDIVIDE + int fastMap1023toX(int, int); unsigned long percentage(byte, unsigned long); unsigned long halfPercentage(byte, unsigned long); @@ -16,4 +18,6 @@ unsigned long divu100(unsigned long); //This is a new version that allows for out_min #define fastMap10Bit(x, out_min, out_max) ( ( ((unsigned long)x * (out_max-out_min)) >> 10 ) + out_min) + + #endif \ No newline at end of file diff --git a/speeduino/maths.ino b/speeduino/maths.ino index 00e2ae5f..be0a58ed 100644 --- a/speeduino/maths.ino +++ b/speeduino/maths.ino @@ -1,5 +1,14 @@ #include "maths.h" #include "globals.h" +#include "src/libdivide/libdivide.h" + +#ifdef USE_LIBDIVIDE + //Constants used for libdivide + struct libdivide::libdivide_u32_t libdiv_u32_10 = libdivide::libdivide_u32_gen(10); + struct libdivide::libdivide_u32_t libdiv_u32_100 = libdivide::libdivide_u32_gen(100); + struct libdivide::libdivide_s32_t libdiv_s32_100 = libdivide::libdivide_s32_gen(100); + struct libdivide::libdivide_u32_t libdiv_u32_200 = libdivide::libdivide_u32_gen(200); +#endif //Replace the standard arduino map() function to use the div function instead int fastMap(unsigned long x, int in_min, int in_max, int out_min, int out_max) @@ -13,65 +22,56 @@ int fastMap(unsigned long x, int in_min, int in_max, int out_min, int out_max) //return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } -/* -The following are all fast versions of specific divisions -Ref: www.hackersdelight.org/divcMore.pdf -*/ - //Unsigned divide by 10 unsigned int divu10(unsigned int n) { - unsigned long q, r; - q = (n >> 1) + (n >> 2); - q = q + (q >> 4); - q = q + (q >> 8); - q = q + (q >> 16); - q = q >> 3; - r = n - (q * 10); - return q + ((r + 6) >> 4); +#ifdef USE_LIBDIVIDE + return libdivide::libdivide_u32_do(n, &libdiv_u32_10); +#else + return (n / 10); +#endif } //Signed divide by 100 int divs100(long n) { +#ifdef USE_LIBDIVIDE + return libdivide::libdivide_s32_do(n, &libdiv_s32_100); +#else return (n / 100); // Amazingly, gcc is producing a better /divide by 100 function than this - /* - long q, r; - n = n + (n>>31 & 99); - q = (n >> 1) + (n >> 3) + (n >> 6) - (n >> 10) + - (n >> 12) + (n >> 13) - (n >> 16); - q = q + (q >> 20); - q = q >> 6; - r = n - q*100; - return q + ((r + 28) >> 7); - */ +#endif } //Unsigned divide by 100 unsigned long divu100(unsigned long n) { - //return (n / 100); - unsigned long q, r; - q = (n >> 1) + (n >> 3) + (n >> 6) - (n >> 10) + - (n >> 12) + (n >> 13) - (n >> 16); - q = q + (q >> 20); - q = q >> 6; - r = n - (q * 100); - return q + ((r + 28) >> 7); +#ifdef USE_LIBDIVIDE + return libdivide::libdivide_u32_do(n, &libdiv_u32_100); +#else + return (n / 100); +#endif } + //Return x percent of y //This is a relatively fast approximation of a percentage value. unsigned long percentage(byte x, unsigned long y) { - return (y * x) / 100; //For some reason this is faster - //return divu100(y * x); +#ifdef USE_LIBDIVIDE + return libdivide::libdivide_u32_do((y * x), &libdiv_u32_100); +#else + return (y * x) / 100; +#endif } //Same as above, but 0.5% accuracy unsigned long halfPercentage(byte x, unsigned long y) { +#ifdef USE_LIBDIVIDE + return libdivide::libdivide_u32_do((y * x), &libdiv_u32_200); +#else return (y * x) / 200; +#endif } /*