fixed some problems in bigint multiplication
This commit is contained in:
parent
346131b3e3
commit
415921d4a7
@ -260,7 +260,7 @@ PROCESS TESTING
|
|||||||
|
|
||||||
(1 + 2) dump.
|
(1 + 2) dump.
|
||||||
##(-2305843009213693952 * 2305843009213693952) dump.
|
##(-2305843009213693952 * 2305843009213693952) dump.
|
||||||
(((-2305843009213693952 - 10) * (-2305843009213693952 - 10) *(-2305843009213693952 - 10) * (-2305843009213693952 - 10) * 255) * ((-2305843009213693952 - 10) * (-2305843009213693952 - 10) *(-2305843009213693952 - 10) * (-2305843009213693952 - 10) * 255)) dump.
|
## (((-2305843009213693952 - 10) * (-2305843009213693952 - 10) *(-2305843009213693952 - 10) * (-2305843009213693952 - 10) * 255) * ((-2305843009213693952 - 10) * (-2305843009213693952 - 10) *(-2305843009213693952 - 10) * (-2305843009213693952 - 10) * 255)) dump.
|
||||||
##((-2305843009213693952 - 10) * (-2305843009213693952 - 10) *(-2305843009213693952 - 10) * (-2305843009213693952 - 10) * 255) dump.
|
##((-2305843009213693952 - 10) * (-2305843009213693952 - 10) *(-2305843009213693952 - 10) * (-2305843009213693952 - 10) * 255) dump.
|
||||||
|
|
||||||
##(-16rFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF * 1) dump.
|
##(-16rFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF * 1) dump.
|
||||||
|
@ -68,24 +68,40 @@ static STIX_INLINE int oow_mul_overflow (stix_oow_t a, stix_oow_t b, stix_oow_t*
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (STIX_SIZEOF_OOI_T == STIX_SIZEOF_INT) && defined(STIX_HAVE_BUILTIN_SMUL_OVERFLOW)
|
#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)
|
# define smooi_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)
|
#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)
|
# define smooi_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)
|
#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)
|
# define smooi_mul_overflow(a,b,c) __builtin_smulll_overflow(a,b,c)
|
||||||
#else
|
#else
|
||||||
static STIX_INLINE int ooi_mul_overflow (stix_ooi_t a, stix_ooi_t b, stix_ooi_t* c)
|
static STIX_INLINE int smooi_mul_overflow (stix_ooi_t a, stix_ooi_t b, stix_ooi_t* c)
|
||||||
{
|
{
|
||||||
#if (STIX_SIZEOF_UINTMAX_T > STIX_SIZEOF_OOI_T)
|
#if (STIX_SIZEOF_UINTMAX_T > STIX_SIZEOF_OOI_T)
|
||||||
stix_intmax_t k;
|
stix_intmax_t k;
|
||||||
|
|
||||||
|
STIX_ASSERT (STIX_IN_SMOOI_RANGE(a));
|
||||||
|
STIX_ASSERT (STIX_IN_SMOOI_RANGE(b));
|
||||||
|
|
||||||
k = (stix_intmax_t)a * (stix_intmax_t)b;
|
k = (stix_intmax_t)a * (stix_intmax_t)b;
|
||||||
*c = (stix_ooi_t)k;
|
*c = (stix_ooi_t)k;
|
||||||
|
|
||||||
return k > STIX_TYPE_MAX(stix_ooi_t) || k < STIX_TYPE_MIN(stix_ooi_t);
|
return k > STIX_TYPE_MAX(stix_ooi_t) || k < STIX_TYPE_MIN(stix_ooi_t);
|
||||||
#else
|
#else
|
||||||
/* TODO: fix this */
|
|
||||||
#error not implemented
|
stix_ooi_t ua, ub;
|
||||||
|
|
||||||
|
STIX_ASSERT (STIX_IN_SMOOI_RANGE(a));
|
||||||
|
STIX_ASSERT (STIX_IN_SMOOI_RANGE(b));
|
||||||
|
|
||||||
*c = a * b;
|
*c = a * b;
|
||||||
return b > 0 && a > STIX_TYPE_MAX(stix_ooi_t) / b; /* works for unsigned types only */
|
|
||||||
|
ub = (b >= 0)? b: -b;
|
||||||
|
ua = (a >= 0)? a: -a;
|
||||||
|
|
||||||
|
/* though this fomula basically works for unsigned types in principle,
|
||||||
|
* the values used here are all absolute values and they fall in
|
||||||
|
* a safe range to apply this fomula */
|
||||||
|
return ub > 0 && ua > STIX_TYPE_MAX(stix_ooi_t) / ub;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -143,6 +159,7 @@ static STIX_INLINE stix_oop_t make_bigint_with_ooi (stix_t* stix, stix_ooi_t i)
|
|||||||
#if defined(USE_FULL_WORD)
|
#if defined(USE_FULL_WORD)
|
||||||
stix_oow_t w;
|
stix_oow_t w;
|
||||||
|
|
||||||
|
STIX_ASSERT (STIX_ZIEOF(stix_oow_t) == STIX_SIZEOF(atom_t));
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
{
|
{
|
||||||
w = i;
|
w = i;
|
||||||
@ -150,7 +167,7 @@ static STIX_INLINE stix_oop_t make_bigint_with_ooi (stix_t* stix, stix_ooi_t i)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The caller must ensure that i is grater than the smallest value
|
/* The caller must ensure that i is greater than the smallest value
|
||||||
* that stix_ooi_t can represent. otherwise, the absolute value
|
* that stix_ooi_t can represent. otherwise, the absolute value
|
||||||
* cannot be held in stix_ooi_t. */
|
* cannot be held in stix_ooi_t. */
|
||||||
STIX_ASSERT (i > STIX_TYPE_MIN(stix_ooi_t));
|
STIX_ASSERT (i > STIX_TYPE_MIN(stix_ooi_t));
|
||||||
@ -779,8 +796,7 @@ 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_OOP_IS_SMOOI(x) && STIX_OOP_IS_SMOOI(y))
|
||||||
{
|
{
|
||||||
/*#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
|
||||||
#if STIX_SIZEOF_INTMAX_T <= STIX_SIZEOF_OOI_T
|
|
||||||
stix_intmax_t i;
|
stix_intmax_t i;
|
||||||
i = (stix_intmax_t)STIX_OOP_TO_SMOOI(x) * (stix_intmax_t)STIX_OOP_TO_SMOOI(y);
|
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);
|
if (STIX_IN_SMOOI_RANGE(i)) return STIX_SMOOI_TO_OOP((stix_ooi_t)i);
|
||||||
@ -791,30 +807,27 @@ stix_oop_t stix_mulints (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
|||||||
|
|
||||||
xv = STIX_OOP_TO_SMOOI(x);
|
xv = STIX_OOP_TO_SMOOI(x);
|
||||||
yv = STIX_OOP_TO_SMOOI(y);
|
yv = STIX_OOP_TO_SMOOI(y);
|
||||||
if (ooi_mul_overflow (xv, yv, &i))
|
if (smooi_mul_overflow (xv, yv, &i))
|
||||||
{
|
{
|
||||||
/* overflowed
|
/* overflowed - convert x and y normal objects and carry on */
|
||||||
* -----------------------------------------------------
|
|
||||||
* no need to call stix_pushtmp() on x and y as they are
|
/* no need to call stix_pushtmp before creating x because
|
||||||
* known to be small integers and we don't need them.
|
* xv and yv contains actual values needed */
|
||||||
* actual values are all in xv and yv. */
|
x = make_bigint_with_ooi (stix, xv);
|
||||||
if (!(x = make_bigint_with_ooi (stix, xv)) ||
|
if (!x) return STIX_NULL;
|
||||||
!(y = make_bigint_with_ooi (stix, yv))) return STIX_NULL;
|
|
||||||
|
stix_pushtmp (stix, &x); /* protect x made above */
|
||||||
|
y = make_bigint_with_ooi (stix, yv);
|
||||||
|
stix_poptmp (stix);
|
||||||
|
if (!y) return STIX_NULL;
|
||||||
|
|
||||||
|
goto normal;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (STIX_IN_SMOOI_RANGE(i)) return STIX_SMOOI_TO_OOP(i);
|
if (STIX_IN_SMOOI_RANGE(i)) return STIX_SMOOI_TO_OOP(i);
|
||||||
return make_bigint_with_ooi (stix, 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
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -869,6 +882,7 @@ stix_oop_t stix_mulints (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
|||||||
if (!is_integer(stix,y)) goto oops_einval;
|
if (!is_integer(stix,y)) goto oops_einval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normal:
|
||||||
z = multiply_unsigned_integers (stix, x, y);
|
z = multiply_unsigned_integers (stix, x, y);
|
||||||
if (!z) return STIX_NULL;
|
if (!z) return STIX_NULL;
|
||||||
if (STIX_OBJ_GET_CLASS(x) != STIX_OBJ_GET_CLASS(y))
|
if (STIX_OBJ_GET_CLASS(x) != STIX_OBJ_GET_CLASS(y))
|
||||||
|
Loading…
Reference in New Issue
Block a user