mruby-bigint (mpz_sub_int): avoid allocating mpz_t for mrb_int

This commit is contained in:
Yukihiro "Matz" Matsumoto
2024-11-02 15:35:46 +09:00
parent fe12e840f3
commit ef18bd86a6
+33 -9
View File
@@ -352,15 +352,39 @@ mpz_sub(mrb_state *mrb, mpz_t *z, mpz_t *x, mpz_t *y)
mpz_add(mrb, z, x, &u);
}
/* x = y - n */
/* x -= n */
/* assumes n is small (fits in mp_limb) */
static void
mpz_sub_int(mrb_state *mrb, mpz_t *x, mpz_t *y, mrb_int n)
mpz_sub_int(mrb_state *mrb, mpz_t *x, mrb_int n)
{
mpz_t z;
// If x is zero, set x to -1
if (zero_p(x) || x->sz == 0) {
mpz_set_int(mrb, x, n);
return;
}
if (x->sn < 0) {
mpz_add_int(mrb, x, 1);
return;
}
mpz_init_set_int(mrb, &z, n);
mpz_sub(mrb, x, y, &z);
mpz_clear(mrb, &z);
// Initialize borrow and start decrement
mp_dbl_limb_signed borrow = (mp_limb)n;
size_t i = 0;
// Subtract 1 from the least significant limb and propagate if necessary
borrow = (mp_dbl_limb_signed)x->p[i] - borrow;
x->p[i] = LOW(borrow);
borrow = (borrow < 0) ? 1 : 0;
// Continue through limbs while there is a borrow
for (i = 1; i < x->sz && borrow; i++) {
borrow = (mp_dbl_limb_signed)x->p[i] - borrow;
x->p[i] = LOW(borrow);
borrow = (borrow < 0) ? 1 : 0;
}
// Trim any unnecessary leading zeros
trim(x);
}
/* w = u * v */
@@ -568,7 +592,7 @@ mpz_mdiv(mrb_state *mrb, mpz_t *q, mpz_t *x, mpz_t *y)
q->sn = 0;
/* now if r != 0 and q < 0 we need to round q towards -inf */
if (!uzero_p(&r) && qsign < 0)
mpz_sub_int(mrb, q, q, 1);
mpz_sub_int(mrb, q, 1);
mpz_clear(mrb, &r);
}
@@ -633,7 +657,7 @@ mpz_mdivmod(mrb_state *mrb, mpz_t *q, mpz_t *r, mpz_t *x, mpz_t *y)
q->sn = 0;
/* now if r != 0 and q < 0 we need to round q towards -inf */
if (!uzero_p(r) && qsign < 0)
mpz_sub_int(mrb, q, q, 1);
mpz_sub_int(mrb, q, 1);
}
static void
@@ -1885,7 +1909,7 @@ mrb_bint_rev(mrb_state *mrb, mrb_value x)
bint_as_mpz(RBIGINT(x), &a);
mpz_init(mrb, &b);
mpz_neg(mrb, &b, &a);
mpz_sub_int(mrb, &b, &b, 1);
mpz_sub_int(mrb, &b, 1);
return bint_norm(mrb, bint_new(mrb, &b));
}