From 01233f70bd79e50161b4a07975e47bee09fb7ac9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Mar 2023 10:48:52 +0900 Subject: [PATCH] mruby-bigint/bigint.c: add two new functions to convert to 64bit int - mrb_bint_as_int64() - mrb_bint_as_uint64() --- include/mruby/internal.h | 6 +++++ mrbgems/mruby-bigint/core/bigint.c | 40 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/mruby/internal.h b/include/mruby/internal.h index ccfd30769..5a6c58f55 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -206,6 +206,12 @@ mrb_value mrb_bint_new_float(mrb_state *mrb, mrb_float x); mrb_float mrb_bint_as_float(mrb_state *mrb, mrb_value x); #endif mrb_int mrb_bint_as_int(mrb_state *mrb, mrb_value x); +#ifdef MRB_INT64 +#define mrb_bint_as_int64(mrb, x) mrb_bint_as_int((mrb), (x)) +#else +int64_t mrb_bint_as_int64(mrb_state *mrb, mrb_value x); +#endif +uint64_t mrb_bint_as_uint64(mrb_state *mrb, mrb_value x); mrb_int mrb_bint_cmp(mrb_state *mrb, mrb_value x, mrb_value y); void mrb_gc_free_bint(mrb_state *mrb, struct RBasic *x); void mrb_bint_copy(mrb_state *mrb, mrb_value x, mrb_value y); diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index cca54d31f..4b548cd7f 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -1139,6 +1139,46 @@ mrb_bint_as_int(mrb_state *mrb, mrb_value x) return i; } +#ifdef MRB_INT32 +int64_t +mrb_bint_as_int64(mrb_state *mrb, mrb_value x) +{ + struct RBigint *b = RBIGINT(x); + mpz_t *m = &b->mp; + uint64_t u = 0; + size_t len = digits(m); + + if (len*sizeof(mp_limb) > sizeof(uint64_t)) { + out_of_range: + mrb_raise(mrb, E_RANGE_ERROR, "integer out of range"); + } + for (size_t i=0; ip[i]; + } + if (u > INT64_MAX) goto out_of_range; + return -(int64_t)u; +} +#endif + +uint64_t +mrb_bint_as_uint64(mrb_state *mrb, mrb_value x) +{ + struct RBigint *b = RBIGINT(x); + mpz_t *m = &b->mp; + uint64_t u = 0; + size_t len = digits(m); + + if (m->sn < 0 || len*sizeof(mp_limb) > sizeof(uint64_t)) { + mrb_raise(mrb, E_RANGE_ERROR, "integer out of range"); + } + for (size_t i=0; ip[i]; + } + return u; +} + mrb_value mrb_bint_add(mrb_state *mrb, mrb_value x, mrb_value y) {