mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-bigint: improve context management and memory handling
Introduce `MPZ_CTX_INIT` macro for simplified context initialization. Refactor `div_limb` to use temporary `mpz_t` variables and `mpz_move` for robust result assignment. Update various `bint` functions to leverage the new context initialization and pass `ctx` for consistent memory management. Co-authored-by: Gemini <gemini@google.com>
This commit is contained in:
+139
-196
@@ -40,8 +40,10 @@ typedef struct mpz_context {
|
||||
} mpz_ctx_t;
|
||||
|
||||
/* Convenience macros for context creation */
|
||||
#define MPZ_CTX_HEAP(mrb_ptr) ((mpz_ctx_t){.mrb = (mrb_ptr), .pool = NULL})
|
||||
#define MPZ_CTX_POOL(mrb_ptr, pool_ptr) ((mpz_ctx_t){.mrb = (mrb_ptr), .pool = (pool_ptr)})
|
||||
#define MPZ_CTX_INIT(mrb_ptr, ctx, pool_ptr) \
|
||||
mpz_pool_t pool ## _storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};\
|
||||
mpz_pool_t *pool_ptr = &pool ## _storage;\
|
||||
mpz_ctx_t ctx = ((mpz_ctx_t){.mrb = (mrb_ptr), .pool = (pool_ptr)})
|
||||
|
||||
/* Access macros for readability */
|
||||
#define MPZ_MRB(ctx) ((ctx)->mrb)
|
||||
@@ -692,10 +694,13 @@ div_limb(mpz_ctx_t *ctx, mpz_t *q, mpz_t *r, mpz_t *x, mp_limb d)
|
||||
{
|
||||
mrb_state *mrb = MPZ_MRB(ctx);
|
||||
|
||||
size_t pool_state = pool_save(ctx);
|
||||
mpz_t temp_q, temp_r;
|
||||
|
||||
if (zero_p(x)) {
|
||||
zero(q);
|
||||
zero(r);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (d == 0) {
|
||||
@@ -714,9 +719,9 @@ div_limb(mpz_ctx_t *ctx, mpz_t *q, mpz_t *r, mpz_t *x, mp_limb d)
|
||||
|
||||
/* Quotient = x >> shift */
|
||||
if (shift == 0) {
|
||||
mpz_init_auto(ctx, q, x->sz);
|
||||
mpz_init_auto(ctx, r, 1);
|
||||
mpz_set(ctx, q, x);
|
||||
mpz_init(ctx, &temp_q);
|
||||
mpz_init(ctx, &temp_r);
|
||||
mpz_set(ctx, &temp_q, x);
|
||||
}
|
||||
else {
|
||||
/* Manual right shift implementation */
|
||||
@@ -724,20 +729,20 @@ div_limb(mpz_ctx_t *ctx, mpz_t *q, mpz_t *r, mpz_t *x, mp_limb d)
|
||||
size_t bit_shift = shift % DIG_SIZE;
|
||||
|
||||
if (limb_shift >= x->sz) {
|
||||
mpz_init_auto(ctx, q, 1);
|
||||
mpz_init_auto(ctx, r, 1);
|
||||
zero(q);
|
||||
mpz_init(ctx, &temp_q);
|
||||
mpz_init(ctx, &temp_r);
|
||||
zero(&temp_q);
|
||||
}
|
||||
else {
|
||||
size_t new_size = x->sz - limb_shift;
|
||||
mpz_init_auto(ctx, q, new_size);
|
||||
mpz_init_auto(ctx, r, 1);
|
||||
mpz_realloc(ctx, q, new_size);
|
||||
mpz_init(ctx, &temp_q);
|
||||
mpz_init(ctx, &temp_r);
|
||||
mpz_realloc(ctx, &temp_q, new_size);
|
||||
|
||||
if (bit_shift == 0) {
|
||||
/* Simple limb copy */
|
||||
for (size_t i = 0; i < new_size; i++) {
|
||||
q->p[i] = x->p[i + limb_shift];
|
||||
temp_q.p[i] = x->p[i + limb_shift];
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -745,68 +750,77 @@ div_limb(mpz_ctx_t *ctx, mpz_t *q, mpz_t *r, mpz_t *x, mp_limb d)
|
||||
mp_limb carry = 0;
|
||||
for (size_t i = new_size; i > 0; i--) {
|
||||
mp_limb current = x->p[i - 1 + limb_shift];
|
||||
q->p[i - 1] = (current >> bit_shift) | carry;
|
||||
temp_q.p[i - 1] = (current >> bit_shift) | carry;
|
||||
carry = (current << (DIG_SIZE - bit_shift)) & DIG_MASK;
|
||||
}
|
||||
}
|
||||
q->sz = new_size;
|
||||
trim(q);
|
||||
q->sn = (q->sz == 0) ? 0 : 1;
|
||||
temp_q.sz = new_size;
|
||||
trim(&temp_q);
|
||||
temp_q.sn = (temp_q.sz == 0) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remainder = x & (d - 1) */
|
||||
/* r is already initialized in all code paths above */
|
||||
mpz_realloc(ctx, r, 1);
|
||||
r->p[0] = x->p[0] & (d - 1);
|
||||
r->sz = (r->p[0] == 0) ? 0 : 1;
|
||||
r->sn = (r->sz == 0) ? 0 : 1;
|
||||
return;
|
||||
/* temp_r is already initialized in all code paths above */
|
||||
mpz_realloc(ctx, &temp_r, 1);
|
||||
temp_r.p[0] = x->p[0] & (d - 1);
|
||||
temp_r.sz = (temp_r.p[0] == 0) ? 0 : 1;
|
||||
temp_r.sn = (temp_r.sz == 0) ? 0 : 1;
|
||||
mpz_move(ctx, q, &temp_q);
|
||||
mpz_move(ctx, r, &temp_r);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* General single-limb division */
|
||||
if (x->sz == 1) {
|
||||
/* Both dividend and divisor are single limb */
|
||||
mpz_init_auto(ctx, q, 1);
|
||||
mpz_init_auto(ctx, r, 1);
|
||||
mpz_realloc(ctx, q, 1);
|
||||
mpz_realloc(ctx, r, 1);
|
||||
mpz_init(ctx, &temp_q);
|
||||
mpz_init(ctx, &temp_r);
|
||||
mpz_realloc(ctx, &temp_q, 1);
|
||||
mpz_realloc(ctx, &temp_r, 1);
|
||||
|
||||
q->p[0] = x->p[0] / d;
|
||||
r->p[0] = x->p[0] % d;
|
||||
temp_q.p[0] = x->p[0] / d;
|
||||
temp_r.p[0] = x->p[0] % d;
|
||||
|
||||
q->sz = (q->p[0] == 0) ? 0 : 1;
|
||||
q->sn = (q->sz == 0) ? 0 : 1;
|
||||
temp_q.sz = (temp_q.p[0] == 0) ? 0 : 1;
|
||||
temp_q.sn = (temp_q.sz == 0) ? 0 : 1;
|
||||
|
||||
r->sz = (r->p[0] == 0) ? 0 : 1;
|
||||
r->sn = (r->sz == 0) ? 0 : 1;
|
||||
return;
|
||||
temp_r.sz = (temp_r.p[0] == 0) ? 0 : 1;
|
||||
temp_r.sn = (temp_r.sz == 0) ? 0 : 1;
|
||||
mpz_move(ctx, q, &temp_q);
|
||||
mpz_move(ctx, r, &temp_r);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Multi-limb dividend, single-limb divisor */
|
||||
size_t n = x->sz;
|
||||
mpz_init_auto(ctx, q, n);
|
||||
mpz_init_auto(ctx, r, 1);
|
||||
mpz_realloc(ctx, q, n);
|
||||
mpz_init_auto(ctx, &temp_q, n);
|
||||
mpz_init_auto(ctx, &temp_r, 1);
|
||||
|
||||
mp_dbl_limb remainder = 0;
|
||||
|
||||
/* Process from most significant limb to least significant */
|
||||
for (size_t i = n; i > 0; i--) {
|
||||
remainder = (remainder << DIG_SIZE) + x->p[i-1];
|
||||
q->p[i-1] = (mp_limb)(remainder / d);
|
||||
temp_q.p[i-1] = (mp_limb)(remainder / d);
|
||||
remainder = remainder % d;
|
||||
}
|
||||
|
||||
/* Set remainder */
|
||||
mpz_realloc(ctx, r, 1);
|
||||
r->p[0] = (mp_limb)remainder;
|
||||
r->sz = (remainder == 0) ? 0 : 1;
|
||||
r->sn = (r->sz == 0) ? 0 : 1;
|
||||
temp_r.p[0] = (mp_limb)remainder;
|
||||
temp_r.sz = (remainder == 0) ? 0 : 1;
|
||||
temp_r.sn = (temp_r.sz == 0) ? 0 : 1;
|
||||
|
||||
/* Trim leading zeros from quotient */
|
||||
trim(q);
|
||||
q->sn = (q->sz == 0) ? 0 : 1;
|
||||
trim(&temp_q);
|
||||
temp_q.sn = (temp_q.sz == 0) ? 0 : 1;
|
||||
|
||||
/* Copy results to avoid pool/heap mixing */
|
||||
mpz_move(ctx, q, &temp_q);
|
||||
mpz_move(ctx, r, &temp_r);
|
||||
|
||||
cleanup:
|
||||
pool_restore(ctx, pool_state);
|
||||
}
|
||||
|
||||
|
||||
@@ -2204,40 +2218,35 @@ bint_as_mpz(struct RBigint *b, mpz_t *x)
|
||||
}
|
||||
|
||||
static struct RBigint*
|
||||
bint_new(mrb_state *mrb, mpz_t *x)
|
||||
bint_new(mpz_ctx_t *ctx, mpz_t *x)
|
||||
{
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
struct RBigint *b = MRB_OBJ_ALLOC(mrb, MRB_TT_BIGINT, mrb->integer_class);
|
||||
struct RBigint *b = MRB_OBJ_ALLOC(MPZ_MRB(ctx), MRB_TT_BIGINT, MPZ_MRB(ctx)->integer_class);
|
||||
if (x->sz <= RBIGINT_EMBED_SIZE_MAX) {
|
||||
RBIGINT_SET_EMBED_SIZE(b, x->sz);
|
||||
RBIGINT_SET_EMBED_SIGN(b, x->sn);
|
||||
if (x->p) memcpy(RBIGINT_EMBED_ARY(b), x->p, x->sz*sizeof(mp_limb));
|
||||
mpz_clear(&ctx, x);
|
||||
mpz_clear(ctx, x);
|
||||
}
|
||||
else {
|
||||
RBIGINT_SET_HEAP(b);
|
||||
b->as.heap = *x;
|
||||
mpz_move(ctx, &b->as.heap, x);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static struct RBigint*
|
||||
bint_new_int(mrb_state *mrb, mrb_int n)
|
||||
bint_new_int(mpz_ctx_t *ctx, mrb_int n)
|
||||
{
|
||||
mpz_t x;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
mpz_init_set_int(&ctx, &x, n);
|
||||
return bint_new(mrb, &x);
|
||||
mpz_init_set_int(ctx, &x, n);
|
||||
return bint_new(ctx, &x);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_new_int(mrb_state *mrb, mrb_int x)
|
||||
{
|
||||
struct RBigint *b = bint_new_int(mrb, x);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
struct RBigint *b = bint_new_int(&ctx, x);
|
||||
return mrb_obj_value(b);
|
||||
}
|
||||
|
||||
@@ -2246,12 +2255,10 @@ mrb_value
|
||||
mrb_bint_new_int64(mrb_state *mrb, int64_t n)
|
||||
{
|
||||
mpz_t x;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_set_int64(&ctx, &x, n);
|
||||
struct RBigint *b = bint_new(mrb, &x);
|
||||
struct RBigint *b = bint_new(&ctx, &x);
|
||||
return mrb_obj_value(b);
|
||||
}
|
||||
#endif
|
||||
@@ -2260,13 +2267,11 @@ mrb_value
|
||||
mrb_bint_new_uint64(mrb_state *mrb, uint64_t x)
|
||||
{
|
||||
mpz_t z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_set_uint64(&ctx, &z, x);
|
||||
struct RBigint *b = bint_new(mrb ,&z);
|
||||
struct RBigint *b = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(b);
|
||||
}
|
||||
|
||||
@@ -2281,14 +2286,13 @@ mrb_bint_new_str(mrb_state *mrb, const char *x, mrb_int len, mrb_int base)
|
||||
sn = -1;
|
||||
}
|
||||
mrb_assert(2 <= base && base <= 36);
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_init_set_str(&ctx, &z, x, len, base);
|
||||
if (sn < 0) {
|
||||
z.sn = sn;
|
||||
}
|
||||
struct RBigint *b = bint_new(mrb, &z);
|
||||
struct RBigint *b = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(b);
|
||||
}
|
||||
|
||||
@@ -2309,9 +2313,8 @@ void
|
||||
mrb_gc_free_bint(mrb_state *mrb, struct RBasic *x)
|
||||
{
|
||||
struct RBigint *b = (struct RBigint*)x;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
if (!RBIGINT_EMBED_P(b)) {
|
||||
mpz_clear(&ctx, &b->as.heap);
|
||||
}
|
||||
@@ -2339,10 +2342,8 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
|
||||
if (x < 1.0) {
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_t r;
|
||||
mpz_init(&ctx, &r);
|
||||
r.sn = sn;
|
||||
@@ -2363,7 +2364,7 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
|
||||
rp[i] = f;
|
||||
if (i == 0) break;
|
||||
}
|
||||
return bint_norm(mrb, bint_new(mrb, &r));
|
||||
return bint_norm(mrb, bint_new(&ctx, &r));
|
||||
}
|
||||
|
||||
mrb_float
|
||||
@@ -2475,9 +2476,9 @@ mrb_bint_add_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
mpz_t a, b, z;
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
if (mrb_integer_p(y)) {
|
||||
mrb_int n = mrb_integer(y);
|
||||
if (int_fit_limb_p(n)) {
|
||||
@@ -2488,7 +2489,7 @@ mrb_bint_add_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
else {
|
||||
mpz_add_int(&ctx, &z, n<0 ? -n : n);
|
||||
}
|
||||
struct RBigint *v = bint_new(mrb, &z);
|
||||
struct RBigint *v = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(v);
|
||||
}
|
||||
}
|
||||
@@ -2496,7 +2497,7 @@ mrb_bint_add_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
bint_as_mpz(RBIGINT(y), &b);
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_add(&ctx, &z, &a, &b);
|
||||
struct RBigint *v = bint_new(mrb, &z);
|
||||
struct RBigint *v = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(v);
|
||||
}
|
||||
|
||||
@@ -2519,9 +2520,7 @@ mrb_value
|
||||
mrb_bint_sub_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
mpz_t a, b, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
if (mrb_integer_p(y)) {
|
||||
@@ -2534,7 +2533,7 @@ mrb_bint_sub_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
else {
|
||||
mpz_sub_int(&ctx, &z, n<0 ? -n : n);
|
||||
}
|
||||
struct RBigint *v = bint_new(mrb, &z);
|
||||
struct RBigint *v = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(v);
|
||||
}
|
||||
}
|
||||
@@ -2542,7 +2541,7 @@ mrb_bint_sub_n(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
bint_as_mpz(RBIGINT(y), &b);
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_sub(&ctx, &z, &a, &b);
|
||||
struct RBigint *v = bint_new(mrb, &z);
|
||||
struct RBigint *v = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(v);
|
||||
}
|
||||
|
||||
@@ -2569,12 +2568,10 @@ bint_mul(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
bint_as_mpz(RBIGINT(y), &b);
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_mul(&ctx, &z, &a, &b);
|
||||
return bint_new(mrb, &z);
|
||||
return bint_new(&ctx, &z);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
@@ -2624,21 +2621,17 @@ mrb_bint_div(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_mdiv(&ctx, &z, &a, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_add_ii(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
{
|
||||
mpz_t a, b, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_init_set_int(&ctx, &a, x);
|
||||
@@ -2646,16 +2639,14 @@ mrb_bint_add_ii(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
mpz_add(&ctx, &z, &a, &b);
|
||||
mpz_clear(&ctx, &a);
|
||||
mpz_clear(&ctx, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_sub_ii(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
{
|
||||
mpz_t a, b, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_init_set_int(&ctx, &a, x);
|
||||
@@ -2663,16 +2654,14 @@ mrb_bint_sub_ii(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
mpz_sub(&ctx, &z, &a, &b);
|
||||
mpz_clear(&ctx, &a);
|
||||
mpz_clear(&ctx, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_mul_ii(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
{
|
||||
mpz_t a, b, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_init_set_int(&ctx, &a, x);
|
||||
@@ -2680,7 +2669,7 @@ mrb_bint_mul_ii(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
mpz_mul(&ctx, &z, &a, &b);
|
||||
mpz_clear(&ctx, &a);
|
||||
mpz_clear(&ctx, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
@@ -2704,12 +2693,10 @@ mrb_bint_mod(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_mmod(&ctx, &z, &a, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
@@ -2728,12 +2715,10 @@ mrb_bint_rem(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_mod(&ctx, &z, &a, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
@@ -2752,13 +2737,11 @@ mrb_bint_divmod(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
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(mrb, &c)), bint_norm(mrb, bint_new(mrb, &d)));
|
||||
return mrb_assoc_new(mrb, bint_norm(mrb, bint_new(&ctx, &c)), bint_norm(mrb, bint_new(&ctx, &d)));
|
||||
}
|
||||
|
||||
mrb_int
|
||||
@@ -2790,9 +2773,7 @@ mrb_bint_cmp(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
mpz_t b;
|
||||
bint_as_mpz(RBIGINT(y), &b);
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
return mpz_cmp(&ctx, &a, &b);
|
||||
}
|
||||
|
||||
@@ -2812,12 +2793,10 @@ mrb_bint_pow(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
|
||||
mpz_t z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_pow(&ctx, &z, &a, mrb_integer(y));
|
||||
|
||||
struct RBigint *b = bint_new(mrb, &z);
|
||||
struct RBigint *b = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(b);
|
||||
}
|
||||
|
||||
@@ -2825,9 +2804,7 @@ mrb_value
|
||||
mrb_bint_powm(mrb_state *mrb, mrb_value x, mrb_value exp, mrb_value mod)
|
||||
{
|
||||
mpz_t a, b, c, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
if (mrb_integer_p(mod)) {
|
||||
@@ -2854,7 +2831,7 @@ mrb_bint_powm(mrb_state *mrb, mrb_value x, mrb_value exp, mrb_value mod)
|
||||
mpz_powm_i(&ctx, &z, &a, e, &c);
|
||||
}
|
||||
if (mrb_integer_p(mod)) mpz_clear(&ctx, &c);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
|
||||
raise:
|
||||
if (mrb_integer_p(mod)) mpz_clear(&ctx, &c);
|
||||
@@ -2877,9 +2854,7 @@ mrb_bint_to_s(mrb_state *mrb, mrb_value x, mrb_int base)
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string from Integer");
|
||||
}
|
||||
mrb_value str = mrb_str_new(mrb, NULL, len+2);
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_get_str(&ctx, RSTRING_PTR(str), len, base, &a);
|
||||
RSTR_SET_LEN(RSTRING(str), strlen(RSTRING_PTR(str)));
|
||||
return str;
|
||||
@@ -2905,12 +2880,10 @@ mrb_bint_and(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
bint_as_mpz(RBIGINT(y), &b);
|
||||
if (zero_p(&a) || zero_p(&b)) return mrb_fixnum_value(0);
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_init(&ctx, &c);
|
||||
mpz_and(&ctx, &c, &a, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &c));
|
||||
return bint_norm(mrb, bint_new(&ctx, &c));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
@@ -2925,25 +2898,21 @@ mrb_bint_or(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (z == -1) return y;
|
||||
}
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
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_or(&ctx, &c, &b, &a);
|
||||
return bint_norm(mrb, bint_new(mrb, &c));
|
||||
return bint_norm(mrb, bint_new(&ctx, &c));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_xor(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
mpz_t a, b, c;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
if (mrb_integer_p(y) && a.sn > 0) {
|
||||
@@ -2952,7 +2921,7 @@ mrb_bint_xor(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (0 < z && (mp_dbl_limb)z < DIG_BASE) {
|
||||
mpz_init_set(&ctx, &c, &a);
|
||||
c.p[0] ^= z;
|
||||
return bint_norm(mrb, bint_new(mrb, &c));
|
||||
return bint_norm(mrb, bint_new(&ctx, &c));
|
||||
}
|
||||
}
|
||||
y = mrb_as_bint(mrb, y);
|
||||
@@ -2961,21 +2930,19 @@ mrb_bint_xor(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (zero_p(&b)) return x;
|
||||
mpz_init(&ctx, &c);
|
||||
mpz_xor(&ctx, &c, &a, &b);
|
||||
return bint_norm(mrb, bint_new(mrb, &c));
|
||||
return bint_norm(mrb, bint_new(&ctx, &c));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_neg(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mpz_t a, b;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
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(mrb, &b);
|
||||
struct RBigint *b2 = bint_new(&ctx, &b);
|
||||
/* no normalization */
|
||||
return mrb_obj_value(b2);
|
||||
}
|
||||
@@ -2984,24 +2951,20 @@ mrb_value
|
||||
mrb_bint_rev(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mpz_t a, b;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
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(mrb, &b));
|
||||
return bint_norm(mrb, bint_new(&ctx, &b));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_lshift(mrb_state *mrb, mrb_value x, mrb_int width)
|
||||
{
|
||||
mpz_t a, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
mpz_init(&ctx, &z);
|
||||
@@ -3011,16 +2974,14 @@ mrb_bint_lshift(mrb_state *mrb, mrb_value x, mrb_int width)
|
||||
else {
|
||||
mpz_mul_2exp(&ctx, &z, &a, width);
|
||||
}
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_rshift(mrb_state *mrb, mrb_value x, mrb_int width)
|
||||
{
|
||||
mpz_t a, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
mpz_init(&ctx, &z);
|
||||
@@ -3030,16 +2991,14 @@ mrb_bint_rshift(mrb_state *mrb, mrb_value x, mrb_int width)
|
||||
else {
|
||||
mpz_div_2exp(&ctx, &z, &a, width);
|
||||
}
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
void
|
||||
mrb_bint_copy(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
mpz_t a, b;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
bint_as_mpz(RBIGINT(y), &b);
|
||||
@@ -3064,15 +3023,13 @@ mrb_bint_sqrt(mrb_state *mrb, mrb_value x)
|
||||
if (a.sn < 0) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "square root of negative number");
|
||||
}
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_t z;
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_sqrt(&ctx, &z, &a);
|
||||
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_int
|
||||
@@ -3094,9 +3051,7 @@ mrb_bint_from_bytes(mrb_state *mrb, const uint8_t *bytes, mrb_int len)
|
||||
{
|
||||
mpz_t z;
|
||||
size_t limb_len = (len + sizeof(mp_limb) - 1) / sizeof(mp_limb);
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &z);
|
||||
mpz_realloc(&ctx, &z, limb_len);
|
||||
@@ -3104,7 +3059,7 @@ mrb_bint_from_bytes(mrb_state *mrb, const uint8_t *bytes, mrb_int len)
|
||||
z.sn = (len > 0) ? 1 : 0;
|
||||
z.sz = limb_len;
|
||||
trim(&z);
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
return bint_norm(mrb, bint_new(&ctx, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
@@ -3123,9 +3078,7 @@ mrb_value
|
||||
mrb_bint_2comp(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mpz_t a, z;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
mpz_init(&ctx, &z);
|
||||
@@ -3142,7 +3095,7 @@ mrb_bint_2comp(mrb_state *mrb, mrb_value x)
|
||||
}
|
||||
z.sn = 1;
|
||||
|
||||
struct RBigint *b2 = bint_new(mrb, &z);
|
||||
struct RBigint *b2 = bint_new(&ctx, &z);
|
||||
return mrb_obj_value(b2);
|
||||
}
|
||||
|
||||
@@ -3151,9 +3104,7 @@ void
|
||||
mrb_bint_reduce(mrb_state *mrb, mrb_value *xp, mrb_value *yp)
|
||||
{
|
||||
mpz_t r, x, y, a, b;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &r);
|
||||
mpz_init(&ctx, &a); mpz_init(&ctx, &b);
|
||||
@@ -3168,8 +3119,8 @@ mrb_bint_reduce(mrb_state *mrb, mrb_value *xp, mrb_value *yp)
|
||||
|
||||
mpz_clear(&ctx, &r);
|
||||
|
||||
struct RBigint *b1 = bint_new(mrb, &a);
|
||||
struct RBigint *b2 = bint_new(mrb, &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);
|
||||
}
|
||||
@@ -3179,9 +3130,7 @@ mrb_value
|
||||
mrb_bint_gcd(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
mpz_t r, a, b;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &r);
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
@@ -3189,7 +3138,7 @@ mrb_bint_gcd(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
|
||||
mpz_gcd(&ctx, &r, &a, &b);
|
||||
|
||||
struct RBigint *result = bint_new(mrb, &r);
|
||||
struct RBigint *result = bint_new(&ctx, &r);
|
||||
return bint_norm(mrb, result);
|
||||
}
|
||||
|
||||
@@ -3203,9 +3152,7 @@ mrb_bint_lcm(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
return zero;
|
||||
}
|
||||
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
/* Get input operand sizes for size estimation */
|
||||
size_t x_size = RBIGINT_EMBED_P(RBIGINT(x)) ? RBIGINT_EMBED_SIZE(RBIGINT(x)) : RBIGINT(x)->as.heap.sz;
|
||||
size_t y_size = RBIGINT_EMBED_P(RBIGINT(y)) ? RBIGINT_EMBED_SIZE(RBIGINT(y)) : RBIGINT(y)->as.heap.sz;
|
||||
@@ -3232,8 +3179,7 @@ mrb_bint_lcm(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
mpz_clear(&ctx, &abs_y);
|
||||
mpz_clear(&ctx, &product);
|
||||
|
||||
struct RBigint *result = bint_new(mrb, &result_mpz);
|
||||
mpz_clear(&ctx, &result_mpz);
|
||||
struct RBigint *result = bint_new(&ctx, &result_mpz);
|
||||
return mrb_obj_value(result);
|
||||
}
|
||||
|
||||
@@ -3241,15 +3187,12 @@ mrb_value
|
||||
mrb_bint_abs(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mpz_t a, result_mpz;
|
||||
mpz_pool_t pool_storage = {.capacity = BIGINT_POOL_DEFAULT_SIZE, .used = 0};
|
||||
mpz_pool_t *pool = &pool_storage;
|
||||
mpz_ctx_t ctx = MPZ_CTX_POOL(mrb, pool);
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
|
||||
mpz_init(&ctx, &result_mpz);
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
mpz_abs(&ctx, &result_mpz, &a);
|
||||
|
||||
struct RBigint *result = bint_new(mrb, &result_mpz);
|
||||
mpz_clear(&ctx, &result_mpz);
|
||||
struct RBigint *result = bint_new(&ctx, &result_mpz);
|
||||
return mrb_obj_value(result);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user