diff --git a/stix/kernel/test-005.st b/stix/kernel/test-005.st index aa33ca4..a9a9422 100644 --- a/stix/kernel/test-005.st +++ b/stix/kernel/test-005.st @@ -264,7 +264,8 @@ PROCESS TESTING ##((-2305843009213693952 - 10) * (-2305843009213693952 - 10) *(-2305843009213693952 - 10) * (-2305843009213693952 - 10) * 255) dump. ##(-16rFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF * 1) dump. - ((-2305843009213693952 * -1) - 1 + 2) dump. + ##((-2305843009213693952 * -1) - 1 + 2) dump. + ((-2305843009213693952 * -2305843009213693952 * 2305843009213693952 * 2305843009213693952 * 2305843009213693952) - 1 + 2) dump. " FFI isNil dump. FFI notNil dump. diff --git a/stix/lib/bigint.c b/stix/lib/bigint.c index 8dc7f77..7c6940f 100644 --- a/stix/lib/bigint.c +++ b/stix/lib/bigint.c @@ -67,6 +67,29 @@ static STIX_INLINE int oow_mul_overflow (stix_oow_t a, stix_oow_t b, stix_oow_t* } #endif +#if (STIX_SIZEOF_OOI_T == STIX_SIZEOF_INT) && defined(STIX_HAVE_BUILTIN_SMUL_OVERFLOW) +# define ooi_mul_overflow(a,b,c) __builtin_smul_overflow(a,b,c) +#elif (STIX_SIZEOF_OOI_T == STIX_SIZEOF_LONG) && defined(STIX_HAVE_BUILTIN_SMULL_OVERFLOW) +# define ooi_mul_overflow(a,b,c) __builtin_smull_overflow(a,b,c) +#elif (STIX_SIZEOF_OOI_T == STIX_SIZEOF_LONG_LONG) && defined(STIX_HAVE_BUILTIN_SMULLL_OVERFLOW) +# define ooi_mul_overflow(a,b,c) __builtin_smulll_overflow(a,b,c) +#else +static STIX_INLINE int ooi_mul_overflow (stix_ooi_t a, stix_ooi_t b, stix_ooi_t* c) +{ +#if (STIX_SIZEOF_UINTMAX_T > STIX_SIZEOF_OOI_T) + stix_intmax_t k; + k = (stix_intmax_t)a * (stix_intmax_t)b; + *c = (stix_ooi_t)k; + return k > STIX_TYPE_MAX(stix_ooi_t) || k < STIX_TYPE_MIN(stix_ooi_t); +#else +/* TODO: fix this */ +#error not implemented + *c = a * b; + return b > 0 && a > STIX_TYPE_MAX(stix_ooi_t) / b; /* works for unsigned types only */ +#endif +} +#endif + #if (SIZEOF_ATOM_T == STIX_SIZEOF_INT) && defined(STIX_HAVE_BUILTIN_UADD_OVERFLOW) # define atom_add_overflow(a,b,c) __builtin_uadd_overflow(a,b,c) #elif (SIZEOF_ATOM_T == STIX_SIZEOF_LONG) && defined(STIX_HAVE_BUILTIN_UADDL_OVERFLOW) @@ -158,12 +181,12 @@ static STIX_INLINE stix_oop_t make_bigint_with_ooi (stix_t* stix, stix_ooi_t i) static STIX_INLINE stix_oop_t make_bigint_with_intmax (stix_t* stix, stix_intmax_t v) { - /* this is not a generic function. it can't handle v - * if it's STIX_TYPE_MIN(stix_intmax_t) */ stix_oow_t len; atom_t buf[STIX_SIZEOF_INTMAX_T / SIZEOF_ATOM_T]; stix_uintmax_t ui; + /* this is not a generic function. it can't handle v + * if it's STIX_TYPE_MIN(stix_intmax_t) */ STIX_ASSERT (v > STIX_TYPE_MIN(stix_intmax_t)); ui = (v >= 0)? v: -v; @@ -175,6 +198,15 @@ static STIX_INLINE stix_oop_t make_bigint_with_intmax (stix_t* stix, stix_intmax } while (ui > 0); +{ int i; +printf ("MKBI-INTMAX=>"); +for (i = len; i > 0;) +{ +printf ("%016lX ", (unsigned long)buf[--i]); +} +printf ("\n"); +} + return stix_instantiate (stix, ((v >= 0)? stix->_large_positive_integer: stix->_large_negative_integer), buf, len); } @@ -747,19 +779,42 @@ stix_oop_t stix_mulints (stix_t* stix, stix_oop_t x, stix_oop_t y) if (STIX_OOP_IS_SMOOI(x) && STIX_OOP_IS_SMOOI(y)) { - #if STIX_SIZEOF_INTMAX_T > STIX_SIZEOF_OOI_T + /*#if STIX_SIZEOF_INTMAX_T > STIX_SIZEOF_OOI_T*/ /* TOOD: uncomment this line and remove the next line after #else block has been tested */ + #if STIX_SIZEOF_INTMAX_T <= STIX_SIZEOF_OOI_T stix_intmax_t i; - i = (stix_intmax_t)STIX_OOP_TO_SMOOI(x) * (stix_intmax_t)STIX_OOP_TO_SMOOI(y); if (STIX_IN_SMOOI_RANGE(i)) return STIX_SMOOI_TO_OOP((stix_ooi_t)i); - return make_bigint_with_intmax (stix, i); #else stix_ooi_t i; + stix_ooi_t xv, yv; + + xv = STIX_OOP_TO_SMOOI(x); + yv = STIX_OOP_TO_SMOOI(y); + if (ooi_mul_overflow (xv, yv, &i)) + { + /* overflowed + * ----------------------------------------------------- + * no need to call stix_pushtmp() on x and y as they are + * known to be small integers and we don't need them. + * actual values are all in xv and yv. */ + if (!(x = make_bigint_with_ooi (stix, xv)) || + !(y = make_bigint_with_ooi (stix, yv))) return STIX_NULL; + } + else + { + if (STIX_IN_SMOOI_RANGE(i)) return STIX_SMOOI_TO_OOP(i); + return make_bigint_with_ooi (stix, i); + } + + /* + stix_ooi_t i; + i = STIX_OOP_TO_SMOOI(x) * STIX_OOP_TO_SMOOI(y); if (STIX_IN_SMOOI_RANGE(i)) return STIX_SMOOI_TO_OOP(i); return make_bigint_with_ooi (stix, i); + */ #endif } else diff --git a/stix/lib/stix-cmn.h b/stix/lib/stix-cmn.h index 4393e94..390c5e8 100644 --- a/stix/lib/stix-cmn.h +++ b/stix/lib/stix-cmn.h @@ -544,6 +544,7 @@ typedef stix_ucs_t stix_oocs_t; #if __has_builtin(__builtin_ctz) #define STIX_HAVE_BUILTIN_CTZ #endif + #if __has_builtin(__builtin_uadd_overflow) #define STIX_HAVE_BUILTIN_UADD_OVERFLOW #endif @@ -562,9 +563,31 @@ typedef stix_ucs_t stix_oocs_t; #if __has_builtin(__builtin_umulll_overflow) #define STIX_HAVE_BUILTIN_UMULLL_OVERFLOW #endif - + + #if __has_builtin(__builtin_sadd_overflow) + #define STIX_HAVE_BUILTIN_SADD_OVERFLOW + #endif + #if __has_builtin(__builtin_saddl_overflow) + #define STIX_HAVE_BUILTIN_SADDL_OVERFLOW + #endif + #if __has_builtin(__builtin_saddll_overflow) + #define STIX_HAVE_BUILTIN_SADDLL_OVERFLOW + #endif + #if __has_builtin(__builtin_smul_overflow) + #define STIX_HAVE_BUILTIN_SMUL_OVERFLOW + #endif + #if __has_builtin(__builtin_smull_overflow) + #define STIX_HAVE_BUILTIN_SMULL_OVERFLOW + #endif + #if __has_builtin(__builtin_smulll_overflow) + #define STIX_HAVE_BUILTIN_SMULLL_OVERFLOW + #endif #elif defined(__GNUC__) && defined(__GNUC_MINOR__) + #if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + #define STIX_HAVE_BUILTIN_CTZ + #endif + #if (__GNUC__ >= 5) #define STIX_HAVE_BUILTIN_UADD_OVERFLOW #define STIX_HAVE_BUILTIN_UADDL_OVERFLOW @@ -572,11 +595,15 @@ typedef stix_ucs_t stix_oocs_t; #define STIX_HAVE_BUILTIN_UMUL_OVERFLOW #define STIX_HAVE_BUILTIN_UMULL_OVERFLOW #define STIX_HAVE_BUILTIN_UMULLL_OVERFLOW + + #define STIX_HAVE_BUILTIN_SADD_OVERFLOW + #define STIX_HAVE_BUILTIN_SADDL_OVERFLOW + #define STIX_HAVE_BUILTIN_SADDLL_OVERFLOW + #define STIX_HAVE_BUILTIN_SMUL_OVERFLOW + #define STIX_HAVE_BUILTIN_SMULL_OVERFLOW + #define STIX_HAVE_BUILTIN_SMULLL_OVERFLOW #endif - #if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - #define STIX_HAVE_BUILTIN_CTZ - #endif #endif /* diff --git a/stix/lib/stix.h b/stix/lib/stix.h index dc4774b..02d5503 100644 --- a/stix/lib/stix.h +++ b/stix/lib/stix.h @@ -92,9 +92,10 @@ typedef struct stix_obj_byte_t* stix_oop_byte_t; typedef struct stix_obj_halfword_t* stix_oop_halfword_t; typedef struct stix_obj_word_t* stix_oop_word_t; -#define STIX_OOW_BITS (STIX_SIZEOF(stix_oow_t) * 8) -#define STIX_OOP_BITS (STIX_SIZEOF(stix_oop_t) * 8) -#define STIX_OOHW_BITS (STIX_SIZEOF(stix_oohw_t) * 8) +#define STIX_OOW_BITS (STIX_SIZEOF_OOW_T * 8) +#define STIX_OOI_BITS (STIX_SIZEOF_OOI_T * 8) +#define STIX_OOP_BITS (STIX_SIZEOF_OOP_T * 8) +#define STIX_OOHW_BITS (STIX_SIZEOF_OOHW_T * 8) /* * OOP encoding