fixup! Merge branch 'bigint-embed' of https://github.com/dearblue/mruby into bigint-embed

This commit is contained in:
Yukihiro "Matz" Matsumoto
2024-10-10 22:57:32 +09:00
parent bda2fa39d2
commit 12b97ceb78
+7 -71
View File
@@ -399,6 +399,7 @@ mpz_sub(mrb_state *mrb, struct RBigint *z, struct RBigint *x, struct RBigint *y)
mpz_set(mrb, &u, y);
RBIGINT_SET_SIGN(&u, -(RBIGINT_SIGN(&u)));
mpz_add(mrb, z, x, &u);
mpz_clear(mrb, &u);
}
/* x = y - n */
@@ -418,7 +419,7 @@ static void
mpz_mul(mrb_state *mrb, struct RBigint *ww, struct RBigint *u, struct RBigint *v)
{
if (zero_p(u) || zero_p(v)) {
zero(ww);
mpz_set_int(mrb, ww, 0);
return;
}
@@ -496,7 +497,7 @@ urshift(mrb_state *mrb, struct RBigint *c1, struct RBigint *a, size_t n)
if (n == 0)
mpz_set(mrb, c1, a);
else if (uzero_p(a)) {
zero(c1);
mpz_set_int(mrb, c1, 0);
}
else {
struct RBigint c;
@@ -527,7 +528,7 @@ ulshift(mrb_state *mrb, struct RBigint *c1, struct RBigint *a, size_t n)
if (n == 0)
mpz_set(mrb, c1, a);
else if (uzero_p(a)) {
zero(c1);
mpz_set_int(mrb, c1, 0);
}
else {
mp_limb cc = 0;
@@ -760,78 +761,13 @@ mpz_sizeinbase(struct RBigint *x, mrb_int base)
return bits/(j-1)+1;
}
/* x = y * n (only called from mpz_init_set_str) */
/* assumes x and n are positive or zero */
/* assumes n is small (fits in mp_limb) */
static void
mpz_mul_int(mrb_state *mrb, mpz_t *x, mrb_int n)
{
if (n == 0 || zero_p(x)) {
zero(x);
return;
}
size_t x_sz = x->sz;
size_t new_sz = x_sz + 1; // Maximum possible size after multiplication
// Reallocate x if necessary
mpz_realloc(mrb, x, new_sz);
mp_dbl_limb cc = 0;
mp_limb n_limb = (mp_limb)n;
for (size_t i = 0; i < x_sz; i++) {
// Multiply each limb and add carry
cc += (mp_dbl_limb)x->p[i] * n_limb;
x->p[i] = LOW(cc);
cc = HIGH(cc);
}
if (cc) {
// If there is a remaining carry, store it
x->p[x_sz] = (mp_limb)cc;
} else {
x->sz = x_sz;
}
x->sn = 1;
trim(x);
}
/* x = y + n (only called from mpz_init_set_str) */
/* assumes x and n are positive or zero */
/* assumes n is 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;
}
// Assume x is positive and n is a small positive integer (n < 36)
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
x->p[i] = LOW(carry); // Store lower 32 bits in current limb
carry = HIGH(carry); // Update carry with higher bits
}
if (carry != 0) {
mpz_realloc(mrb, x, x->sz + 1);
x->p[x->sz-1] = (mp_limb)carry;
x->sn = 1;
}
trim(x);
}
static int
mpz_init_set_str(mrb_state *mrb, struct RBigint *x, const char *s, mrb_int len, mrb_int base)
{
int retval = 0;
short sn;
uint8_t k;
mpz_init(mrb, x);
zero(x);
if (*s == '-') {
sn = -1; s++;
@@ -854,8 +790,8 @@ mpz_init_set_str(mrb_state *mrb, struct RBigint *x, const char *s, mrb_int len,
retval = (-1);
break;
}
mpz_mul_int(mrb, x, base);
mpz_add_int(mrb, x, k);
mpz_mul_int(mrb, x, x, base);
mpz_add_int(mrb, x, x, k);
}
RBIGINT_SET_SIGN(x, sn);
return retval;