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)
#endif
#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)
#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
#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)
#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 */
#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)
{
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;
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;
#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:
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))
{
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;
case 4:
*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, 2) << HCL_LIW_BITS * 1) |
HCL_OBJ_GET_HALFWORD_VAL(num, 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, 2) << (HCL_LIW_BITS * 1)) |
((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 3));
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:
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
#endif
static HCL_INLINE hcl_oop_t make_bigint_with_oow (hcl_t* hcl, hcl_oow_t w)
{
#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);
}
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
HCL_OBJ_SET_LIWORD_VAL (z, 0, w);
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);
}
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
HCL_OBJ_SET_LIWORD_VAL (z, 0, hw[0]);
if (hw[1] > 0) HCL_OBJ_SET_LIWORD_VAL (z, 1, hw[1]);
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);
z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(oop), HCL_NULL, count + inc);
hcl_popvolat (hcl);
if (!z)
if (HCL_UNLIKELY(!z))
{
const hcl_ooch_t* orgmsg = hcl_backuperrmsg(hcl);
hcl_seterrbfmt (hcl, HCL_ERRNUM(hcl), "unable to clone bigint %O for expansion - %s", oop, orgmsg);
@ -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));
if (count <= 0) count = HCL_OBJ_GET_SIZE(oop);
hcl_pushvolat (hcl, (hcl_oop_t*)&_class);
hcl_pushvolat (hcl, &oop);
z = hcl_instantiate(hcl, _class, HCL_NULL, count);
hcl_popvolat (hcl);
hcl_popvolat (hcl);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
for (i = 0; i < count; i++)
{
@ -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)
{
/* 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;*/
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[1] = ndigits_yl + ndigits_yh + 1;
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? */
if (!tmp[1]) goto oops;
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 (HCL_UNLIKELY(!tmp[1])) goto oops;
/* make a temporary for (a0 + a1) and (a0 * b0) */
tmplen[0] = ndigits_xl + ndigits_yl + 1;
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 */
tmplen[0] = add_unsigned_array(x, ndigits_xl, x + nshifts, ndigits_xh, tmp[0]);
@ -1560,12 +1594,12 @@ oops:
tmplen[0] = ndigits_yl + ndigits_yh + 1;
tmplen[1] = ndigits_xh + ndigits_yh;
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;
/* make a temporary for (a0 + a1) and (a0 * b0) */
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;
/* tmp[0] = a0 + a1 */
@ -1576,7 +1610,7 @@ oops:
/* tmp[2] = (a0 + a1) * (b0 + b1) */
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 (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);
z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(x), HCL_NULL, zs);
hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
add_unsigned_array (
((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);
z = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x));
hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
subtract_unsigned_array (hcl,
((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);
z = make_pbigint(hcl, HCL_NULL, xs + ys);
hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
#if defined(HCL_ENABLE_KARATSUBA)
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
qq = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x));
#endif
if (!qq)
if (HCL_UNLIKELY(!qq))
{
hcl_popvolats (hcl, 2);
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);
#endif
hcl_popvolats (hcl, 3);
if (!rr) return HCL_NULL;
if (HCL_UNLIKELY(!rr)) return HCL_NULL;
#if defined(USE_DIVIDE_UNSIGNED_ARRAY3)
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
((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)qq)->slot, ((hcl_oop_liword_t)rr)->slot);
((hcl_oop_liword_t)qq)->slot, ((hcl_oop_liword_t)rr)->slot
);
*r = rr;
return qq;
@ -2296,7 +2330,7 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
}
else if (HCL_OOP_IS_SMOOI(y))
{
@ -2308,7 +2342,7 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!y) return HCL_NULL;
if (HCL_UNLIKELY(!y)) return HCL_NULL;
}
else
{
@ -2404,7 +2438,7 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
}
else if (HCL_OOP_IS_SMOOI(y))
{
@ -2416,7 +2450,7 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!y) return HCL_NULL;
if (HCL_UNLIKELY(!y)) return HCL_NULL;
}
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);
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);
}
else
@ -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);
x = make_bigint_with_ooi(hcl, xv);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
}
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:
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);
return z;
case -1:
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);
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);
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;
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;
*rem = r;
}
return z;
}
}
@ -2791,7 +2824,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi(hcl, yv);
hcl_popvolat (hcl);
if (!y) return HCL_NULL;
if (HCL_UNLIKELY(!y)) return HCL_NULL;
}
else
{
@ -2807,7 +2840,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);
z = divide_unsigned_integers(hcl, x, y, &r);
hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (x_neg_sign)
{
@ -2824,7 +2857,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);
r = normalize_bigint(hcl, r);
hcl_popvolats (hcl, 2);
if (!r) return HCL_NULL;
if (HCL_UNLIKELY(!r)) return HCL_NULL;
if (r != HCL_SMOOI_TO_OOP(0) && modulo)
{
@ -2834,17 +2867,17 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
hcl_pushvolat (hcl, &y);
r = hcl_addints(hcl, r, y);
hcl_popvolats (hcl, 2);
if (!r) return HCL_NULL;
if (HCL_UNLIKELY(!r)) return HCL_NULL;
hcl_pushvolat (hcl, &r);
z = normalize_bigint(hcl, z);
hcl_popvolat (hcl);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
hcl_pushvolat (hcl, &r);
z = hcl_subints(hcl, z, HCL_SMOOI_TO_OOP(1));
hcl_popvolat (hcl);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
*rem = r;
return z;
@ -2854,7 +2887,7 @@ 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 */
/* TODO: subtract 1 without normalization??? */
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));
}
}
@ -2864,7 +2897,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop
hcl_pushvolat (hcl, &z);
r = normalize_bigint(hcl, r);
hcl_popvolat (hcl);
if (!r) return HCL_NULL;
if (HCL_UNLIKELY(!r)) return HCL_NULL;
}
hcl_pushvolat (hcl, &r);
@ -3089,7 +3122,7 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
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);
y = make_bigint_with_ooi (hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
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);
z = make_pbigint(hcl, HCL_NULL, zalloc);
hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
if (negx && negy)
{
@ -3302,7 +3335,7 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint;
}
@ -3318,7 +3351,7 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &x);
y = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
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);
z = make_pbigint(hcl, HCL_NULL, zalloc);
hcl_popvolats (hcl, 2);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
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);
x = make_bigint_with_ooi (hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
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);
y = make_bigint_with_ooi (hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint;
}
@ -3756,7 +3789,7 @@ hcl_oop_t hcl_bitinvint (hcl_t* hcl, hcl_oop_t x)
hcl_pushvolat (hcl, &x);
z = make_pbigint(hcl, HCL_NULL, zalloc);
hcl_popvolat (hcl);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
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 */
z = make_nbigint(hcl, HCL_NULL, xs + 1);
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)' */
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);
carry = 1;
for (i = 0; i <= xs; i++)
{
@ -3898,7 +3930,7 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc
hcl_pushvolat (hcl, &y);
z = rshift_negative_bigint(hcl, x, shift);
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 */
hcl_pushvolat (hcl, &z);
@ -3921,7 +3953,7 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc
hcl_pushvolat (hcl, &y);
x = normalize_bigint(hcl, z);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
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);
z = clone_bigint(hcl, x, zs);
hcl_popvolat (hcl);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
/* for convenience in subtraction below.
* it could be HCL_TYPE_MAX(hcl_oow_t)
@ -4033,14 +4065,14 @@ static HCL_INLINE hcl_oop_t lshift_bigint_and_normalize (hcl_t* hcl, hcl_oop_t x
hcl_pushvolat (hcl, &y);
z = expand_bigint(hcl, x, wshift);
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);
hcl_pushvolat (hcl, &y);
x = normalize_bigint(hcl, z);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
hcl_pushvolat (hcl, &x);
y = hcl_subints(hcl, y, HCL_SMOOI_TO_OOP(shift));
@ -4096,7 +4128,7 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (v2 > wshift * HCL_LIW_BITS) 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);
return normalize_bigint(hcl, z);
@ -4169,7 +4201,7 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
hcl_pushvolat (hcl, &y);
x = make_bigint_with_ooi(hcl, v);
hcl_popvolat (hcl);
if (!x) return HCL_NULL;
if (HCL_UNLIKELY(!x)) return HCL_NULL;
goto bigint_and_bigint;
}
@ -4254,7 +4286,7 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (shift > wshift * HCL_LIW_BITS) 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);
}
@ -4268,12 +4300,12 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y)
if (negx)
{
z = rshift_negative_bigint(hcl, x, shift);
if (!z) return HCL_NULL;
if (HCL_UNLIKELY(!z)) return HCL_NULL;
}
else
{
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);
}
}
@ -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))
{
/* TODO: reuse this buffer? */
hwp = (hcl_liw_t*)hcl_allocmem(hcl, outlen * HCL_SIZEOF(hw[0]));
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++;
}
r2 = r1;
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:
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;
}
@ -4712,52 +4744,52 @@ hcl_oop_t hcl_sqrtint (hcl_t* hcl, hcl_oop_t x)
hcl_pushvolat (hcl, &m2);
a = hcl_ltints(hcl, x, HCL_SMOOI_TO_OOP(0));
if (!a) goto oops;
if (HCL_UNLIKELY(!a)) goto oops;
if (a == hcl->_true)
{
/* the given number is a negative number.
* i will arrange the return value to be negative. */
x = hcl_negateint(hcl, x);
if (!x) goto oops;
if (HCL_UNLIKELY(!x)) goto oops;
neg = 1;
}
else neg = 0;
a = HCL_SMOOI_TO_OOP(1);
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));
if (!b) goto oops;
if (HCL_UNLIKELY(!b)) goto oops;
while (1)
{
t = hcl_geints(hcl, b, a);
if (!t) return HCL_NULL;
if (HCL_UNLIKELY(!t)) return HCL_NULL;
if (t == hcl->_false) break;
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));
if (!m) goto oops;
if (HCL_UNLIKELY(!m)) goto oops;
m2 = hcl_mulints(hcl, m, m);
if (!m2) goto oops;
if (HCL_UNLIKELY(!m2)) goto oops;
t = hcl_gtints(hcl, m2, x);
if (!t) return HCL_NULL;
if (HCL_UNLIKELY(!t)) return HCL_NULL;
if (t == hcl->_true)
{
b = hcl_subints(hcl, m, HCL_SMOOI_TO_OOP(1));
if (!b) goto oops;
if (HCL_UNLIKELY(!b)) goto oops;
}
else
{
a = hcl_addints(hcl, m, HCL_SMOOI_TO_OOP(1));
if (!a) goto oops;
if (HCL_UNLIKELY(!a)) goto oops;
}
}
hcl_popvolats (hcl, 5);
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);
return x;
@ -4767,7 +4799,6 @@ oops:
return HCL_NULL;
}
hcl_oop_t hcl_absint (hcl_t* hcl, hcl_oop_t 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);
}
/* the number can't be represented as a single hcl_oow_t value.
* mutli-word conversion begins now */
as = HCL_OBJ_GET_SIZE(num);
reqcapa = as * HCL_LIW_BITS + 1;
if (hcl->inttostr.xbuf.capa < reqcapa)
{
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.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)
{
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.ptr = t;
}