touched up bigint.c
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
hyung-hwan 2024-09-20 12:00:18 +09:00
parent e81bcbab61
commit 3e6cfccb3b

View File

@ -92,7 +92,6 @@ static const hcl_uint8_t debruijn_64[64] =
# define LOG2_FOR_POW2(x) hcl_get_pos_of_msb_set_pow2(x) # define LOG2_FOR_POW2(x) hcl_get_pos_of_msb_set_pow2(x)
#endif #endif
#if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UADD_OVERFLOW) #if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UADD_OVERFLOW)
# define oow_add_overflow(a,b,c) __builtin_uadd_overflow(a,b,c) # define oow_add_overflow(a,b,c) __builtin_uadd_overflow(a,b,c)
#elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UADDL_OVERFLOW) #elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UADDL_OVERFLOW)
@ -107,7 +106,6 @@ static HCL_INLINE int oow_add_overflow (hcl_oow_t a, hcl_oow_t b, hcl_oow_t* c)
} }
#endif #endif
#if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UMUL_OVERFLOW) #if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UMUL_OVERFLOW)
# define oow_mul_overflow(a,b,c) __builtin_umul_overflow(a,b,c) # define oow_mul_overflow(a,b,c) __builtin_umul_overflow(a,b,c)
#elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UMULL_OVERFLOW) #elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UMULL_OVERFLOW)
@ -418,7 +416,7 @@ int hcl_inttoooi (hcl_t* hcl, hcl_oop_t x, hcl_ooi_t* i)
/* do nothing. required macros are defined in hcl.h */ /* do nothing. required macros are defined in hcl.h */
#elif (HCL_SIZEOF_UINTMAX_T == HCL_SIZEOF_OOW_T * 2) #elif (HCL_SIZEOF_UINTMAX_T == HCL_SIZEOF_OOW_T * 2) || (HCL_SIZEOF_UINTMAX_T == HCL_SIZEOF_OOW_T * 4)
static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_t* w) static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_t* w)
{ {
HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(num)); HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(num));
@ -434,9 +432,25 @@ static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_
goto done; goto done;
case 2: case 2:
*w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << HCL_LIW_BITS) | HCL_OBJ_GET_WORD_VAL(num, 1); *w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << HCL_LIW_BITS) |
((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 1));
goto done; goto done;
#if (HCL_SIZEOF_UINTMAX_T >= HCL_SIZEOF_OOW_T * 4)
case 3:
*w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << (HCL_LIW_BITS * 2)) |
((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 1) << (HCL_LIW_BITS * 1)) |
((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 2))
goto done;
case 4:
*w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << (HCL_LIW_BITS * 3)) |
((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 1) << (HCL_LIW_BITS * 2)) |
((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 2) << (HCL_LIW_BITS * 1)) |
((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 3))
goto done;
#endif
default: default:
goto oops_range; goto oops_range;
} }
@ -446,16 +460,39 @@ static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_
switch (HCL_OBJ_GET_SIZE(num)) switch (HCL_OBJ_GET_SIZE(num))
{ {
case 2: case 2:
*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << HCL_LIW_BITS) | HCL_OBJ_GET_HALFWORD_VAL(num, 1); *w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << HCL_LIW_BITS) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1));
goto done; goto done;
case 4: case 4:
*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << HCL_LIW_BITS * 3) | *w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << (HCL_LIW_BITS * 3)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << HCL_LIW_BITS * 2) | ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << (HCL_LIW_BITS * 2)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << HCL_LIW_BITS * 1) | ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << (HCL_LIW_BITS * 1)) |
HCL_OBJ_GET_HALFWORD_VAL(num, 3); ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 3));
goto done; goto done;
#if (HCL_SIZEOF_UINTMAX_T >= HCL_SIZEOF_OOW_T * 4)
case 6:
*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << (HCL_LIW_BITS * 5)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << (HCL_LIW_BITS * 4)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << (HCL_LIW_BITS * 3)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 3) << (HCL_LIW_BITS * 2)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 4) << (HCL_LIW_BITS * 1)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 5));
goto done;
case 8:
*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << (HCL_LIW_BITS * 7)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << (HCL_LIW_BITS * 6)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << (HCL_LIW_BITS * 5)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 3) << (HCL_LIW_BITS * 4)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 4) << (HCL_LIW_BITS * 3)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 5) << (HCL_LIW_BITS * 2)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 6) << (HCL_LIW_BITS * 1)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 7));
goto done;
#endif
default: default:
goto oops_range; goto oops_range;
} }
@ -529,7 +566,6 @@ int hcl_inttointmax (hcl_t* hcl, hcl_oop_t x, hcl_intmax_t* i)
# error UNSUPPORTED UINTMAX SIZE # error UNSUPPORTED UINTMAX SIZE
#endif #endif
static HCL_INLINE hcl_oop_t make_bigint_with_oow (hcl_t* hcl, hcl_oow_t w) static HCL_INLINE hcl_oop_t make_bigint_with_oow (hcl_t* hcl, hcl_oow_t w)
{ {
#if (HCL_LIW_BITS == HCL_OOW_BITS) #if (HCL_LIW_BITS == HCL_OOW_BITS)
@ -605,7 +641,7 @@ static HCL_INLINE hcl_oop_t make_bloated_bigint_with_ooi (hcl_t* hcl, hcl_ooi_t
z = make_nbigint(hcl, HCL_NULL, 1 + extra); z = make_nbigint(hcl, HCL_NULL, 1 + extra);
} }
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
HCL_OBJ_SET_LIWORD_VAL (z, 0, w); HCL_OBJ_SET_LIWORD_VAL (z, 0, w);
return z; return z;
@ -630,7 +666,7 @@ static HCL_INLINE hcl_oop_t make_bloated_bigint_with_ooi (hcl_t* hcl, hcl_ooi_t
z = make_nbigint(hcl, HCL_NULL, (hw[1] > 0? 2: 1) + extra); z = make_nbigint(hcl, HCL_NULL, (hw[1] > 0? 2: 1) + extra);
} }
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
HCL_OBJ_SET_LIWORD_VAL (z, 0, hw[0]); HCL_OBJ_SET_LIWORD_VAL (z, 0, hw[0]);
if (hw[1] > 0) HCL_OBJ_SET_LIWORD_VAL (z, 1, hw[1]); if (hw[1] > 0) HCL_OBJ_SET_LIWORD_VAL (z, 1, hw[1]);
return z; return z;
@ -760,7 +796,7 @@ static HCL_INLINE hcl_oop_t expand_bigint (hcl_t* hcl, hcl_oop_t oop, hcl_oow_t
hcl_pushvolat (hcl, &oop); hcl_pushvolat (hcl, &oop);
z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(oop), HCL_NULL, count + inc); z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(oop), HCL_NULL, count + inc);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) if (HCL_UNLIKELY(!z))
{ {
const hcl_ooch_t* orgmsg = hcl_backuperrmsg(hcl); const hcl_ooch_t* orgmsg = hcl_backuperrmsg(hcl);
hcl_seterrbfmt (hcl, HCL_ERRNUM(hcl), "unable to clone bigint %O for expansion - %s", oop, orgmsg); hcl_seterrbfmt (hcl, HCL_ERRNUM(hcl), "unable to clone bigint %O for expansion - %s", oop, orgmsg);
@ -774,7 +810,7 @@ static HCL_INLINE hcl_oop_t expand_bigint (hcl_t* hcl, hcl_oop_t oop, hcl_oow_t
return z; return z;
} }
static HCL_INLINE hcl_oop_t _clone_bigint(hcl_t* hcl, hcl_oop_t oop, hcl_oow_t count, hcl_oop_class_t _class) static HCL_INLINE hcl_oop_t _clone_bigint (hcl_t* hcl, hcl_oop_t oop, hcl_oow_t count, hcl_oop_class_t _class)
{ {
hcl_oop_t z; hcl_oop_t z;
hcl_oow_t i; hcl_oow_t i;
@ -782,12 +818,10 @@ static HCL_INLINE hcl_oop_t _clone_bigint(hcl_t* hcl, hcl_oop_t oop, hcl_oow_t c
HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop)); HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop));
if (count <= 0) count = HCL_OBJ_GET_SIZE(oop); if (count <= 0) count = HCL_OBJ_GET_SIZE(oop);
hcl_pushvolat (hcl, (hcl_oop_t*)&_class);
hcl_pushvolat (hcl, &oop); hcl_pushvolat (hcl, &oop);
z = hcl_instantiate(hcl, _class, HCL_NULL, count); z = hcl_instantiate(hcl, _class, HCL_NULL, count);
hcl_popvolat (hcl); hcl_popvolat (hcl);
hcl_popvolat (hcl); if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (!z) return HCL_NULL;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
@ -854,7 +888,7 @@ static hcl_oop_t normalize_bigint (hcl_t* hcl, hcl_oop_t oop)
hcl_oow_t count; hcl_oow_t count;
HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop)); HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop));
count = count_effective_digits (oop); count = count_effective_digits(oop);
#if (HCL_LIW_BITS == HCL_OOW_BITS) #if (HCL_LIW_BITS == HCL_OOW_BITS)
if (count == 1) /* 1 word */ if (count == 1) /* 1 word */
@ -986,7 +1020,7 @@ static HCL_INLINE int is_equal_unsigned (hcl_oop_t x, hcl_oop_t y)
static HCL_INLINE int is_equal (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) static HCL_INLINE int is_equal (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
{ {
/* check if two large integers are equal to each other */ /* check if two large integers are equal to each other */
/*return HCL_OBJ_GET_FLAGS_BRAND(x) == HCL_OBJ_GET_FLAGS_BRAND(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) && /*return HCL_OBJ_GET_CLASS(x) == HCL_OBJ_GET_CLASS(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) &&
HCL_MEMCMP(((hcl_oop_liword_t)x)->slot, ((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(x) * HCL_SIZEOF(hcl_liw_t)) == 0;*/ HCL_MEMCMP(((hcl_oop_liword_t)x)->slot, ((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(x) * HCL_SIZEOF(hcl_liw_t)) == 0;*/
return HCL_OBJ_GET_CLASS(x) == HCL_OBJ_GET_CLASS(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) && is_equal_unsigned(x, y); return HCL_OBJ_GET_CLASS(x) == HCL_OBJ_GET_CLASS(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) && is_equal_unsigned(x, y);
} }
@ -1423,13 +1457,13 @@ static HCL_INLINE hcl_oow_t multiply_unsigned_array_karatsuba (hcl_t* hcl, const
tmplen[0] = ndigits_xh + ndigits_yh; tmplen[0] = ndigits_xh + ndigits_yh;
tmplen[1] = ndigits_yl + ndigits_yh + 1; tmplen[1] = ndigits_yl + ndigits_yh + 1;
if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0]; if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0];
tmp[1] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]); /* TODO: should i use the object memory? */ tmp[1] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]); /* TODO: should i use the object memory? if not, reuse the buffer and minimize memory allocation */
if (!tmp[1]) goto oops; if (HCL_UNLIKELY(!tmp[1])) goto oops;
/* make a temporary for (a0 + a1) and (a0 * b0) */ /* make a temporary for (a0 + a1) and (a0 * b0) */
tmplen[0] = ndigits_xl + ndigits_yl + 1; tmplen[0] = ndigits_xl + ndigits_yl + 1;
tmp[0] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]); tmp[0] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]);
if (!tmp[0]) goto oops; if (HCL_UNLIKELY(!tmp[0])) goto oops;
/* tmp[0] = a0 + a1 */ /* tmp[0] = a0 + a1 */
tmplen[0] = add_unsigned_array(x, ndigits_xl, x + nshifts, ndigits_xh, tmp[0]); tmplen[0] = add_unsigned_array(x, ndigits_xl, x + nshifts, ndigits_xh, tmp[0]);
@ -1496,7 +1530,7 @@ static HCL_INLINE hcl_oow_t multiply_unsigned_array_karatsuba (hcl_t* hcl, const
hcl_freemem (hcl, tmp[1]); hcl_freemem (hcl, tmp[1]);
hcl_freemem (hcl, tmp[0]); hcl_freemem (hcl, tmp[0]);
return count_effective (z, xlen); return count_effective(z, xlen);
oops: oops:
if (tmp[1]) hcl_freemem (hcl, tmp[1]); if (tmp[1]) hcl_freemem (hcl, tmp[1]);
@ -1560,12 +1594,12 @@ oops:
tmplen[0] = ndigits_yl + ndigits_yh + 1; tmplen[0] = ndigits_yl + ndigits_yh + 1;
tmplen[1] = ndigits_xh + ndigits_yh; tmplen[1] = ndigits_xh + ndigits_yh;
if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0]; if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0];
tmp[1] = hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]); tmp[1] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]);
if (!tmp[1]) goto oops; if (!tmp[1]) goto oops;
/* make a temporary for (a0 + a1) and (a0 * b0) */ /* make a temporary for (a0 + a1) and (a0 * b0) */
tmplen[0] = ndigits_xl + ndigits_yl; tmplen[0] = ndigits_xl + ndigits_yl;
tmp[0] = hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]); tmp[0] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]);
if (!tmp[0]) goto oops; if (!tmp[0]) goto oops;
/* tmp[0] = a0 + a1 */ /* tmp[0] = a0 + a1 */
@ -1576,7 +1610,7 @@ oops:
/* tmp[2] = (a0 + a1) * (b0 + b1) */ /* tmp[2] = (a0 + a1) * (b0 + b1) */
tmplen[2] = tmplen[0] + tmplen[1]; tmplen[2] = tmplen[0] + tmplen[1];
tmp[2] = hcl_callocmem (hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[2]); tmp[2] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[2]);
if (!tmp[2]) goto oops; if (!tmp[2]) goto oops;
if (CANNOT_KARATSUBA(hcl, tmplen[0], tmplen[1])) if (CANNOT_KARATSUBA(hcl, tmplen[0], tmplen[1]))
{ {
@ -2113,7 +2147,7 @@ static hcl_oop_t add_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(x), HCL_NULL, zs); z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(x), HCL_NULL, zs);
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
add_unsigned_array ( add_unsigned_array (
((hcl_oop_liword_t)x)->slot, as, ((hcl_oop_liword_t)x)->slot, as,
@ -2134,7 +2168,7 @@ static hcl_oop_t subtract_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x)); z = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x));
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
subtract_unsigned_array (hcl, subtract_unsigned_array (hcl,
((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x), ((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x),
@ -2161,7 +2195,7 @@ static hcl_oop_t multiply_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = make_pbigint(hcl, HCL_NULL, xs + ys); z = make_pbigint(hcl, HCL_NULL, xs + ys);
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
#if defined(HCL_ENABLE_KARATSUBA) #if defined(HCL_ENABLE_KARATSUBA)
if (CANNOT_KARATSUBA(hcl, xs, ys)) if (CANNOT_KARATSUBA(hcl, xs, ys))
@ -2229,7 +2263,7 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y,
#else #else
qq = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x)); qq = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x));
#endif #endif
if (!qq) if (HCL_UNLIKELY(!qq))
{ {
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
return HCL_NULL; return HCL_NULL;
@ -2244,8 +2278,7 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y,
rr = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(y) + 1); rr = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(y) + 1);
#endif #endif
hcl_popvolats (hcl, 3); hcl_popvolats (hcl, 3);
if (!rr) return HCL_NULL; if (HCL_UNLIKELY(!rr)) return HCL_NULL;
#if defined(USE_DIVIDE_UNSIGNED_ARRAY3) #if defined(USE_DIVIDE_UNSIGNED_ARRAY3)
divide_unsigned_array3 (hcl, divide_unsigned_array3 (hcl,
@ -2256,7 +2289,8 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y,
#endif #endif
((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x), ((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x),
((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(y), ((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(y),
((hcl_oop_liword_t)qq)->slot, ((hcl_oop_liword_t)rr)->slot); ((hcl_oop_liword_t)qq)->slot, ((hcl_oop_liword_t)rr)->slot
);
*r = rr; *r = rr;
return qq; return qq;
@ -2280,7 +2314,7 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
i = HCL_OOP_TO_SMOOI(x) + HCL_OOP_TO_SMOOI(y); i = HCL_OOP_TO_SMOOI(x) + HCL_OOP_TO_SMOOI(y);
if (HCL_IN_SMOOI_RANGE(i)) return HCL_SMOOI_TO_OOP(i); if (HCL_IN_SMOOI_RANGE(i)) return HCL_SMOOI_TO_OOP(i);
return make_bigint_with_ooi (hcl, i); return make_bigint_with_ooi(hcl, i);
} }
else else
{ {
@ -2294,9 +2328,9 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y)); if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y));
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi (hcl, v); x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
} }
else if (HCL_OOP_IS_SMOOI(y)) else if (HCL_OOP_IS_SMOOI(y))
{ {
@ -2306,9 +2340,9 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x));
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi (hcl, v); y = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!y) return HCL_NULL; if (HCL_UNLIKELY(!y)) return HCL_NULL;
} }
else else
{ {
@ -2321,7 +2355,7 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (HCL_IS_NBIGINT(hcl, x)) if (HCL_IS_NBIGINT(hcl, x))
{ {
/* x is negative, y is positive */ /* x is negative, y is positive */
if (is_less_unsigned (x, y)) if (is_less_unsigned(x, y))
{ {
z = subtract_unsigned_integers(hcl, y, x); z = subtract_unsigned_integers(hcl, y, x);
if (HCL_UNLIKELY(!z)) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
@ -2360,7 +2394,7 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
} }
} }
return normalize_bigint (hcl, z); return normalize_bigint(hcl, z);
oops_einval: oops_einval:
hcl_seterrbfmt (hcl, HCL_EINVAL, "not integer - %O, %O", x, y); hcl_seterrbfmt (hcl, HCL_EINVAL, "not integer - %O, %O", x, y);
@ -2383,7 +2417,7 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
i = HCL_OOP_TO_SMOOI(x) - HCL_OOP_TO_SMOOI(y); i = HCL_OOP_TO_SMOOI(x) - HCL_OOP_TO_SMOOI(y);
if (HCL_IN_SMOOI_RANGE(i)) return HCL_SMOOI_TO_OOP(i); if (HCL_IN_SMOOI_RANGE(i)) return HCL_SMOOI_TO_OOP(i);
return make_bigint_with_ooi (hcl, i); return make_bigint_with_ooi(hcl, i);
} }
else else
{ {
@ -2402,9 +2436,9 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
} }
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi (hcl, v); x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
} }
else if (HCL_OOP_IS_SMOOI(y)) else if (HCL_OOP_IS_SMOOI(y))
{ {
@ -2414,9 +2448,9 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x));
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi (hcl, v); y = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!y) return HCL_NULL; if (HCL_UNLIKELY(!y)) return HCL_NULL;
} }
else else
{ {
@ -2428,7 +2462,7 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
{ {
neg = HCL_IS_NBIGINT(hcl, x); neg = HCL_IS_NBIGINT(hcl, x);
z = add_unsigned_integers(hcl, x, y); z = add_unsigned_integers(hcl, x, y);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (neg) HCL_OBJ_SET_CLASS (z, (hcl_oop_t)hcl->c_large_negative_integer); if (neg) HCL_OBJ_SET_CLASS (z, (hcl_oop_t)hcl->c_large_negative_integer);
} }
else else
@ -2494,7 +2528,7 @@ hcl_oop_t hcl_mulints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
else else
{ {
if (HCL_IN_SMOOI_RANGE(i)) return HCL_SMOOI_TO_OOP(i); if (HCL_IN_SMOOI_RANGE(i)) return HCL_SMOOI_TO_OOP(i);
return make_bigint_with_ooi (hcl, i); return make_bigint_with_ooi(hcl, i);
} }
#endif #endif
} }
@ -2519,7 +2553,7 @@ hcl_oop_t hcl_mulints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
} }
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi (hcl, v); x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (HCL_UNLIKELY(!x)) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
} }
@ -2695,7 +2729,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi(hcl, xv); x = make_bigint_with_ooi(hcl, xv);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
} }
else if (HCL_OOP_IS_SMOOI(y)) else if (HCL_OOP_IS_SMOOI(y))
{ {
@ -2714,13 +2748,13 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
case 1: case 1:
z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x));
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (rem) *rem = HCL_SMOOI_TO_OOP(0); if (rem) *rem = HCL_SMOOI_TO_OOP(0);
return z; return z;
case -1: case -1:
z = clone_bigint_negated(hcl, x, HCL_OBJ_GET_SIZE(x)); z = clone_bigint_negated(hcl, x, HCL_OBJ_GET_SIZE(x));
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (rem) *rem = HCL_SMOOI_TO_OOP(0); if (rem) *rem = HCL_SMOOI_TO_OOP(0);
return z; return z;
@ -2741,7 +2775,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
y_neg_sign = (yv < 0); y_neg_sign = (yv < 0);
z = clone_bigint_to_positive(hcl, x, HCL_OBJ_GET_SIZE(x)); z = clone_bigint_to_positive(hcl, x, HCL_OBJ_GET_SIZE(x));
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
zw = ((hcl_oop_liword_t)z)->slot; zw = ((hcl_oop_liword_t)z)->slot;
zs = HCL_OBJ_GET_SIZE(z); zs = HCL_OBJ_GET_SIZE(z);
@ -2777,7 +2811,6 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
if (HCL_UNLIKELY(!r)) return HCL_NULL; if (HCL_UNLIKELY(!r)) return HCL_NULL;
*rem = r; *rem = r;
} }
return z; return z;
} }
} }
@ -2789,9 +2822,9 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
/* carry on to the full bigint division */ /* carry on to the full bigint division */
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi (hcl, yv); y = make_bigint_with_ooi(hcl, yv);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!y) return HCL_NULL; if (HCL_UNLIKELY(!y)) return HCL_NULL;
} }
else else
{ {
@ -2805,9 +2838,9 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = divide_unsigned_integers (hcl, x, y, &r); z = divide_unsigned_integers(hcl, x, y, &r);
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (x_neg_sign) if (x_neg_sign)
{ {
@ -2822,9 +2855,9 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
hcl_pushvolat (hcl, &z); hcl_pushvolat (hcl, &z);
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
r = normalize_bigint (hcl, r); r = normalize_bigint(hcl, r);
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!r) return HCL_NULL; if (HCL_UNLIKELY(!r)) return HCL_NULL;
if (r != HCL_SMOOI_TO_OOP(0) && modulo) if (r != HCL_SMOOI_TO_OOP(0) && modulo)
{ {
@ -2832,19 +2865,19 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
{ {
hcl_pushvolat (hcl, &z); hcl_pushvolat (hcl, &z);
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
r = hcl_addints (hcl, r, y); r = hcl_addints(hcl, r, y);
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!r) return HCL_NULL; if (HCL_UNLIKELY(!r)) return HCL_NULL;
hcl_pushvolat (hcl, &r); hcl_pushvolat (hcl, &r);
z = normalize_bigint (hcl, z); z = normalize_bigint(hcl, z);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
hcl_pushvolat (hcl, &r); hcl_pushvolat (hcl, &r);
z = hcl_subints (hcl, z, HCL_SMOOI_TO_OOP(1)); z = hcl_subints(hcl, z, HCL_SMOOI_TO_OOP(1));
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
*rem = r; *rem = r;
return z; return z;
@ -2853,18 +2886,18 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
{ {
/* remainder is not needed at all */ /* remainder is not needed at all */
/* TODO: subtract 1 without normalization??? */ /* TODO: subtract 1 without normalization??? */
z = normalize_bigint (hcl, z); z = normalize_bigint(hcl, z);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
return hcl_subints (hcl, z, HCL_SMOOI_TO_OOP(1)); return hcl_subints(hcl, z, HCL_SMOOI_TO_OOP(1));
} }
} }
} }
else else
{ {
hcl_pushvolat (hcl, &z); hcl_pushvolat (hcl, &z);
r = normalize_bigint (hcl, r); r = normalize_bigint(hcl, r);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!r) return HCL_NULL; if (HCL_UNLIKELY(!r)) return HCL_NULL;
} }
hcl_pushvolat (hcl, &r); hcl_pushvolat (hcl, &r);
@ -3087,9 +3120,9 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (v == 0) return HCL_SMOOI_TO_OOP(0); if (v == 0) return HCL_SMOOI_TO_OOP(0);
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi (hcl, v); x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint; goto bigint_and_bigint;
} }
@ -3105,7 +3138,7 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi (hcl, v); y = make_bigint_with_ooi (hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint; goto bigint_and_bigint;
} }
@ -3160,7 +3193,7 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = make_pbigint(hcl, HCL_NULL, zalloc); z = make_pbigint(hcl, HCL_NULL, zalloc);
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (negx && negy) if (negx && negy)
{ {
@ -3288,7 +3321,7 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
v3 = v1 | v2; v3 = v1 | v2;
if (HCL_IN_SMOOI_RANGE(v3)) return HCL_SMOOI_TO_OOP(v3); if (HCL_IN_SMOOI_RANGE(v3)) return HCL_SMOOI_TO_OOP(v3);
return make_bigint_with_ooi (hcl, v3); return make_bigint_with_ooi(hcl, v3);
} }
else if (HCL_OOP_IS_SMOOI(x)) else if (HCL_OOP_IS_SMOOI(x))
{ {
@ -3300,9 +3333,9 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y)); if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y));
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi (hcl, v); x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint; goto bigint_and_bigint;
} }
@ -3316,9 +3349,9 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x));
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi (hcl, v); y = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint; goto bigint_and_bigint;
} }
@ -3380,7 +3413,7 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = make_pbigint(hcl, HCL_NULL, zalloc); z = make_pbigint(hcl, HCL_NULL, zalloc);
hcl_popvolats (hcl, 2); hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (negx && negy) if (negx && negy)
{ {
@ -3520,7 +3553,7 @@ hcl_oop_t hcl_bitxorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi (hcl, v); x = make_bigint_with_ooi (hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint; goto bigint_and_bigint;
} }
@ -3536,7 +3569,7 @@ hcl_oop_t hcl_bitxorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi (hcl, v); y = make_bigint_with_ooi (hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint; goto bigint_and_bigint;
} }
@ -3756,7 +3789,7 @@ hcl_oop_t hcl_bitinvint (hcl_t* hcl, hcl_oop_t x)
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
z = make_pbigint(hcl, HCL_NULL, zalloc); z = make_pbigint(hcl, HCL_NULL, zalloc);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (negx) if (negx)
{ {
@ -3828,7 +3861,7 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint (hcl_t* hcl, hcl_oop_t x, hcl
/* +1 for the second inversion below */ /* +1 for the second inversion below */
z = make_nbigint(hcl, HCL_NULL, xs + 1); z = make_nbigint(hcl, HCL_NULL, xs + 1);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
/* the following lines roughly for 'z = hcl_bitinv (hcl, x)' */ /* the following lines roughly for 'z = hcl_bitinv (hcl, x)' */
carry = 1; carry = 1;
@ -3851,7 +3884,6 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint (hcl_t* hcl, hcl_oop_t x, hcl
} }
HCL_OBJ_SET_LIWORD_VAL (z, xs, ~(hcl_liw_t)0); HCL_OBJ_SET_LIWORD_VAL (z, xs, ~(hcl_liw_t)0);
carry = 1; carry = 1;
for (i = 0; i <= xs; i++) for (i = 0; i <= xs; i++)
{ {
@ -3896,13 +3928,13 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc
do do
{ {
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = rshift_negative_bigint (hcl, x, shift); z = rshift_negative_bigint(hcl, x, shift);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
/* y is a negative number. use hcl_addints() until it becomes 0 */ /* y is a negative number. use hcl_addints() until it becomes 0 */
hcl_pushvolat (hcl, &z); hcl_pushvolat (hcl, &z);
y = hcl_addints (hcl, y, HCL_SMOOI_TO_OOP(shift)); y = hcl_addints(hcl, y, HCL_SMOOI_TO_OOP(shift));
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!y) return HCL_NULL; if (!y) return HCL_NULL;
@ -3913,15 +3945,15 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc
if (shift == 0) if (shift == 0)
{ {
/* no more shift */ /* no more shift */
return normalize_bigint (hcl, z); return normalize_bigint(hcl, z);
} }
HCL_ASSERT (hcl, sign <= -1); HCL_ASSERT (hcl, sign <= -1);
} }
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = normalize_bigint (hcl, z); x = normalize_bigint(hcl, z);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
if (HCL_OOP_IS_SMOOI(x)) if (HCL_OOP_IS_SMOOI(x))
{ {
@ -3971,7 +4003,7 @@ static HCL_INLINE hcl_oop_t rshift_positive_bigint_and_normalize (hcl_t* hcl, hc
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = clone_bigint(hcl, x, zs); z = clone_bigint(hcl, x, zs);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
/* for convenience in subtraction below. /* for convenience in subtraction below.
* it could be HCL_TYPE_MAX(hcl_oow_t) * it could be HCL_TYPE_MAX(hcl_oow_t)
@ -3981,7 +4013,7 @@ static HCL_INLINE hcl_oop_t rshift_positive_bigint_and_normalize (hcl_t* hcl, hc
do do
{ {
rshift_unsigned_array (((hcl_oop_liword_t)z)->slot, zs, shift); rshift_unsigned_array (((hcl_oop_liword_t)z)->slot, zs, shift);
if (count_effective (((hcl_oop_liword_t)z)->slot, zs) == 1 && if (count_effective(((hcl_oop_liword_t)z)->slot, zs) == 1 &&
HCL_OBJ_GET_LIWORD_VAL(z, 0) == 0) HCL_OBJ_GET_LIWORD_VAL(z, 0) == 0)
{ {
/* if z is 0, i don't have to go on */ /* if z is 0, i don't have to go on */
@ -4031,16 +4063,16 @@ static HCL_INLINE hcl_oop_t lshift_bigint_and_normalize (hcl_t* hcl, hcl_oop_t x
if (shift > wshift * HCL_LIW_BITS) wshift++; if (shift > wshift * HCL_LIW_BITS) wshift++;
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
z = expand_bigint (hcl, x, wshift); z = expand_bigint(hcl, x, wshift);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift);
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = normalize_bigint(hcl, z); x = normalize_bigint(hcl, z);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
hcl_pushvolat (hcl, &x); hcl_pushvolat (hcl, &x);
y = hcl_subints(hcl, y, HCL_SMOOI_TO_OOP(shift)); y = hcl_subints(hcl, y, HCL_SMOOI_TO_OOP(shift));
@ -4095,11 +4127,11 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
wshift = v2 / HCL_LIW_BITS; wshift = v2 / HCL_LIW_BITS;
if (v2 > wshift * HCL_LIW_BITS) wshift++; if (v2 > wshift * HCL_LIW_BITS) wshift++;
z = make_bloated_bigint_with_ooi (hcl, v1, wshift); z = make_bloated_bigint_with_ooi(hcl, v1, wshift);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), v2); lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), v2);
return normalize_bigint (hcl, z); return normalize_bigint(hcl, z);
} }
else else
{ {
@ -4167,9 +4199,9 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
} }
hcl_pushvolat (hcl, &y); hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi (hcl, v); x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl); hcl_popvolat (hcl);
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint; goto bigint_and_bigint;
} }
@ -4223,9 +4255,9 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
return (negx)? HCL_SMOOI_TO_OOP(-1): HCL_SMOOI_TO_OOP(0); return (negx)? HCL_SMOOI_TO_OOP(-1): HCL_SMOOI_TO_OOP(0);
#else #else
if (negx) if (negx)
return rshift_negative_bigint_and_normalize (hcl, x, y); return rshift_negative_bigint_and_normalize(hcl, x, y);
else else
return rshift_positive_bigint_and_normalize (hcl, x, y); return rshift_positive_bigint_and_normalize(hcl, x, y);
#endif #endif
} }
else else
@ -4240,7 +4272,7 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_seterrnum (hcl, HCL_EOOMEM); /* is it a soft failure or a hard failure? is this error code proper? */ hcl_seterrnum (hcl, HCL_EOOMEM); /* is it a soft failure or a hard failure? is this error code proper? */
return HCL_NULL; return HCL_NULL;
#else #else
return lshift_bigint_and_normalize (hcl, x, y); return lshift_bigint_and_normalize(hcl, x, y);
#endif #endif
} }
} }
@ -4253,8 +4285,8 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
wshift = shift / HCL_LIW_BITS; wshift = shift / HCL_LIW_BITS;
if (shift > wshift * HCL_LIW_BITS) wshift++; if (shift > wshift * HCL_LIW_BITS) wshift++;
z = expand_bigint (hcl, x, wshift); z = expand_bigint(hcl, x, wshift);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift);
} }
@ -4268,12 +4300,12 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (negx) if (negx)
{ {
z = rshift_negative_bigint(hcl, x, shift); z = rshift_negative_bigint(hcl, x, shift);
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
} }
else else
{ {
z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x));
if (!z) return HCL_NULL; if (HCL_UNLIKELY(!z)) return HCL_NULL;
rshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); rshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift);
} }
} }
@ -4364,6 +4396,7 @@ hcl_oop_t hcl_strtoint (hcl_t* hcl, const hcl_ooch_t* str, hcl_oow_t len, int ra
if (outlen > HCL_COUNTOF(hw)) if (outlen > HCL_COUNTOF(hw))
{ {
/* TODO: reuse this buffer? */
hwp = (hcl_liw_t*)hcl_allocmem(hcl, outlen * HCL_SIZEOF(hw[0])); hwp = (hcl_liw_t*)hcl_allocmem(hcl, outlen * HCL_SIZEOF(hw[0]));
if (!hwp) return HCL_NULL; if (!hwp) return HCL_NULL;
} }
@ -4441,7 +4474,6 @@ hcl_oop_t hcl_strtoint (hcl_t* hcl, const hcl_ooch_t* str, hcl_oow_t len, int ra
ptr++; ptr++;
} }
r2 = r1; r2 = r1;
for (i = 0; i < hwlen; i++) for (i = 0; i < hwlen; i++)
{ {
@ -4499,7 +4531,7 @@ hcl_oop_t hcl_strtoint (hcl_t* hcl, const hcl_ooch_t* str, hcl_oow_t len, int ra
oops_einval: oops_einval:
if (hwp && hw != hwp) hcl_freemem (hcl, hwp); if (hwp && hw != hwp) hcl_freemem (hcl, hwp);
hcl_seterrnum (hcl, HCL_EINVAL); hcl_seterrbfmt (hcl, HCL_EINVAL, "unable to convert '%.*js' to integer", len, str);
return HCL_NULL; return HCL_NULL;
} }
@ -4712,52 +4744,52 @@ hcl_oop_t hcl_sqrtint (hcl_t* hcl, hcl_oop_t x)
hcl_pushvolat (hcl, &m2); hcl_pushvolat (hcl, &m2);
a = hcl_ltints(hcl, x, HCL_SMOOI_TO_OOP(0)); a = hcl_ltints(hcl, x, HCL_SMOOI_TO_OOP(0));
if (!a) goto oops; if (HCL_UNLIKELY(!a)) goto oops;
if (a == hcl->_true) if (a == hcl->_true)
{ {
/* the given number is a negative number. /* the given number is a negative number.
* i will arrange the return value to be negative. */ * i will arrange the return value to be negative. */
x = hcl_negateint(hcl, x); x = hcl_negateint(hcl, x);
if (!x) goto oops; if (HCL_UNLIKELY(!x)) goto oops;
neg = 1; neg = 1;
} }
else neg = 0; else neg = 0;
a = HCL_SMOOI_TO_OOP(1); a = HCL_SMOOI_TO_OOP(1);
b = hcl_bitshiftint(hcl, x, HCL_SMOOI_TO_OOP(-5)); b = hcl_bitshiftint(hcl, x, HCL_SMOOI_TO_OOP(-5));
if (!b) goto oops; if (HCL_UNLIKELY(!b)) goto oops;
b = hcl_addints(hcl, b, HCL_SMOOI_TO_OOP(8)); b = hcl_addints(hcl, b, HCL_SMOOI_TO_OOP(8));
if (!b) goto oops; if (HCL_UNLIKELY(!b)) goto oops;
while (1) while (1)
{ {
t = hcl_geints(hcl, b, a); t = hcl_geints(hcl, b, a);
if (!t) return HCL_NULL; if (HCL_UNLIKELY(!t)) return HCL_NULL;
if (t == hcl->_false) break; if (t == hcl->_false) break;
m = hcl_addints(hcl, a, b); m = hcl_addints(hcl, a, b);
if (!m) goto oops; if (HCL_UNLIKELY(!m)) goto oops;
m = hcl_bitshiftint(hcl, m, HCL_SMOOI_TO_OOP(-1)); m = hcl_bitshiftint(hcl, m, HCL_SMOOI_TO_OOP(-1));
if (!m) goto oops; if (HCL_UNLIKELY(!m)) goto oops;
m2 = hcl_mulints(hcl, m, m); m2 = hcl_mulints(hcl, m, m);
if (!m2) goto oops; if (HCL_UNLIKELY(!m2)) goto oops;
t = hcl_gtints(hcl, m2, x); t = hcl_gtints(hcl, m2, x);
if (!t) return HCL_NULL; if (HCL_UNLIKELY(!t)) return HCL_NULL;
if (t == hcl->_true) if (t == hcl->_true)
{ {
b = hcl_subints(hcl, m, HCL_SMOOI_TO_OOP(1)); b = hcl_subints(hcl, m, HCL_SMOOI_TO_OOP(1));
if (!b) goto oops; if (HCL_UNLIKELY(!b)) goto oops;
} }
else else
{ {
a = hcl_addints(hcl, m, HCL_SMOOI_TO_OOP(1)); a = hcl_addints(hcl, m, HCL_SMOOI_TO_OOP(1));
if (!a) goto oops; if (HCL_UNLIKELY(!a)) goto oops;
} }
} }
hcl_popvolats (hcl, 5); hcl_popvolats (hcl, 5);
x = hcl_subints(hcl, a, HCL_SMOOI_TO_OOP(1)); x = hcl_subints(hcl, a, HCL_SMOOI_TO_OOP(1));
if (!x) return HCL_NULL; if (HCL_UNLIKELY(!x)) return HCL_NULL;
if (neg) x = hcl_negateint(hcl, x); if (neg) x = hcl_negateint(hcl, x);
return x; return x;
@ -4767,7 +4799,6 @@ oops:
return HCL_NULL; return HCL_NULL;
} }
hcl_oop_t hcl_absint (hcl_t* hcl, hcl_oop_t x) hcl_oop_t hcl_absint (hcl_t* hcl, hcl_oop_t x)
{ {
if (HCL_OOP_IS_SMOOI(x)) if (HCL_OOP_IS_SMOOI(x))
@ -4873,13 +4904,15 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int flagged_radix)
return hcl_makestring(hcl, xbuf, xlen); return hcl_makestring(hcl, xbuf, xlen);
} }
/* the number can't be represented as a single hcl_oow_t value.
* mutli-word conversion begins now */
as = HCL_OBJ_GET_SIZE(num); as = HCL_OBJ_GET_SIZE(num);
reqcapa = as * HCL_LIW_BITS + 1; reqcapa = as * HCL_LIW_BITS + 1;
if (hcl->inttostr.xbuf.capa < reqcapa) if (hcl->inttostr.xbuf.capa < reqcapa)
{ {
xbuf = (hcl_ooch_t*)hcl_reallocmem(hcl, hcl->inttostr.xbuf.ptr, reqcapa * HCL_SIZEOF(*xbuf)); xbuf = (hcl_ooch_t*)hcl_reallocmem(hcl, hcl->inttostr.xbuf.ptr, reqcapa * HCL_SIZEOF(*xbuf));
if (!xbuf) return HCL_NULL; if (HCL_UNLIKELY(!xbuf)) return HCL_NULL;
hcl->inttostr.xbuf.capa = reqcapa; hcl->inttostr.xbuf.capa = reqcapa;
hcl->inttostr.xbuf.ptr = xbuf; hcl->inttostr.xbuf.ptr = xbuf;
} }
@ -4891,7 +4924,7 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int flagged_radix)
if (hcl->inttostr.t.capa < as) if (hcl->inttostr.t.capa < as)
{ {
t = (hcl_liw_t*)hcl_reallocmem(hcl, hcl->inttostr.t.ptr, reqcapa * HCL_SIZEOF(*t)); t = (hcl_liw_t*)hcl_reallocmem(hcl, hcl->inttostr.t.ptr, reqcapa * HCL_SIZEOF(*t));
if (!t) return HCL_NULL; if (HCL_UNLIKELY(!t)) return HCL_NULL;
hcl->inttostr.t.capa = as; hcl->inttostr.t.capa = as;
hcl->inttostr.t.ptr = t; hcl->inttostr.t.ptr = t;
} }