diff --git a/Makefile.am b/Makefile.am index 9784828..bf4ccc3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -214,6 +214,7 @@ GenOrdAST_SOURCES = pregen/GenOrdAST.hs $(pregen_sources) GenTagAST_SOURCES = pregen/GenTagAST.hs $(pregen_sources) rangetest_SOURCES = rangetest.c +rangetest_CFLAGS = -Wall rangetest_LDFLAGS = -lm #The programs to actually build: diff --git a/rangetest.c b/rangetest.c index 450f970..1b72687 100644 --- a/rangetest.c +++ b/rangetest.c @@ -220,15 +220,6 @@ int main(int argc, char** argv) check_all(2147483647,32); check_all(9223372036854775807,64); - testf(occam_mul_int8_t(127,127,"")); - testf(occam_mul_int8_t(2,127,"")); - testf(occam_mul_int8_t(127,127,"")); - testf(occam_mul_int8_t(127,-128,"")); - testf(occam_mul_int8_t(-128,-128,"")); - testf(occam_mul_int8_t(-1,-128,"")); - testp(-128,occam_mul_int8_t(1,-128,"")); - //TODO test multiply like the others - test_commutative(int8_t,occam_add_int8_t,add); test_commutative(int8_t,occam_mul_int8_t,mult); diff --git a/support/tock_support.h b/support/tock_support.h index f8c1bd4..0d99cc1 100644 --- a/support/tock_support.h +++ b/support/tock_support.h @@ -141,66 +141,27 @@ static inline int occam_check_retype (int src, int dest, const char *pos) { static inline type occam_subtr_##type (type, type, const char *) occam_unused; \ static inline type occam_subtr_##type (type a, type b, const char *pos) { return a - b;} -//Here is the plan: -// - For any values that are smaller than sizeof(long), cast them to long and check that way (TODO). -// - For all other values, split the number. Take N to be the length of the word -// and n to be N/2. Split the bits into top(A|B) and bottom(A|B) So we have: -//A = topA*2^n + bottomA -//B = topB*2^n + bottomB -//A*B = (topA*2^n + bottomA) * (topB*2^n + bottomB) -// = topA*topB*2^N + 2^n*(topA*bottomB + topB*bottomA) + (bottomA*bottomB) -// -//If topA*topB is non-zero, the multiplication will definitely overflow. So -//the multiplication can only be valid if either topA or topB is zero. -//Then we can see if the middle bracketed multiplication is >= 2^n, in which case -//the calculation would also overflow. Also, given that either topA or topB is zero, -//only one of the components of the bracketed sum is non-zero. Finally we do an occam add-style addition -//of the middle and end, again checking for overflow. - -#define abs(x) ((x) < 0 ? -x : x) - -/* This is my other attempt at the function, but it turned out slower: - - const utype topA = (utype)abs(a) >> (sizeof(type)*CHAR_BIT/2); \ - const utype topB = (utype)abs(b) >> (sizeof(type)*CHAR_BIT/2); \ - const utype bottomA = (utype)abs(a) & (((utype)1<<(sizeof(type)*CHAR_BIT/2))-1); \ - const utype bottomB = (utype)abs(b) & (((utype)1<<(sizeof(type)*CHAR_BIT/2))-1); \ - const utype pos_res = ((a > 0 && b > 0) || (a < 0 && b < 0)) ? 1 : 0; \ - if (topA != 0 && topB != 0) { \ - occam_stop(pos,3,"integer overflow when doing %d * %d", a, b); \ - } else { \ - const utype mid = topA != 0 ? topA*bottomB : topB*bottomA; \ - const utype mid_shift = mid << (sizeof(type)*CHAR_BIT/2); \ - const utype low = bottomA*bottomB; \ - if ((mid>>((utype)1<<(sizeof(type)*CHAR_BIT/2))==0)&&(((utype)__MAX(type))+1-pos_res-mid_shift>=low)) {\ - return (pos_res == 1 ? (type)(mid_shift+low) : -(type)mid_shift-(type)low); \ - } else { \ - occam_stop(pos,3,"integer overflow when doing %d * %d", a, b); \ - } \ - } \ - } -*/ - - -#define MAKE_MUL(type,utype) \ +#define MAKE_MUL(type) \ static inline type occam_mul_##type (type, type, const char *) occam_unused; \ static inline type occam_mul_##type (const type a, const type b, const char *pos) { \ - if (( (a < 0 ? -a : a) >> ((sizeof(type)*CHAR_BIT/2)-1) \ - | (b < 0 ? -b : b) >> ((sizeof(type)*CHAR_BIT/2)-1)) == 0) { \ - /*overflow not possible on such small numbers*/ \ - return a * b; \ - } else if (b == 0) { \ - return 0; \ - } else { \ + if (sizeof(type) < sizeof(long)) /*should be statically known*/ { \ + const long r = (long)a * (long) b; \ + if (r < (long)__MIN(type) || r > (long)__MAX(type)) { \ + occam_stop(pos, 3, "integer overflow when doing %d * %d", a, b); \ + } else { \ + return (type)r; \ + } \ + } else { \ + /* Taken from: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg326431.html */ \ const type r = a * b; \ - /* Taken from: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg326431.html */ \ - if (r / b != a) { \ - occam_stop(pos, 3, "integer overflow when doing %d * %d", a, b); \ - } else { \ + if (b != 0 && r / b != a) { \ + occam_stop(pos, 3, "integer overflow when doing %d * %d", a, b); \ + } else { \ return r; \ - } \ + } \ } \ } + #define MAKE_MULF(type) \ static inline type occam_mul_##type (type, type, const char *) occam_unused; \ static inline type occam_mul_##type (type a, type b, const char *pos) { return a * b;} @@ -302,7 +263,7 @@ static inline int occam_check_retype (int src, int dest, const char *pos) { MAKE_RANGE_CHECK(type,flag) \ MAKE_ADD(type) \ MAKE_SUBTR(type) \ - MAKE_MUL(type,utype) \ + MAKE_MUL(type) \ MAKE_DIV(type) \ MAKE_REM(type) \ MAKE_NEGATE(type) \ @@ -315,7 +276,7 @@ static inline int occam_check_retype (int src, int dest, const char *pos) { MAKE_RANGE_CHECK(uint8_t, "%d") MAKE_ADD(uint8_t) MAKE_SUBTR(uint8_t) -MAKE_MUL(uint8_t,uint8_t) +MAKE_MUL(uint8_t) MAKE_DIV(uint8_t) MAKE_SHIFT(uint8_t,uint8_t) MAKE_PLUS(uint8_t)