From 3f2e39cf44386fa70401420b292b15864b4d6f0e Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sat, 10 Aug 2019 16:20:44 +0000 Subject: [PATCH] added moo_inttouintmax and moo_inttointmax --- moo/lib/bigint.c | 141 ++++++++++++++++++++++++++++++++++++++++++----- moo/lib/moo.h | 17 ++++++ 2 files changed, 145 insertions(+), 13 deletions(-) diff --git a/moo/lib/bigint.c b/moo/lib/bigint.c index f5bdb9d..e04b19c 100644 --- a/moo/lib/bigint.c +++ b/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; int n; - n = moo_inttooow (moo, x, &w); + 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) @@ -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)); if (MOO_POINTER_IS_PBIGINT(moo, x)) { - return MOO_SMOOI_TO_OOP (0); + return MOO_SMOOI_TO_OOP(0); } else { - return MOO_SMOOI_TO_OOP (1); + return MOO_SMOOI_TO_OOP(1); } #else 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_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); if (!quo) return MOO_NULL; - sign = integer_to_oow (moo, quo, &wp); + sign = integer_to_oow(moo, quo, &wp); MOO_ASSERT (moo, 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)); moo_pushvolat (moo, &y); - x = make_bigint_with_ooi (moo, v); + x = make_bigint_with_ooi(moo, v); moo_popvolat (moo); 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)); moo_pushvolat (moo, &x); - y = make_bigint_with_ooi (moo, v); + y = make_bigint_with_ooi(moo, v); moo_popvolat (moo); 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 { moo_pushvolat (moo, &y); - z = rshift_negative_bigint (moo, x, shift); + z = rshift_negative_bigint(moo, x, shift); moo_popvolat (moo); if (!z) return MOO_NULL; /* y is a negative number. use moo_addints() until it becomes 0 */ 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); 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; else { if (shift == 0) { /* no more shift */ - return normalize_bigint (moo, z); + return normalize_bigint(moo, z); } MOO_ASSERT (moo, sign <= -1); } moo_pushvolat (moo, &y); - x = normalize_bigint (moo, z); + x = normalize_bigint(moo, z); moo_popvolat (moo); if (!x) return MOO_NULL; diff --git a/moo/lib/moo.h b/moo/lib/moo.h index ab5c411..e37a98f 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -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,