diff --git a/C/absmi.c b/C/absmi.c index 538d9ec38..e081a1e09 100644 --- a/C/absmi.c +++ b/C/absmi.c @@ -10257,7 +10257,7 @@ Yap_absmi(int inp) if (IsIntTerm(d0) && IsIntTerm(d1)) { Int i2 = IntOfTerm(d1); if (i2 < 0) - d0 = MkIntegerTerm(IntOfTerm(d0) >> -i2); + d0 = MkIntegerTerm(SLR(IntOfTerm(d0), -i2)); else d0 = do_sll(IntOfTerm(d0),i2); } @@ -10343,7 +10343,7 @@ Yap_absmi(int inp) if (IsIntTerm(d0)) { Int i2 = IntOfTerm(d0); if (i2 < 0) - d0 = MkIntegerTerm(d1 >> -i2); + d0 = MkIntegerTerm(SLR(d1, -i2)); else d0 = do_sll(d1,i2); } @@ -10388,7 +10388,7 @@ Yap_absmi(int inp) if (IsIntTerm(d0) && IsIntTerm(d1)) { Int i2 = IntOfTerm(d1); if (i2 < 0) - d0 = MkIntegerTerm(IntOfTerm(d0) >> -i2); + d0 = MkIntegerTerm(SLR(IntOfTerm(d0), -i2)); else d0 = do_sll(IntOfTerm(d0),i2); } @@ -10481,7 +10481,7 @@ Yap_absmi(int inp) if (IsIntTerm(d0)) { Int i2 = IntOfTerm(d0); if (i2 < 0) - d0 = MkIntegerTerm(d1 >> -i2); + d0 = MkIntegerTerm(SLR(d1, -i2)); else d0 = do_sll(d1,i2); } @@ -10531,7 +10531,7 @@ Yap_absmi(int inp) if (i2 < 0) d0 = do_sll(IntOfTerm(d0), -i2); else - d0 = MkIntTerm(IntOfTerm(d0) >> i2); + d0 = MkIntTerm(SLR(IntOfTerm(d0), i2)); } else { saveregs(); @@ -10576,7 +10576,7 @@ Yap_absmi(int inp) { Int d1 = PREG->u.xxn.c; if (IsIntTerm(d0)) { - d0 = MkIntTerm(IntOfTerm(d0) >> d1); + d0 = MkIntTerm(SLR(IntOfTerm(d0), d1)); } else { saveregs(); @@ -10617,7 +10617,7 @@ Yap_absmi(int inp) if (i2 < 0) d0 = do_sll(d1, -i2); else - d0 = MkIntegerTerm(d1 >> i2); + d0 = MkIntegerTerm(SLR(d1, i2)); } else { saveregs(); @@ -10662,7 +10662,7 @@ Yap_absmi(int inp) if (i2 < 0) d0 = do_sll(IntOfTerm(d0), -i2); else - d0 = MkIntTerm(IntOfTerm(d0) >> i2); + d0 = MkIntTerm(SLR(IntOfTerm(d0), i2)); } else { saveregs(); @@ -10710,7 +10710,7 @@ Yap_absmi(int inp) { Int d1 = PREG->u.yxn.c; if (IsIntTerm(d0)) { - d0 = MkIntTerm(IntOfTerm(d0) >> d1); + d0 = MkIntTerm(SLR(IntOfTerm(d0), d1)); } else { saveregs(); @@ -10753,7 +10753,7 @@ Yap_absmi(int inp) if (i2 < 0) d0 = do_sll(d1, -i2); else - d0 = MkIntegerTerm(d1 >> i2); + d0 = MkIntegerTerm(SLR(d1, i2)); } else { saveregs(); diff --git a/H/arith2.h b/H/arith2.h index 528842106..9ee698391 100644 --- a/H/arith2.h +++ b/H/arith2.h @@ -69,6 +69,12 @@ sub_int(Int i, Int j) #endif } +inline static Int +SLR(Int i, Int shift) +{ + return (shift < sizeof(Int)*8-1 ? shift : (i >= 0 ? 0 : -1)); +} + #ifdef __GNUC__ #ifdef __i386__ #define DO_MULTI() { Int tmp1; \ @@ -114,28 +120,56 @@ times_int(Int i1, Int i2) { } -#if USE_GMP -static inline int -sl_overflow(Int i,Int j) +#ifndef __GNUC__X +static int +clrsb(Int i) { - Int x = (8*sizeof(CELL)-2)-j; - CELL t = (1<>= 32; +#endif + if (i < (Int)(0x10000)) {j += 16;} + else i >>= 16; + if (i < (Int)(0x100)) {j += 8;} + else i >>= 8; + if (i < (Int)(0x10)) {j += 4;} + else i >>= 4; + if (i < (Int)(0x4)) {j += 2;} + else i >>= 2; + if (i < (Int)(0x2)) j++; + return j; } #endif + inline static Term -do_sll(Int i, Int j) +do_sll(Int i, Int j) /* j > 0 */ { + Int k; #ifdef USE_GMP - if (sl_overflow(i,j)) { - return Yap_gmp_sll_ints(i, j); - } + if ( +#ifdef __GNUC__X +#if SIZEOF_LONG_INT < SIZEOF_INT_P + __builtin_clrsbll(i) +#else + __builtin_clrsbl(i) #endif +#else + clrsb(i) +#endif + > j) + RINT(i << j); + return Yap_gmp_sll_ints(i, j); +#else RINT(i << j); +#endif } @@ -459,14 +493,16 @@ p_sll(Term t1, Term t2) { switch (ETypeOfTerm(t2)) { case long_int_e: /* two integers */ - if (IntegerOfTerm(t2) < 0) { - Int i2 = IntegerOfTerm(t2); - if (i2 == Int_MIN) { - return Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2, ">>/2"); + { Int i2 = IntegerOfTerm(t2); + + if (i2 <= 0) { + if (i2 == Int_MIN) { + return Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2, ">>/2"); + } + RINT(SLR(IntegerOfTerm(t1), -i2)); } - RINT(IntegerOfTerm(t1) >> -i2); + return do_sll(IntegerOfTerm(t1),i2); } - return do_sll(IntegerOfTerm(t1),IntegerOfTerm(t2)); case double_e: return Yap_ArithError(TYPE_ERROR_INTEGER, t2, "<>/2"); + { Int i2 = IntegerOfTerm(t2); + + if (i2 < 0) { + if (i2 == Int_MIN) { + return Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2, ">>/2"); + } + return do_sll(IntegerOfTerm(t1), -i2); } - return do_sll(IntegerOfTerm(t1), -i2); + RINT(SLR(IntegerOfTerm(t1), i2)); } - RINT(IntegerOfTerm(t1) >> IntegerOfTerm(t2)); case double_e: return Yap_ArithError(TYPE_ERROR_INTEGER, t2, ">>/2"); case big_int_e: