mruby-bigint/bigint.c: add two new functions to convert to 64bit int

- mrb_bint_as_int64()
- mrb_bint_as_uint64()
This commit is contained in:
Yukihiro "Matz" Matsumoto
2023-03-08 10:48:52 +09:00
parent c71408bc0a
commit 01233f70bd
2 changed files with 46 additions and 0 deletions
+6
View File
@@ -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);
+40
View File
@@ -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; i<len; i++) {
u <<= DIG_SIZE;
u |= m->p[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; i<len; i++) {
u <<= DIG_SIZE;
u |= m->p[i];
}
return u;
}
mrb_value
mrb_bint_add(mrb_state *mrb, mrb_value x, mrb_value y)
{