mruby-bigint: disable pool if MRB_BIGINT_POOL_SIZE is 0

This commit introduces conditional compilation to disable the memory pool for
big integers if MRB_BIGINT_POOL_SIZE is defined as 0. This allows for better
control over memory usage on devices with restricted stack size.

Co-authored-by: Gemini <gemini@google.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-07-29 10:22:21 +09:00
parent 06651722f0
commit 123ffe7065
+165 -142
View File
@@ -24,11 +24,19 @@
#define imin(x,y) (((x)<(y))?(x):(y))
#define dg(x,i) (((size_t)i < (x)->sz)?(x)->p[i]:0)
/* Scoped Memory Pool Infrastructure */
#ifndef MRB_BIGINT_POOL_SIZE
#define MRB_BIGINT_POOL_SIZE 512 /* 2KB on 32-bit, 4KB on 64-bit */
#endif
/* Scoped Memory Pool Infrastructure */
#if MRB_BIGINT_POOL_SIZE == 0
#define mpz_ctx_t mrb_state
#define MPZ_MRB(ctx) (ctx)
#define MPZ_HAS_POOL(ctx) (0)
#define MPZ_CTX_INIT(mrb_ptr, ctx, pool_ptr) mrb_state *ctx = (mrb_ptr);
#define pool_save(ctx) 0
#define pool_restore(ctx, state) (void)state
#else
typedef struct mpz_pool {
mp_limb data[MRB_BIGINT_POOL_SIZE];
size_t used;
@@ -44,14 +52,14 @@ typedef struct mpz_context {
#define MPZ_CTX_INIT(mrb_ptr, ctx, pool_ptr) \
mpz_pool_t pool ## _storage = {0};\
mpz_pool_t *pool_ptr = &pool ## _storage;\
mpz_ctx_t ctx = ((mpz_ctx_t){.mrb = (mrb_ptr), .pool = (pool_ptr)})
mpz_ctx_t ctx ## _struct = ((mpz_ctx_t){.mrb = (mrb_ptr), .pool = (pool_ptr)}); \
mpz_ctx_t *ctx = &(ctx ## _struct);
/* Access macros for readability */
#define MPZ_MRB(ctx) ((ctx)->mrb)
#define MPZ_POOL(ctx) ((ctx)->pool)
#define MPZ_HAS_POOL(ctx) ((ctx)->pool != NULL)
/* Pool allocation functions */
static size_t
pool_save(mpz_ctx_t *ctx)
{
@@ -79,6 +87,7 @@ pool_alloc(mpz_pool_t *pool, size_t limbs)
pool->used += limbs;
return ptr;
}
#endif
static void
mpz_init(mpz_ctx_t *ctx, mpz_t *s)
@@ -109,12 +118,14 @@ mpz_init_capa(mpz_ctx_t *ctx, mpz_t *s, size_t hint)
}
}
#if MRB_BIGINT_POOL_SIZE > 0
/* Pool-preferred allocation (future: mpz_init_temp) */
static void
mpz_init_temp(mpz_ctx_t *ctx, mpz_t *s, size_t hint)
{
s->sn = 0;
if (hint > 0 && MPZ_HAS_POOL(ctx)) {
mp_limb *pool_ptr = pool_alloc(MPZ_POOL(ctx), hint);
if (pool_ptr) {
@@ -123,12 +134,15 @@ mpz_init_temp(mpz_ctx_t *ctx, mpz_t *s, size_t hint)
return;
}
}
/* Fallback to heap allocation */
mpz_init_capa(ctx, s, hint);
}
#else
#define mpz_init_temp(ctx, s, hint) mpz_init_capa(ctx, s, hint)
#endif
/* Check if mpz_t uses pool memory */
#if MRB_BIGINT_POOL_SIZE > 0
static int
is_pool_memory(mpz_t *z, mpz_pool_t *pool)
{
@@ -138,6 +152,7 @@ is_pool_memory(mpz_t *z, mpz_pool_t *pool)
uintptr_t pool_end = pool_start + sizeof(pool->data);
return ptr_addr >= pool_start && ptr_addr < pool_end;
}
#endif
static void
mpz_realloc(mpz_ctx_t *ctx, mpz_t *x, size_t size)
@@ -151,6 +166,7 @@ mpz_realloc(mpz_ctx_t *ctx, mpz_t *x, size_t size)
size_t old_sz = x->sz;
#if MRB_BIGINT_POOL_SIZE > 0
/* Pool memory cannot be reallocated - must use heap */
if (MPZ_HAS_POOL(ctx) && is_pool_memory(x, MPZ_POOL(ctx))) {
/* Allocate new heap memory and copy from pool */
@@ -161,9 +177,12 @@ mpz_realloc(mpz_ctx_t *ctx, mpz_t *x, size_t size)
x->p = new_p;
}
else {
#endif
/* Regular heap reallocation */
x->p = (mp_limb*)mrb_realloc(MPZ_MRB(ctx), x->p, size * sizeof(mp_limb));
#if MRB_BIGINT_POOL_SIZE > 0
}
#endif
/* Zero-initialize new limbs */
for (size_t i = old_sz; i < size; i++) {
@@ -270,12 +289,16 @@ static void
mpz_clear(mpz_ctx_t *ctx, mpz_t *s)
{
if (s->p) {
#if MRB_BIGINT_POOL_SIZE > 0
if (MPZ_HAS_POOL(ctx) && is_pool_memory(s, MPZ_POOL(ctx))) {
/* Pool memory - don't free, just mark as unused */
}
else {
#endif
mrb_free(MPZ_MRB(ctx), s->p);
#if MRB_BIGINT_POOL_SIZE > 0
}
#endif
s->p = NULL;
}
s->sn = 0;
@@ -2239,7 +2262,7 @@ mrb_value
mrb_bint_new_int(mrb_state *mrb, mrb_int x)
{
MPZ_CTX_INIT(mrb, ctx, pool);
struct RBigint *b = bint_new_int(&ctx, x);
struct RBigint *b = bint_new_int(ctx, x);
return mrb_obj_value(b);
}
@@ -2250,8 +2273,8 @@ mrb_bint_new_int64(mrb_state *mrb, int64_t n)
mpz_t x;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_set_int64(&ctx, &x, n);
struct RBigint *b = bint_new(&ctx, &x);
mpz_set_int64(ctx, &x, n);
struct RBigint *b = bint_new(ctx, &x);
return mrb_obj_value(b);
}
#endif
@@ -2262,9 +2285,9 @@ mrb_bint_new_uint64(mrb_state *mrb, uint64_t x)
mpz_t z;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_set_uint64(&ctx, &z, x);
struct RBigint *b = bint_new(&ctx, &z);
mpz_init(ctx, &z);
mpz_set_uint64(ctx, &z, x);
struct RBigint *b = bint_new(ctx, &z);
return mrb_obj_value(b);
}
@@ -2281,11 +2304,11 @@ mrb_bint_new_str(mrb_state *mrb, const char *x, mrb_int len, mrb_int base)
mrb_assert(2 <= base && base <= 36);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init_set_str(&ctx, &z, x, len, base);
mpz_init_set_str(ctx, &z, x, len, base);
if (sn < 0) {
z.sn = sn;
}
struct RBigint *b = bint_new(&ctx, &z);
struct RBigint *b = bint_new(ctx, &z);
return mrb_obj_value(b);
}
@@ -2309,7 +2332,7 @@ mrb_gc_free_bint(mrb_state *mrb, struct RBasic *x)
MPZ_CTX_INIT(mrb, ctx, pool);
if (!RBIGINT_EMBED_P(b)) {
mpz_clear(&ctx, &b->as.heap);
mpz_clear(ctx, &b->as.heap);
}
}
@@ -2338,7 +2361,7 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_t r;
mpz_init(&ctx, &r);
mpz_init(ctx, &r);
r.sn = sn;
mrb_float b = (double)DIG_BASE;
@@ -2348,7 +2371,7 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
for (rn = 1; x >= b; rn++)
x *= bi;
mpz_realloc(&ctx, &r, rn);
mpz_realloc(ctx, &r, rn);
mp_limb *rp = r.p;
for (size_t i=rn-1;;i--) {
mp_limb f = LOW((mp_limb)x);
@@ -2357,7 +2380,7 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
rp[i] = f;
if (i == 0) break;
}
return bint_norm(mrb, bint_new(&ctx, &r));
return bint_norm(mrb, bint_new(ctx, &r));
}
mrb_float
@@ -2475,22 +2498,22 @@ mrb_bint_add_n(mrb_state *mrb, mrb_value x, mrb_value y)
if (mrb_integer_p(y)) {
mrb_int n = mrb_integer(y);
if (int_fit_limb_p(n)) {
mpz_init_set(&ctx, &z, &a);
mpz_init_set(ctx, &z, &a);
if ((n > 0) ^ (z.sn > 0)) {
mpz_sub_int(&ctx, &z, n<0 ? -n : n);
mpz_sub_int(ctx, &z, n<0 ? -n : n);
}
else {
mpz_add_int(&ctx, &z, n<0 ? -n : n);
mpz_add_int(ctx, &z, n<0 ? -n : n);
}
struct RBigint *v = bint_new(&ctx, &z);
struct RBigint *v = bint_new(ctx, &z);
return mrb_obj_value(v);
}
}
y = mrb_as_bint(mrb, y);
bint_as_mpz(RBIGINT(y), &b);
mpz_init(&ctx, &z);
mpz_add(&ctx, &z, &a, &b);
struct RBigint *v = bint_new(&ctx, &z);
mpz_init(ctx, &z);
mpz_add(ctx, &z, &a, &b);
struct RBigint *v = bint_new(ctx, &z);
return mrb_obj_value(v);
}
@@ -2519,22 +2542,22 @@ mrb_bint_sub_n(mrb_state *mrb, mrb_value x, mrb_value y)
if (mrb_integer_p(y)) {
mrb_int n = mrb_integer(y);
if (int_fit_limb_p(n)) {
mpz_init_set(&ctx, &z, &a);
mpz_init_set(ctx, &z, &a);
if ((n > 0) ^ (z.sn > 0)) {
mpz_add_int(&ctx, &z, n<0 ? -n : n);
mpz_add_int(ctx, &z, n<0 ? -n : n);
}
else {
mpz_sub_int(&ctx, &z, n<0 ? -n : n);
mpz_sub_int(ctx, &z, n<0 ? -n : n);
}
struct RBigint *v = bint_new(&ctx, &z);
struct RBigint *v = bint_new(ctx, &z);
return mrb_obj_value(v);
}
}
y = mrb_as_bint(mrb, y);
bint_as_mpz(RBIGINT(y), &b);
mpz_init(&ctx, &z);
mpz_sub(&ctx, &z, &a, &b);
struct RBigint *v = bint_new(&ctx, &z);
mpz_init(ctx, &z);
mpz_sub(ctx, &z, &a, &b);
struct RBigint *v = bint_new(ctx, &z);
return mrb_obj_value(v);
}
@@ -2562,9 +2585,9 @@ bint_mul(mrb_state *mrb, mrb_value x, mrb_value y)
bint_as_mpz(RBIGINT(y), &b);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_mul(&ctx, &z, &a, &b);
return bint_new(&ctx, &z);
mpz_init(ctx, &z);
mpz_mul(ctx, &z, &a, &b);
return bint_new(ctx, &z);
}
mrb_value
@@ -2615,9 +2638,9 @@ mrb_bint_div(mrb_state *mrb, mrb_value x, mrb_value y)
bint_as_mpz(RBIGINT(x), &a);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_mdiv(&ctx, &z, &a, &b);
return bint_norm(mrb, bint_new(&ctx, &z));
mpz_init(ctx, &z);
mpz_mdiv(ctx, &z, &a, &b);
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -2626,13 +2649,13 @@ mrb_bint_add_ii(mrb_state *mrb, mrb_int x, mrb_int y)
mpz_t a, b, z;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_init_set_int(&ctx, &a, x);
mpz_init_set_int(&ctx, &b, y);
mpz_add(&ctx, &z, &a, &b);
mpz_clear(&ctx, &a);
mpz_clear(&ctx, &b);
return bint_norm(mrb, bint_new(&ctx, &z));
mpz_init(ctx, &z);
mpz_init_set_int(ctx, &a, x);
mpz_init_set_int(ctx, &b, y);
mpz_add(ctx, &z, &a, &b);
mpz_clear(ctx, &a);
mpz_clear(ctx, &b);
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -2641,13 +2664,13 @@ mrb_bint_sub_ii(mrb_state *mrb, mrb_int x, mrb_int y)
mpz_t a, b, z;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_init_set_int(&ctx, &a, x);
mpz_init_set_int(&ctx, &b, y);
mpz_sub(&ctx, &z, &a, &b);
mpz_clear(&ctx, &a);
mpz_clear(&ctx, &b);
return bint_norm(mrb, bint_new(&ctx, &z));
mpz_init(ctx, &z);
mpz_init_set_int(ctx, &a, x);
mpz_init_set_int(ctx, &b, y);
mpz_sub(ctx, &z, &a, &b);
mpz_clear(ctx, &a);
mpz_clear(ctx, &b);
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -2656,13 +2679,13 @@ mrb_bint_mul_ii(mrb_state *mrb, mrb_int x, mrb_int y)
mpz_t a, b, z;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_init_set_int(&ctx, &a, x);
mpz_init_set_int(&ctx, &b, y);
mpz_mul(&ctx, &z, &a, &b);
mpz_clear(&ctx, &a);
mpz_clear(&ctx, &b);
return bint_norm(mrb, bint_new(&ctx, &z));
mpz_init(ctx, &z);
mpz_init_set_int(ctx, &a, x);
mpz_init_set_int(ctx, &b, y);
mpz_mul(ctx, &z, &a, &b);
mpz_clear(ctx, &a);
mpz_clear(ctx, &b);
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -2687,9 +2710,9 @@ mrb_bint_mod(mrb_state *mrb, mrb_value x, mrb_value y)
bint_as_mpz(RBIGINT(x), &a);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_mmod(&ctx, &z, &a, &b);
return bint_norm(mrb, bint_new(&ctx, &z));
mpz_init(ctx, &z);
mpz_mmod(ctx, &z, &a, &b);
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -2709,9 +2732,9 @@ mrb_bint_rem(mrb_state *mrb, mrb_value x, mrb_value y)
bint_as_mpz(RBIGINT(x), &a);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &z);
mpz_mod(&ctx, &z, &a, &b);
return bint_norm(mrb, bint_new(&ctx, &z));
mpz_init(ctx, &z);
mpz_mod(ctx, &z, &a, &b);
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -2731,10 +2754,10 @@ mrb_bint_divmod(mrb_state *mrb, mrb_value x, mrb_value y)
bint_as_mpz(RBIGINT(x), &a);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &c);
mpz_init(&ctx, &d);
mpz_mdivmod(&ctx, &c, &d, &a, &b);
return mrb_assoc_new(mrb, bint_norm(mrb, bint_new(&ctx, &c)), bint_norm(mrb, bint_new(&ctx, &d)));
mpz_init(ctx, &c);
mpz_init(ctx, &d);
mpz_mdivmod(ctx, &c, &d, &a, &b);
return mrb_assoc_new(mrb, bint_norm(mrb, bint_new(ctx, &c)), bint_norm(mrb, bint_new(ctx, &d)));
}
mrb_int
@@ -2767,7 +2790,7 @@ mrb_bint_cmp(mrb_state *mrb, mrb_value x, mrb_value y)
mpz_t b;
bint_as_mpz(RBIGINT(y), &b);
MPZ_CTX_INIT(mrb, ctx, pool);
return mpz_cmp(&ctx, &a, &b);
return mpz_cmp(ctx, &a, &b);
}
mrb_value
@@ -2787,9 +2810,9 @@ mrb_bint_pow(mrb_state *mrb, mrb_value x, mrb_value y)
mpz_t z;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_pow(&ctx, &z, &a, mrb_integer(y));
mpz_pow(ctx, &z, &a, mrb_integer(y));
struct RBigint *b = bint_new(&ctx, &z);
struct RBigint *b = bint_new(ctx, &z);
return mrb_obj_value(b);
}
@@ -2803,7 +2826,7 @@ mrb_bint_powm(mrb_state *mrb, mrb_value x, mrb_value exp, mrb_value mod)
if (mrb_integer_p(mod)) {
mrb_int m = mrb_integer(mod);
if (m == 0) mrb_int_zerodiv(mrb);
mpz_init_set_int(&ctx, &c, m);
mpz_init_set_int(ctx, &c, m);
}
else {
mod = mrb_as_bint(mrb, mod);
@@ -2812,22 +2835,22 @@ mrb_bint_powm(mrb_state *mrb, mrb_value x, mrb_value exp, mrb_value mod)
mrb_int_zerodiv(mrb);
}
}
mpz_init(&ctx, &z);
mpz_init(ctx, &z);
if (mrb_bigint_p(exp)) {
bint_as_mpz(RBIGINT(exp), &b);
if (b.sn < 0) goto raise;
mpz_powm(&ctx, &z, &a, &b, &c);
mpz_powm(ctx, &z, &a, &b, &c);
}
else {
mrb_int e = mrb_integer(exp);
if (e < 0) goto raise;
mpz_powm_i(&ctx, &z, &a, e, &c);
mpz_powm_i(ctx, &z, &a, e, &c);
}
if (mrb_integer_p(mod)) mpz_clear(&ctx, &c);
return bint_norm(mrb, bint_new(&ctx, &z));
if (mrb_integer_p(mod)) mpz_clear(ctx, &c);
return bint_norm(mrb, bint_new(ctx, &z));
raise:
if (mrb_integer_p(mod)) mpz_clear(&ctx, &c);
if (mrb_integer_p(mod)) mpz_clear(ctx, &c);
mrb_raise(mrb, E_ARGUMENT_ERROR, "int.pow(n,m): n must be positive");
/* not reached */
return mrb_nil_value();
@@ -2848,7 +2871,7 @@ mrb_bint_to_s(mrb_state *mrb, mrb_value x, mrb_int base)
}
mrb_value str = mrb_str_new(mrb, NULL, len+2);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_get_str(&ctx, RSTRING_PTR(str), len, base, &a);
mpz_get_str(ctx, RSTRING_PTR(str), len, base, &a);
RSTR_SET_LEN(RSTRING(str), strlen(RSTRING_PTR(str)));
return str;
}
@@ -2874,9 +2897,9 @@ mrb_bint_and(mrb_state *mrb, mrb_value x, mrb_value y)
if (zero_p(&a) || zero_p(&b)) return mrb_fixnum_value(0);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &c);
mpz_and(&ctx, &c, &a, &b);
return bint_norm(mrb, bint_new(&ctx, &c));
mpz_init(ctx, &c);
mpz_and(ctx, &c, &a, &b);
return bint_norm(mrb, bint_new(ctx, &c));
}
mrb_value
@@ -2896,9 +2919,9 @@ mrb_bint_or(mrb_state *mrb, mrb_value x, mrb_value y)
bint_as_mpz(RBIGINT(y), &b);
if (zero_p(&a)) return y;
if (zero_p(&b)) return x;
mpz_init(&ctx, &c);
mpz_or(&ctx, &c, &b, &a);
return bint_norm(mrb, bint_new(&ctx, &c));
mpz_init(ctx, &c);
mpz_or(ctx, &c, &b, &a);
return bint_norm(mrb, bint_new(ctx, &c));
}
mrb_value
@@ -2912,18 +2935,18 @@ mrb_bint_xor(mrb_state *mrb, mrb_value x, mrb_value y)
mrb_int z = mrb_integer(y);
if (z == 0) return x;
if (0 < z && (mp_dbl_limb)z < DIG_BASE) {
mpz_init_set(&ctx, &c, &a);
mpz_init_set(ctx, &c, &a);
c.p[0] ^= z;
return bint_norm(mrb, bint_new(&ctx, &c));
return bint_norm(mrb, bint_new(ctx, &c));
}
}
y = mrb_as_bint(mrb, y);
bint_as_mpz(RBIGINT(y), &b);
if (zero_p(&a)) return y;
if (zero_p(&b)) return x;
mpz_init(&ctx, &c);
mpz_xor(&ctx, &c, &a, &b);
return bint_norm(mrb, bint_new(&ctx, &c));
mpz_init(ctx, &c);
mpz_xor(ctx, &c, &a, &b);
return bint_norm(mrb, bint_new(ctx, &c));
}
mrb_value
@@ -2933,9 +2956,9 @@ mrb_bint_neg(mrb_state *mrb, mrb_value x)
MPZ_CTX_INIT(mrb, ctx, pool);
bint_as_mpz(RBIGINT(x), &a);
mpz_init(&ctx, &b);
mpz_neg(&ctx, &b, &a);
struct RBigint *b2 = bint_new(&ctx, &b);
mpz_init(ctx, &b);
mpz_neg(ctx, &b, &a);
struct RBigint *b2 = bint_new(ctx, &b);
/* no normalization */
return mrb_obj_value(b2);
}
@@ -2947,10 +2970,10 @@ mrb_bint_rev(mrb_state *mrb, mrb_value x)
MPZ_CTX_INIT(mrb, ctx, pool);
bint_as_mpz(RBIGINT(x), &a);
mpz_init(&ctx, &b);
mpz_neg(&ctx, &b, &a);
mpz_sub_int(&ctx, &b, 1);
return bint_norm(mrb, bint_new(&ctx, &b));
mpz_init(ctx, &b);
mpz_neg(ctx, &b, &a);
mpz_sub_int(ctx, &b, 1);
return bint_norm(mrb, bint_new(ctx, &b));
}
mrb_value
@@ -2960,14 +2983,14 @@ mrb_bint_lshift(mrb_state *mrb, mrb_value x, mrb_int width)
MPZ_CTX_INIT(mrb, ctx, pool);
bint_as_mpz(RBIGINT(x), &a);
mpz_init(&ctx, &z);
mpz_init(ctx, &z);
if (width < 0) {
mpz_div_2exp(&ctx, &z, &a, -width);
mpz_div_2exp(ctx, &z, &a, -width);
}
else {
mpz_mul_2exp(&ctx, &z, &a, width);
mpz_mul_2exp(ctx, &z, &a, width);
}
return bint_norm(mrb, bint_new(&ctx, &z));
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -2977,14 +3000,14 @@ mrb_bint_rshift(mrb_state *mrb, mrb_value x, mrb_int width)
MPZ_CTX_INIT(mrb, ctx, pool);
bint_as_mpz(RBIGINT(x), &a);
mpz_init(&ctx, &z);
mpz_init(ctx, &z);
if (width < 0) {
mpz_mul_2exp(&ctx, &z, &a, -width);
mpz_mul_2exp(ctx, &z, &a, -width);
}
else {
mpz_div_2exp(&ctx, &z, &a, width);
mpz_div_2exp(ctx, &z, &a, width);
}
return bint_norm(mrb, bint_new(&ctx, &z));
return bint_norm(mrb, bint_new(ctx, &z));
}
void
@@ -2995,7 +3018,7 @@ mrb_bint_copy(mrb_state *mrb, mrb_value x, mrb_value y)
bint_as_mpz(RBIGINT(x), &a);
bint_as_mpz(RBIGINT(y), &b);
mpz_init_set(&ctx, &a, &b);
mpz_init_set(ctx, &a, &b);
}
size_t
@@ -3019,10 +3042,10 @@ mrb_bint_sqrt(mrb_state *mrb, mrb_value x)
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_t z;
mpz_init(&ctx, &z);
mpz_sqrt(&ctx, &z, &a);
mpz_init(ctx, &z);
mpz_sqrt(ctx, &z, &a);
return bint_norm(mrb, bint_new(&ctx, &z));
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_int
@@ -3046,12 +3069,12 @@ mrb_bint_from_bytes(mrb_state *mrb, const uint8_t *bytes, mrb_int len)
size_t limb_len = (len + sizeof(mp_limb) - 1) / sizeof(mp_limb);
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init_capa(&ctx, &z, limb_len);
mpz_init_capa(ctx, &z, limb_len);
memcpy(z.p, bytes, len);
z.sn = (len > 0) ? 1 : 0;
z.sz = limb_len;
trim(&z);
return bint_norm(mrb, bint_new(&ctx, &z));
return bint_norm(mrb, bint_new(ctx, &z));
}
mrb_value
@@ -3073,10 +3096,10 @@ mrb_bint_2comp(mrb_state *mrb, mrb_value x)
MPZ_CTX_INIT(mrb, ctx, pool);
bint_as_mpz(RBIGINT(x), &a);
mpz_init(&ctx, &z);
mpz_init(ctx, &z);
mrb_assert(a.sn < 0);
size_t size = a.sz;
mpz_realloc(&ctx, &z, size);
mpz_realloc(ctx, &z, size);
mp_limb *ds = a.p;
mp_limb *dd = z.p;
char carry = 1;
@@ -3087,7 +3110,7 @@ mrb_bint_2comp(mrb_state *mrb, mrb_value x)
}
z.sn = 1;
struct RBigint *b2 = bint_new(&ctx, &z);
struct RBigint *b2 = bint_new(ctx, &z);
return mrb_obj_value(b2);
}
@@ -3098,21 +3121,21 @@ mrb_bint_reduce(mrb_state *mrb, mrb_value *xp, mrb_value *yp)
mpz_t r, x, y, a, b;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &r);
mpz_init(&ctx, &a); mpz_init(&ctx, &b);
mpz_init(ctx, &r);
mpz_init(ctx, &a); mpz_init(ctx, &b);
bint_as_mpz(RBIGINT(*xp), &x);
bint_as_mpz(RBIGINT(*yp), &y);
mpz_gcd(&ctx, &r, &x, &y);
mpz_gcd(ctx, &r, &x, &y);
mpz_mdiv(&ctx, &a, &x, &r);
mpz_mdiv(&ctx, &b, &y, &r);
mpz_mdiv(ctx, &a, &x, &r);
mpz_mdiv(ctx, &b, &y, &r);
mpz_clear(&ctx, &r);
mpz_clear(ctx, &r);
struct RBigint *b1 = bint_new(&ctx, &a);
struct RBigint *b2 = bint_new(&ctx, &b);
struct RBigint *b1 = bint_new(ctx, &a);
struct RBigint *b2 = bint_new(ctx, &b);
*xp = mrb_obj_value(b1);
*yp = mrb_obj_value(b2);
}
@@ -3124,13 +3147,13 @@ mrb_bint_gcd(mrb_state *mrb, mrb_value x, mrb_value y)
mpz_t r, a, b;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &r);
mpz_init(ctx, &r);
bint_as_mpz(RBIGINT(x), &a);
bint_as_mpz(RBIGINT(y), &b);
mpz_gcd(&ctx, &r, &a, &b);
mpz_gcd(ctx, &r, &a, &b);
struct RBigint *result = bint_new(&ctx, &r);
struct RBigint *result = bint_new(ctx, &r);
return bint_norm(mrb, result);
}
@@ -3150,28 +3173,28 @@ mrb_bint_lcm(mrb_state *mrb, mrb_value x, mrb_value y)
size_t y_size = RBIGINT_EMBED_P(RBIGINT(y)) ? RBIGINT_EMBED_SIZE(RBIGINT(y)) : RBIGINT(y)->as.heap.sz;
size_t max_size = (x_size > y_size) ? x_size : y_size;
mpz_init_temp(&ctx, &gcd_val, max_size);
mpz_init_temp(&ctx, &abs_x, x_size);
mpz_init_temp(&ctx, &abs_y, y_size);
mpz_init_temp(&ctx, &product, x_size + y_size + 1);
mpz_init_temp(&ctx, &result_mpz, x_size + y_size + 1);
mpz_init_temp(ctx, &gcd_val, max_size);
mpz_init_temp(ctx, &abs_x, x_size);
mpz_init_temp(ctx, &abs_y, y_size);
mpz_init_temp(ctx, &product, x_size + y_size + 1);
mpz_init_temp(ctx, &result_mpz, x_size + y_size + 1);
bint_as_mpz(RBIGINT(x), &x_mpz);
bint_as_mpz(RBIGINT(y), &y_mpz);
mpz_abs(&ctx, &abs_x, &x_mpz);
mpz_abs(&ctx, &abs_y, &y_mpz);
mpz_abs(ctx, &abs_x, &x_mpz);
mpz_abs(ctx, &abs_y, &y_mpz);
mpz_gcd(&ctx, &gcd_val, &abs_x, &abs_y);
mpz_mul(&ctx, &product, &abs_x, &abs_y);
mpz_mdiv(&ctx, &result_mpz, &product, &gcd_val);
mpz_gcd(ctx, &gcd_val, &abs_x, &abs_y);
mpz_mul(ctx, &product, &abs_x, &abs_y);
mpz_mdiv(ctx, &result_mpz, &product, &gcd_val);
mpz_clear(&ctx, &gcd_val);
mpz_clear(&ctx, &abs_x);
mpz_clear(&ctx, &abs_y);
mpz_clear(&ctx, &product);
mpz_clear(ctx, &gcd_val);
mpz_clear(ctx, &abs_x);
mpz_clear(ctx, &abs_y);
mpz_clear(ctx, &product);
struct RBigint *result = bint_new(&ctx, &result_mpz);
struct RBigint *result = bint_new(ctx, &result_mpz);
return mrb_obj_value(result);
}
@@ -3181,10 +3204,10 @@ mrb_bint_abs(mrb_state *mrb, mrb_value x)
mpz_t a, result_mpz;
MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(&ctx, &result_mpz);
mpz_init(ctx, &result_mpz);
bint_as_mpz(RBIGINT(x), &a);
mpz_abs(&ctx, &result_mpz, &a);
mpz_abs(ctx, &result_mpz, &a);
struct RBigint *result = bint_new(&ctx, &result_mpz);
struct RBigint *result = bint_new(ctx, &result_mpz);
return mrb_obj_value(result);
}