mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-bigint: fixed a bug with bigint +/- mrb_int; close #6445
This commit is contained in:
@@ -312,18 +312,16 @@ mpz_add(mrb_state *mrb, mpz_t *zz, mpz_t *x, mpz_t *y)
|
||||
mpz_move(mrb, zz, &z);
|
||||
}
|
||||
|
||||
/* x = x + n (only called from mpz_init_set_str) */
|
||||
/* assumes x and n are positive or zero */
|
||||
/* assumes n is small (fits in mp_limb) */
|
||||
/* x += n */
|
||||
/* ignores sign of x */
|
||||
/* assumes n is positive and small (fits in mp_limb) */
|
||||
static void
|
||||
mpz_add_int(mrb_state *mrb, mpz_t *x, mrb_int n)
|
||||
{
|
||||
if (n == 0) {
|
||||
// If n is zero, no operation is needed
|
||||
return;
|
||||
}
|
||||
// If n is zero, no operation is needed
|
||||
if (n == 0) return;
|
||||
|
||||
// Assume x is positive and n is a small positive integer (n < 36)
|
||||
// Assume x is positive and n is a small positive integer
|
||||
mp_dbl_limb carry = n; // Initialize carry with n
|
||||
for (size_t i = 0; i < x->sz && carry; i++) {
|
||||
carry += (mp_dbl_limb)x->p[i]; // Add current limb and carry
|
||||
@@ -352,20 +350,26 @@ mpz_sub(mrb_state *mrb, mpz_t *z, mpz_t *x, mpz_t *y)
|
||||
mpz_add(mrb, z, x, &u);
|
||||
}
|
||||
|
||||
/* x -= n */
|
||||
/* assumes n is small (fits in mp_limb) */
|
||||
/* x -= n */
|
||||
/* ignores sign of x */
|
||||
/* assumes n is positive and small (fits in mp_limb) */
|
||||
static void
|
||||
mpz_sub_int(mrb_state *mrb, mpz_t *x, mrb_int n)
|
||||
{
|
||||
// If x is zero, set x to -1
|
||||
// If n is zero, no operation is needed
|
||||
if (n == 0) return;
|
||||
|
||||
// If x is zero, set x to n
|
||||
if (zero_p(x) || x->sz == 0) {
|
||||
mpz_set_int(mrb, x, n);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
if (x->sn < 0) {
|
||||
mpz_add_int(mrb, x, 1);
|
||||
mpz_add_int(mrb, x, n);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Initialize borrow and start decrement
|
||||
mp_dbl_limb_signed borrow = (mp_limb)n;
|
||||
@@ -1480,22 +1484,17 @@ mrb_bint_as_uint64(mrb_state *mrb, mrb_value x)
|
||||
static mrb_bool
|
||||
int_fit_limb_p(mrb_int i)
|
||||
{
|
||||
#ifdef MRB_INT64
|
||||
#if DIG_SIZE == 32
|
||||
# ifdef MRB_INT64
|
||||
// if mp_limb is int32_t
|
||||
return (i >= INT32_MIN && i <= INT32_MAX);
|
||||
#else /* if DIG_SIZE == 16 */
|
||||
// if mp_limb is int16_t
|
||||
return (i >= INT16_MIN && i <= INT16_MAX);
|
||||
#endif
|
||||
#else /* MRB_INT32 */
|
||||
#if DIG_SIZE == 32
|
||||
return (i > INT32_MIN && i <= INT32_MAX);
|
||||
# else
|
||||
// if mp_limb is also int32_t, it always fits
|
||||
return TRUE;
|
||||
# endif
|
||||
#else /* if DIG_SIZE == 16 */
|
||||
// if mp_limb is int16_t
|
||||
return (i >= INT16_MIN && i <= INT16_MAX);
|
||||
#endif
|
||||
return (i > INT16_MIN && i <= INT16_MAX);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1507,14 +1506,25 @@ mrb_bint_add_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
if (mrb_integer_p(y)) {
|
||||
mrb_int i = mrb_integer(y);
|
||||
if (int_fit_limb_p(i)) {
|
||||
mrb_int n = mrb_integer(y);
|
||||
if (int_fit_limb_p(n)) {
|
||||
mpz_init_set(mrb, &z, &a);
|
||||
if ((i > 0) ^ (z.sn > 0)) {
|
||||
mpz_sub_int(mrb, &z, i);
|
||||
if (n > 0) {
|
||||
if (z.sn > 0) {
|
||||
mpz_add_int(mrb, &z, n);
|
||||
}
|
||||
else {
|
||||
mpz_sub_int(mrb, &z, n);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mpz_add_int(mrb, &z, i);
|
||||
n = -n;
|
||||
if (z.sn > 0) {
|
||||
mpz_sub_int(mrb, &z, n);
|
||||
}
|
||||
else {
|
||||
mpz_add_int(mrb, &z, n);
|
||||
}
|
||||
}
|
||||
struct RBigint *v = bint_new(mrb, &z);
|
||||
return mrb_obj_value(v);
|
||||
@@ -1550,14 +1560,25 @@ mrb_bint_sub_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
if (mrb_integer_p(y)) {
|
||||
mrb_int i = mrb_integer(y);
|
||||
if (int_fit_limb_p(i)) {
|
||||
mrb_int n = mrb_integer(y);
|
||||
if (int_fit_limb_p(n)) {
|
||||
mpz_init_set(mrb, &z, &a);
|
||||
if ((i > 0) ^ (z.sn > 0)) {
|
||||
mpz_add_int(mrb, &z, i);
|
||||
if (n > 0) {
|
||||
if (z.sn > 0) {
|
||||
mpz_sub_int(mrb, &z, n);
|
||||
}
|
||||
else {
|
||||
mpz_add_int(mrb, &z, n);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mpz_sub_int(mrb, &z, i);
|
||||
n = -n;
|
||||
if (z.sn > 0) {
|
||||
mpz_add_int(mrb, &z, n);
|
||||
}
|
||||
else {
|
||||
mpz_sub_int(mrb, &z, n);
|
||||
}
|
||||
}
|
||||
struct RBigint *v = bint_new(mrb, &z);
|
||||
return mrb_obj_value(v);
|
||||
|
||||
Reference in New Issue
Block a user