Changed multiply back to the very simplest implementation
This commit is contained in:
parent
ecf840fe9f
commit
084fcad1fe
|
@ -214,6 +214,7 @@ GenOrdAST_SOURCES = pregen/GenOrdAST.hs $(pregen_sources)
|
||||||
GenTagAST_SOURCES = pregen/GenTagAST.hs $(pregen_sources)
|
GenTagAST_SOURCES = pregen/GenTagAST.hs $(pregen_sources)
|
||||||
|
|
||||||
rangetest_SOURCES = rangetest.c
|
rangetest_SOURCES = rangetest.c
|
||||||
|
rangetest_CFLAGS = -Wall
|
||||||
rangetest_LDFLAGS = -lm
|
rangetest_LDFLAGS = -lm
|
||||||
|
|
||||||
#The programs to actually build:
|
#The programs to actually build:
|
||||||
|
|
|
@ -220,15 +220,6 @@ int main(int argc, char** argv)
|
||||||
check_all(2147483647,32);
|
check_all(2147483647,32);
|
||||||
check_all(9223372036854775807,64);
|
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_add_int8_t,add);
|
||||||
test_commutative(int8_t,occam_mul_int8_t,mult);
|
test_commutative(int8_t,occam_mul_int8_t,mult);
|
||||||
|
|
||||||
|
|
|
@ -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, type, const char *) occam_unused; \
|
||||||
static inline type occam_subtr_##type (type a, type b, const char *pos) { return a - b;}
|
static inline type occam_subtr_##type (type a, type b, const char *pos) { return a - b;}
|
||||||
|
|
||||||
//Here is the plan:
|
#define MAKE_MUL(type) \
|
||||||
// - 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) \
|
|
||||||
static inline type occam_mul_##type (type, type, const char *) occam_unused; \
|
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) { \
|
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) \
|
if (sizeof(type) < sizeof(long)) /*should be statically known*/ { \
|
||||||
| (b < 0 ? -b : b) >> ((sizeof(type)*CHAR_BIT/2)-1)) == 0) { \
|
const long r = (long)a * (long) b; \
|
||||||
/*overflow not possible on such small numbers*/ \
|
if (r < (long)__MIN(type) || r > (long)__MAX(type)) { \
|
||||||
return a * b; \
|
occam_stop(pos, 3, "integer overflow when doing %d * %d", a, b); \
|
||||||
} else if (b == 0) { \
|
} else { \
|
||||||
return 0; \
|
return (type)r; \
|
||||||
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
const type r = a * b; \
|
|
||||||
/* Taken from: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg326431.html */ \
|
/* Taken from: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg326431.html */ \
|
||||||
if (r / b != a) { \
|
const type r = a * b; \
|
||||||
|
if (b != 0 && r / b != a) { \
|
||||||
occam_stop(pos, 3, "integer overflow when doing %d * %d", a, b); \
|
occam_stop(pos, 3, "integer overflow when doing %d * %d", a, b); \
|
||||||
} else { \
|
} else { \
|
||||||
return r; \
|
return r; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAKE_MULF(type) \
|
#define MAKE_MULF(type) \
|
||||||
static inline type occam_mul_##type (type, type, const char *) occam_unused; \
|
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;}
|
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_RANGE_CHECK(type,flag) \
|
||||||
MAKE_ADD(type) \
|
MAKE_ADD(type) \
|
||||||
MAKE_SUBTR(type) \
|
MAKE_SUBTR(type) \
|
||||||
MAKE_MUL(type,utype) \
|
MAKE_MUL(type) \
|
||||||
MAKE_DIV(type) \
|
MAKE_DIV(type) \
|
||||||
MAKE_REM(type) \
|
MAKE_REM(type) \
|
||||||
MAKE_NEGATE(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_RANGE_CHECK(uint8_t, "%d")
|
||||||
MAKE_ADD(uint8_t)
|
MAKE_ADD(uint8_t)
|
||||||
MAKE_SUBTR(uint8_t)
|
MAKE_SUBTR(uint8_t)
|
||||||
MAKE_MUL(uint8_t,uint8_t)
|
MAKE_MUL(uint8_t)
|
||||||
MAKE_DIV(uint8_t)
|
MAKE_DIV(uint8_t)
|
||||||
MAKE_SHIFT(uint8_t,uint8_t)
|
MAKE_SHIFT(uint8_t,uint8_t)
|
||||||
MAKE_PLUS(uint8_t)
|
MAKE_PLUS(uint8_t)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user