added moo_inttouintmax and moo_inttointmax
This commit is contained in:
parent
99bca6a028
commit
3f2e39cf44
141
moo/lib/bigint.c
141
moo/lib/bigint.c
@ -371,10 +371,10 @@ int moo_inttoooi (moo_t* moo, moo_oop_t x, moo_ooi_t* i)
|
|||||||
moo_oow_t w;
|
moo_oow_t w;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = moo_inttooow (moo, x, &w);
|
n = moo_inttooow(moo, x, &w);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
MOO_ASSERT (moo, MOO_TYPE_MAX(moo_ooi_t) + MOO_TYPE_MIN(moo_ooi_t) == -1); /* assume 2's complement */
|
MOO_STATIC_ASSERT (MOO_TYPE_MAX(moo_ooi_t) + MOO_TYPE_MIN(moo_ooi_t) == -1); /* assume 2's complement */
|
||||||
if (w > (moo_oow_t)MOO_TYPE_MAX(moo_ooi_t) + 1)
|
if (w > (moo_oow_t)MOO_TYPE_MAX(moo_ooi_t) + 1)
|
||||||
{
|
{
|
||||||
moo_seterrnum (moo, MOO_ERANGE); /* not convertable. number too small */
|
moo_seterrnum (moo, MOO_ERANGE); /* not convertable. number too small */
|
||||||
@ -395,6 +395,121 @@ int moo_inttoooi (moo_t* moo, moo_oop_t x, moo_ooi_t* i)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (MOO_SIZEOF_UINTMAX_T == MOO_SIZEOF_OOW_T)
|
||||||
|
|
||||||
|
/* do nothing. required macros are defined in moo.h */
|
||||||
|
|
||||||
|
#elif (MOO_SIZEOF_UINTMAX_T == MOO_SIZEOF_OOW_T * 2)
|
||||||
|
static MOO_INLINE int bigint_to_uintmax (moo_t* moo, moo_oop_t num, moo_uintmax_t* w)
|
||||||
|
{
|
||||||
|
MOO_ASSERT (moo, MOO_OOP_IS_POINTER(num));
|
||||||
|
MOO_ASSERT (moo, MOO_POINTER_IS_PBIGINT(moo, num) || MOO_POINTER_IS_NBIGINT(moo, num));
|
||||||
|
|
||||||
|
#if (MOO_LIW_BITS == MOO_OOW_BITS)
|
||||||
|
MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(num) >= 1);
|
||||||
|
|
||||||
|
switch (MOO_OBJ_GET_SIZE(num))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
*w = ((moo_uintmax_t)MOO_OBJ_GET_WORD_SLOT(num)[0];
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
*w = ((moo_uintmax_t)MOO_OBJ_GET_WORD_SLOT(num)[0] << MOO_LIW_BITS) | MOO_OBJ_GET_WORD_SLOT(num)[1];
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto oops_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif (MOO_LIW_BITS == MOO_OOHW_BITS)
|
||||||
|
MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(num) >= 2);
|
||||||
|
switch (MOO_OBJ_GET_SIZE(num))
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
*w = ((moo_uintmax_t)MOO_OBJ_GET_HALFWORD_SLOT(num)[0] << MOO_LIW_BITS) | MOO_OBJ_GET_HALFWORD_SLOT(num)[1];
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
*w = ((moo_uintmax_t)MOO_OBJ_GET_HALFWORD_SLOT(num)[0] << MOO_LIW_BITS * 3) |
|
||||||
|
((moo_uintmax_t)MOO_OBJ_GET_HALFWORD_SLOT(num)[1] << MOO_LIW_BITS * 2) |
|
||||||
|
((moo_uintmax_t)MOO_OBJ_GET_HALFWORD_SLOT(num)[2] << MOO_LIW_BITS * 1) |
|
||||||
|
MOO_OBJ_GET_HALFWORD_SLOT(num)[3];
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto oops_range;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# error UNSUPPORTED LIW BIT SIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
done:
|
||||||
|
return (MOO_POINTER_IS_NBIGINT(moo, num))? -1: 1;
|
||||||
|
|
||||||
|
oops_range:
|
||||||
|
moo_seterrnum (moo, MOO_ERANGE);
|
||||||
|
return 0; /* not convertable */
|
||||||
|
}
|
||||||
|
|
||||||
|
int moo_inttouintmax (moo_t* moo, moo_oop_t x, moo_uintmax_t* w)
|
||||||
|
{
|
||||||
|
if (MOO_OOP_IS_SMOOI(x))
|
||||||
|
{
|
||||||
|
moo_ooi_t v;
|
||||||
|
|
||||||
|
v = MOO_OOP_TO_SMOOI(x);
|
||||||
|
if (v < 0)
|
||||||
|
{
|
||||||
|
*w = -v;
|
||||||
|
return -1; /* negative number negated - kind of an error */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*w = v;
|
||||||
|
return 1; /* zero or positive number */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moo_isbigint(moo, x)) return bigint_to_uintmax(moo, x, w);
|
||||||
|
|
||||||
|
moo_seterrbfmt (moo, MOO_EINVAL, "not an integer - %O", x);
|
||||||
|
return 0; /* not convertable - too big, too small, or not an integer */
|
||||||
|
}
|
||||||
|
|
||||||
|
int moo_inttointmax (moo_t* moo, moo_oop_t x, moo_intmax_t* i)
|
||||||
|
{
|
||||||
|
moo_uintmax_t w;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = moo_inttouintmax(moo, x, &w);
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
MOO_STATIC_ASSERT (MOO_TYPE_MAX(moo_intmax_t) + MOO_TYPE_MIN(moo_intmax_t) == -1); /* assume 2's complement */
|
||||||
|
if (w > (moo_uintmax_t)MOO_TYPE_MAX(moo_intmax_t) + 1)
|
||||||
|
{
|
||||||
|
moo_seterrnum (moo, MOO_ERANGE); /* not convertable. number too small */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*i = -w;
|
||||||
|
}
|
||||||
|
else if (n > 0)
|
||||||
|
{
|
||||||
|
if (w > MOO_TYPE_MAX(moo_intmax_t))
|
||||||
|
{
|
||||||
|
moo_seterrnum (moo, MOO_ERANGE); /* not convertable. number too big */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*i = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error UNSUPPORTED UINTMAX SIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
static MOO_INLINE moo_oop_t make_bigint_with_oow (moo_t* moo, moo_oow_t w)
|
static MOO_INLINE moo_oop_t make_bigint_with_oow (moo_t* moo, moo_oow_t w)
|
||||||
{
|
{
|
||||||
#if (MOO_LIW_BITS == MOO_OOW_BITS)
|
#if (MOO_LIW_BITS == MOO_OOW_BITS)
|
||||||
@ -2818,11 +2933,11 @@ moo_oop_t moo_bitatint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
|||||||
MOO_ASSERT (moo, MOO_OBJ_SIZE_BITS_MAX <= MOO_TYPE_MAX(moo_oow_t));
|
MOO_ASSERT (moo, MOO_OBJ_SIZE_BITS_MAX <= MOO_TYPE_MAX(moo_oow_t));
|
||||||
if (MOO_POINTER_IS_PBIGINT(moo, x))
|
if (MOO_POINTER_IS_PBIGINT(moo, x))
|
||||||
{
|
{
|
||||||
return MOO_SMOOI_TO_OOP (0);
|
return MOO_SMOOI_TO_OOP(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return MOO_SMOOI_TO_OOP (1);
|
return MOO_SMOOI_TO_OOP(1);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
xs = MOO_OBJ_GET_SIZE(x);
|
xs = MOO_OBJ_GET_SIZE(x);
|
||||||
@ -2843,11 +2958,11 @@ moo_oop_t moo_bitatint (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
|||||||
MOO_ASSERT (moo, sign == 0);
|
MOO_ASSERT (moo, sign == 0);
|
||||||
|
|
||||||
moo_pushvolat (moo, &x);
|
moo_pushvolat (moo, &x);
|
||||||
quo = moo_divints (moo, y, MOO_SMOOI_TO_OOP(MOO_LIW_BITS), 0, &rem);
|
quo = moo_divints(moo, y, MOO_SMOOI_TO_OOP(MOO_LIW_BITS), 0, &rem);
|
||||||
moo_popvolat (moo);
|
moo_popvolat (moo);
|
||||||
if (!quo) return MOO_NULL;
|
if (!quo) return MOO_NULL;
|
||||||
|
|
||||||
sign = integer_to_oow (moo, quo, &wp);
|
sign = integer_to_oow(moo, quo, &wp);
|
||||||
MOO_ASSERT (moo, sign >= 0);
|
MOO_ASSERT (moo, sign >= 0);
|
||||||
if (sign == 0)
|
if (sign == 0)
|
||||||
{
|
{
|
||||||
@ -3127,7 +3242,7 @@ moo_oop_t moo_bitorints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
|||||||
if (v == 0) return clone_bigint(moo, y, MOO_OBJ_GET_SIZE(y));
|
if (v == 0) return clone_bigint(moo, y, MOO_OBJ_GET_SIZE(y));
|
||||||
|
|
||||||
moo_pushvolat (moo, &y);
|
moo_pushvolat (moo, &y);
|
||||||
x = make_bigint_with_ooi (moo, v);
|
x = make_bigint_with_ooi(moo, v);
|
||||||
moo_popvolat (moo);
|
moo_popvolat (moo);
|
||||||
if (!x) return MOO_NULL;
|
if (!x) return MOO_NULL;
|
||||||
|
|
||||||
@ -3143,7 +3258,7 @@ moo_oop_t moo_bitorints (moo_t* moo, moo_oop_t x, moo_oop_t y)
|
|||||||
if (v == 0) return clone_bigint(moo, x, MOO_OBJ_GET_SIZE(x));
|
if (v == 0) return clone_bigint(moo, x, MOO_OBJ_GET_SIZE(x));
|
||||||
|
|
||||||
moo_pushvolat (moo, &x);
|
moo_pushvolat (moo, &x);
|
||||||
y = make_bigint_with_ooi (moo, v);
|
y = make_bigint_with_ooi(moo, v);
|
||||||
moo_popvolat (moo);
|
moo_popvolat (moo);
|
||||||
if (!x) return MOO_NULL;
|
if (!x) return MOO_NULL;
|
||||||
|
|
||||||
@ -3722,30 +3837,30 @@ static MOO_INLINE moo_oop_t rshift_negative_bigint_and_normalize (moo_t* moo, mo
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
moo_pushvolat (moo, &y);
|
moo_pushvolat (moo, &y);
|
||||||
z = rshift_negative_bigint (moo, x, shift);
|
z = rshift_negative_bigint(moo, x, shift);
|
||||||
moo_popvolat (moo);
|
moo_popvolat (moo);
|
||||||
if (!z) return MOO_NULL;
|
if (!z) return MOO_NULL;
|
||||||
|
|
||||||
/* y is a negative number. use moo_addints() until it becomes 0 */
|
/* y is a negative number. use moo_addints() until it becomes 0 */
|
||||||
moo_pushvolat (moo, &z);
|
moo_pushvolat (moo, &z);
|
||||||
y = moo_addints (moo, y, MOO_SMOOI_TO_OOP(shift));
|
y = moo_addints(moo, y, MOO_SMOOI_TO_OOP(shift));
|
||||||
moo_popvolat (moo);
|
moo_popvolat (moo);
|
||||||
if (!y) return MOO_NULL;
|
if (!y) return MOO_NULL;
|
||||||
|
|
||||||
sign = integer_to_oow (moo, y, &shift);
|
sign = integer_to_oow(moo, y, &shift);
|
||||||
if (sign == 0) shift = MOO_SMOOI_MAX;
|
if (sign == 0) shift = MOO_SMOOI_MAX;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (shift == 0)
|
if (shift == 0)
|
||||||
{
|
{
|
||||||
/* no more shift */
|
/* no more shift */
|
||||||
return normalize_bigint (moo, z);
|
return normalize_bigint(moo, z);
|
||||||
}
|
}
|
||||||
MOO_ASSERT (moo, sign <= -1);
|
MOO_ASSERT (moo, sign <= -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
moo_pushvolat (moo, &y);
|
moo_pushvolat (moo, &y);
|
||||||
x = normalize_bigint (moo, z);
|
x = normalize_bigint(moo, z);
|
||||||
moo_popvolat (moo);
|
moo_popvolat (moo);
|
||||||
if (!x) return MOO_NULL;
|
if (!x) return MOO_NULL;
|
||||||
|
|
||||||
|
@ -2208,6 +2208,23 @@ MOO_EXPORT int moo_inttoooi (
|
|||||||
moo_ooi_t* i
|
moo_ooi_t* i
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#if (MOO_SIZEOF_UINTMAX_T == MOO_SIZEOF_OOW_T)
|
||||||
|
# define moo_inttouintmax moo_inttooow
|
||||||
|
# define moo_inttointmax moo_inttoooi
|
||||||
|
#else
|
||||||
|
MOO_EXPORT int moo_inttouintmax (
|
||||||
|
moo_t* moo,
|
||||||
|
moo_oop_t x,
|
||||||
|
moo_uintmax_t* w
|
||||||
|
);
|
||||||
|
|
||||||
|
MOO_EXPORT int moo_inttointmax (
|
||||||
|
moo_t* moo,
|
||||||
|
moo_oop_t x,
|
||||||
|
moo_intmax_t* i
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
MOO_EXPORT moo_oop_t moo_findclass (
|
MOO_EXPORT moo_oop_t moo_findclass (
|
||||||
moo_t* moo,
|
moo_t* moo,
|
||||||
moo_oop_nsdic_t nsdic,
|
moo_oop_nsdic_t nsdic,
|
||||||
|
Loading…
Reference in New Issue
Block a user