added moo_inttouintmax and moo_inttointmax

This commit is contained in:
hyunghwan.chung 2019-08-10 16:20:44 +00:00
parent 99bca6a028
commit 3f2e39cf44
2 changed files with 145 additions and 13 deletions

View File

@ -374,7 +374,7 @@ int moo_inttoooi (moo_t* moo, moo_oop_t x, moo_ooi_t* i)
n = moo_inttooow(moo, x, &w);
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)
{
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;
}
#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)
{
#if (MOO_LIW_BITS == MOO_OOW_BITS)

View File

@ -2208,6 +2208,23 @@ MOO_EXPORT int moo_inttoooi (
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_t* moo,
moo_oop_nsdic_t nsdic,