mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
src/bigint.c: implement multi-precision integer.
To enable multi-precision integer support, you need to link `mruby-bigint` mrbgem. The gem itself is empty but it turns on the "bigint" support.
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
** @file mruby/bigint.h - Multi-precision, Integer
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
#ifdef MRB_USE_BIGINT
|
||||
|
||||
#ifndef MRUBY_BIGINT_H
|
||||
#define MRUBY_BIGINT_H
|
||||
/*
|
||||
* FREE GMP - a public domain implementation of a subset of the
|
||||
* gmp library
|
||||
*
|
||||
* I hearby place the file in the public domain.
|
||||
*
|
||||
* Do whatever you want with this code. Change it. Sell it. Claim you
|
||||
* wrote it.
|
||||
* Bugs, complaints, flames, rants: please send email to
|
||||
* Mark Henderson <markh@wimsey.bc.ca>
|
||||
* I'm already aware that fgmp is considerably slower than gmp
|
||||
*
|
||||
* CREDITS:
|
||||
* Paul Rouse <par@r-cube.demon.co.uk> - generic bug fixes, mpz_sqrt and
|
||||
* mpz_sqrtrem, and modifications to get fgmp to compile on a system
|
||||
* with int and long of different sizes (specifically MS-DOS,286 compiler)
|
||||
* Also see the file "notes" included with the fgmp distribution, for
|
||||
* more credits.
|
||||
*
|
||||
* VERSION 1.0 - beta 5
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef MRB_32BIT
|
||||
/*
|
||||
* The values below are for 32 bit machines (i.e. machines with a
|
||||
* 32 bit long type)
|
||||
* You'll need to change them, if you're using something else
|
||||
* If DIGITBITS is odd, see the comment at the top of mpz_sqrtrem
|
||||
*/
|
||||
typedef int32_t mp_limb;
|
||||
#define LMAX 0x3fffffffL
|
||||
#define LC 0xc0000000L
|
||||
#define OVMASK 0x2
|
||||
#define CMASK (LMAX+1)
|
||||
#define HLMAX 0x7fffL
|
||||
#define HCMASK (HLMAX + 1)
|
||||
#define HIGH(x) (((x) & 0x3fff8000L) >> 15)
|
||||
#define LOW(x) ((x) & 0x7fffL)
|
||||
|
||||
#else
|
||||
/* 64 bit long type */
|
||||
typedef int64_t mp_limb;
|
||||
#define LMAX 0x3fffffffffffffffL
|
||||
#define LC 0xc000000000000000L
|
||||
#define OVMASK 0x2
|
||||
#define CMASK (LMAX+1)
|
||||
#define HLMAX 0x7fffffffL
|
||||
#define HCMASK (HLMAX + 1)
|
||||
#define HIGH(x) (((x) & 0x3fffffff80000000L) >> 31)
|
||||
#define LOW(x) ((x) & 0x7fffffffL)
|
||||
#endif
|
||||
|
||||
typedef struct _mpz_t {
|
||||
mp_limb *p;
|
||||
short sn;
|
||||
size_t sz;
|
||||
} mpz_t;
|
||||
|
||||
struct RBigint {
|
||||
MRB_OBJECT_HEADER;
|
||||
mpz_t mp;
|
||||
};
|
||||
#define RBIGINT(v) ((struct RBigint*)mrb_ptr(v))
|
||||
|
||||
#define iabs(x) ((x>0) ? (x) : (-x))
|
||||
#define imax(x,y) ((x>y)?x:y)
|
||||
#define LONGBITS (sizeof(mp_limb)*8)
|
||||
#define DIGITBITS (LONGBITS-2)
|
||||
#define HALFDIGITBITS ((LONGBITS-2)/2)
|
||||
|
||||
#define hd(x,i) (((size_t)(i)>=2*((x)->sz))? 0:(((i)%2) ? HIGH((x)->p[(i)/2]) \
|
||||
: LOW((x)->p[(i)/2])))
|
||||
#define dg(x,i) (((size_t)(i) < (x)->sz) ? ((x)->p)[i] : 0)
|
||||
|
||||
#define RBIGINT(v) ((struct RBigint*)mrb_ptr(v))
|
||||
|
||||
mrb_value mrb_bint_new_int(mrb_state *mrb, mrb_int x);
|
||||
mrb_value mrb_bint_add(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_sub(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_mul(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_div(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_divmod(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_add_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_sub_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_mul_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_div_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_mod(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_rem(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_pow(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_powm(mrb_state *mrb, mrb_value x, mrb_int y, mrb_value z);
|
||||
mrb_value mrb_bint_and(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_or(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_xor(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_rev(mrb_state *mrb, mrb_value x);
|
||||
mrb_value mrb_bint_lshift(mrb_state *mrb, mrb_value x, mrb_int width);
|
||||
mrb_value mrb_bint_rshift(mrb_state *mrb, mrb_value x, mrb_int width);
|
||||
mrb_value mrb_bint_to_s(mrb_state *mrb, mrb_value x, mrb_int base);
|
||||
#ifndef MRB_NO_FLOAT
|
||||
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);
|
||||
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);
|
||||
#endif
|
||||
|
||||
#endif /* MRB_USE_BIGINT */
|
||||
@@ -83,6 +83,8 @@ mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_int_add(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_int_sub(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_int_mul(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
void mrb_int_zerodiv(mrb_state *mrb);
|
||||
void mrb_int_overflow(mrb_state *mrb, const char *reason);
|
||||
|
||||
#ifdef MRB_USE_COMPLEX
|
||||
mrb_value mrb_complex_new(mrb_state *mrb, mrb_float x, mrb_float y);
|
||||
@@ -154,4 +156,36 @@ void mrb_gc_free_iv(mrb_state*, struct RObject*);
|
||||
/* VM */
|
||||
mrb_int mrb_ci_bidx(mrb_callinfo *ci);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
mrb_value mrb_bint_new_int(mrb_state *mrb, mrb_int x);
|
||||
mrb_value mrb_bint_new_str(mrb_state *mrb, const char *x, mrb_int len, mrb_int base);
|
||||
mrb_value mrb_as_bint(mrb_state *mrb, mrb_value x);
|
||||
mrb_value mrb_bint_add(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_sub(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_mul(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_div(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_divmod(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_add_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_sub_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_mul_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_div_ii(mrb_state *mrb, mrb_int x, mrb_int y);
|
||||
mrb_value mrb_bint_mod(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_rem(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_pow(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_powm(mrb_state *mrb, mrb_value x, mrb_int y, mrb_value z);
|
||||
mrb_value mrb_bint_and(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_or(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_xor(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_bint_rev(mrb_state *mrb, mrb_value x);
|
||||
mrb_value mrb_bint_lshift(mrb_state *mrb, mrb_value x, mrb_int width);
|
||||
mrb_value mrb_bint_rshift(mrb_state *mrb, mrb_value x, mrb_int width);
|
||||
mrb_value mrb_bint_to_s(mrb_state *mrb, mrb_value x, mrb_int base);
|
||||
#ifndef MRB_NO_FLOAT
|
||||
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);
|
||||
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);
|
||||
#endif
|
||||
|
||||
#endif /* MRUBY_INTERNAL_H */
|
||||
|
||||
@@ -154,7 +154,8 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
|
||||
f(MRB_TT_ISTRUCT, struct RIStruct, "istruct") \
|
||||
f(MRB_TT_BREAK, struct RBreak, "break") \
|
||||
f(MRB_TT_COMPLEX, struct RComplex, "Complex") \
|
||||
f(MRB_TT_RATIONAL, struct RRational, "Rational")
|
||||
f(MRB_TT_RATIONAL, struct RRational, "Rational") \
|
||||
f(MRB_TT_BIGINT, struct RBigint, "Integer")
|
||||
|
||||
enum mrb_vtype {
|
||||
#define MRB_VTYPE_DEFINE(tt, type, name) tt,
|
||||
@@ -300,6 +301,9 @@ struct RCptr {
|
||||
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
|
||||
#endif
|
||||
#define mrb_test(o) mrb_bool(o)
|
||||
#ifndef mrb_bigint_p
|
||||
#define mrb_bigint_p(o) (mrb_type(o) == MRB_TT_BIGINT)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns a float in Ruby.
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
# fgmp
|
||||
|
||||
FGMP is a public domain implementation of a subset of the GNU gmp library with the same API.
|
||||
|
||||
WELCOME TO FGMP.
|
||||
|
||||
FGMP is a public domain implementation of a subset of the GNU gmp library
|
||||
with the same API.
|
||||
|
||||
For instance, you can link the following trivial program with either
|
||||
this code, or libgmp.a and get the same results.
|
||||
|
||||
``` C
|
||||
#include <stdio.h>
|
||||
#include "gmp.h"
|
||||
main()
|
||||
{
|
||||
MP_INT a; MP_INT b; MP_INT c;
|
||||
|
||||
mpz_init_set_ui(&a,1); mpz_init_set_ui(&b,2); mpz_init(&c);
|
||||
mpz_add(&c,&a,&b);
|
||||
printf("\n%s\n", mpz_get_str(NULL,10,&c));
|
||||
}
|
||||
```
|
||||
|
||||
FGMP is really in the public domain. You can do whatever you want with
|
||||
it.
|
||||
|
||||
I wrote FGMP so that we would all have access to a (truly free)
|
||||
implementation of this subset of the API of GNU libgmp. I encourage
|
||||
everyone to distribute this as widely as possible.
|
||||
|
||||
If you need more documentation, I suggest you look at the file
|
||||
gmp.texi which is included with the GNU gmp library.
|
||||
|
||||
You can send me bug reports, implementations of missing functions, flames
|
||||
and rants by Email.
|
||||
|
||||
Any submissions of new code to be integrated into fgmp must also be
|
||||
placed in the public domain (For the particularly dense, you can
|
||||
release a new fgmp yourself under different licensing terms. This
|
||||
is a condition for including a submission in a release of FGMP that
|
||||
I personally prepare).
|
||||
|
||||
Mark Henderson <markh@wimsey.bc.ca>
|
||||
|
||||
# This is the fifth BETA release. 1.0b5
|
||||
|
||||
I hearby place this file and all of FGMP in the public domain.
|
||||
|
||||
Thanks to Paul Rouse <par@r-cube.demon.co.uk> for changes to get fgmp
|
||||
to work on a 286 MS-DOS compiler, the functions mpz_sqrt and
|
||||
mpz_sqrtrem, plus other general bug fixes.
|
||||
|
||||
Thanks also to Erick Gallesio <eg@kaolin.unice.fr> for a fix
|
||||
to mpz_init_set_str
|
||||
|
||||
Define B64 if your "long" type is 64 bits. Otherwise we assume 32
|
||||
bit longs. (The 64 bit version hasn't been tested enough)
|
||||
|
||||
```
|
||||
Platforms:
|
||||
Linux 0.99 (gcc)
|
||||
IBM RS6000/AIX 3.2 (IBM xlc compiler and gcc 2.3)
|
||||
Sun OS 4.1, Sun 3/4
|
||||
DEC Alpha OSF/1 (only lightly tested, 64 bit longs do make a difference,
|
||||
thanks to DEC for providing access via axposf.pa.dec.com). Define B64
|
||||
for this platform
|
||||
MS-DOS 286 C compiler (see credits above)
|
||||
```
|
||||
|
||||
# Some differences between gmp and fgmp
|
||||
|
||||
1. fgmp is considerably slower than gmp
|
||||
2. fgmp does not implement the following:
|
||||
all mpq_*
|
||||
internal mpn_* functions
|
||||
mpz_perfect_square_p
|
||||
mpz_inp_raw, mpz_out_raw
|
||||
mp_set_memory_functions, mpz_out_str, mpz_inp_str
|
||||
3. fgmp implements the following in addition to the routines in GNU gmp.
|
||||
`int mpz_jacobi(MP_INT *a, MP_INT *b)`
|
||||
- finds the jacobi symbol (a/b)
|
||||
4. mpz_sizeinbase often overestimates the exact value
|
||||
|
||||
5. To convert your gmp based program to fgmp (subject to the
|
||||
above)
|
||||
|
||||
- recompile your source. Make sure to include the gmp.h file included
|
||||
with fgmp rather than that included with gmp. (The point is to recompile
|
||||
all files which include gmp.h)
|
||||
- link with gmp.o instead of libgmp.a
|
||||
|
||||
Here's a complete sorted list of function implemented in fgmp:
|
||||
|
||||
```
|
||||
_mpz_realloc
|
||||
mpz_abs
|
||||
mpz_add
|
||||
mpz_add_ui
|
||||
mpz_and
|
||||
mpz_clear
|
||||
mpz_cmp
|
||||
mpz_cmp_si
|
||||
mpz_cmp_ui
|
||||
mpz_div
|
||||
mpz_div_2exp
|
||||
mpz_div_ui
|
||||
mpz_divmod
|
||||
mpz_divmod_ui
|
||||
mpz_fac_ui
|
||||
mpz_gcd
|
||||
mpz_gcdext
|
||||
mpz_get_si
|
||||
mpz_get_str
|
||||
mpz_get_ui
|
||||
mpz_init
|
||||
mpz_init_set
|
||||
mpz_init_set_si
|
||||
mpz_init_set_str
|
||||
mpz_init_set_ui
|
||||
mpz_jacobi
|
||||
mpz_mdiv
|
||||
mpz_mdiv_ui
|
||||
mpz_mdivmod
|
||||
mpz_mdivmod_ui
|
||||
mpz_mmod
|
||||
mpz_mmod_ui
|
||||
mpz_mod
|
||||
mpz_mod_2exp
|
||||
mpz_mod_ui
|
||||
mpz_mul
|
||||
mpz_mul_2exp
|
||||
mpz_mul_ui
|
||||
mpz_neg
|
||||
mpz_or
|
||||
mpz_pow_ui
|
||||
mpz_powm
|
||||
mpz_powm_ui
|
||||
mpz_probab_prime_p
|
||||
mpz_random
|
||||
mpz_random2
|
||||
mpz_set
|
||||
mpz_set_si
|
||||
mpz_set_str
|
||||
mpz_set_ui
|
||||
mpz_size
|
||||
mpz_sizeinbase
|
||||
mpz_sqrt
|
||||
mpz_sqrtrem
|
||||
mpz_sub
|
||||
mpz_sub_ui
|
||||
mpz_xor
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
# Multi-precision Integer extension for mruby
|
||||
|
||||
This extension uses fgmp, which is a public domain implementation of a subset of the GNU gmp library by Mark Henderson <markh@wimsey.bc.ca>
|
||||
But it's heavily modified to fit with mruby. You can get the original source code from <https://github.com/deischi/fgmp.git>
|
||||
You can read the original README for fgmp in <README-fgmp.md>
|
||||
|
||||
## Implementation
|
||||
|
||||
This mrbgem is only to turn on `MRB_USE_BIGINT` flag. The implementation resides in `include/mruby/bigint.h` and `src/bigint.c`.
|
||||
@@ -0,0 +1,6 @@
|
||||
MRuby::Gem::Specification.new('mruby-bigint') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Integer class extension to multiple-precision'
|
||||
spec.build.defines << "MRB_USE_BIGINT"
|
||||
end
|
||||
@@ -1,9 +1,40 @@
|
||||
#include <mruby.h>
|
||||
#include <mruby/numeric.h>
|
||||
#include <mruby/internal.h>
|
||||
#include <mruby/presym.h>
|
||||
|
||||
void mrb_int_zerodiv(mrb_state *mrb);
|
||||
void mrb_int_overflow(mrb_state *mrb, const char *reason);
|
||||
#ifdef MRB_USE_BIGINT
|
||||
#include <mruby/bigint.h>
|
||||
|
||||
static mrb_value
|
||||
bint_allbits(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
y = mrb_as_bint(mrb, y);
|
||||
x = mrb_bint_and(mrb, x, y);
|
||||
if (mrb_bint_cmp(mrb, x, y) == 0) return mrb_true_value();
|
||||
return mrb_false_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
bint_anybits(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
y = mrb_as_bint(mrb, y);
|
||||
x = mrb_bint_and(mrb, x, y);
|
||||
if (mrb_bint_cmp(mrb, x, mrb_fixnum_value(0)) != 0)
|
||||
return mrb_true_value();
|
||||
return mrb_false_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
bint_nobits(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
y = mrb_as_bint(mrb, y);
|
||||
x = mrb_bint_and(mrb, x, y);
|
||||
if (mrb_bint_cmp(mrb, x, mrb_fixnum_value(0)) == 0)
|
||||
return mrb_true_value();
|
||||
return mrb_false_value();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
@@ -14,6 +45,9 @@ void mrb_int_overflow(mrb_state *mrb, const char *reason);
|
||||
static mrb_value
|
||||
int_allbits(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
return bint_allbits(mrb, self, mrb_get_arg1(mrb));
|
||||
#endif
|
||||
mrb_int n, m;
|
||||
|
||||
mrb_get_args(mrb, "i", &m);
|
||||
@@ -30,6 +64,9 @@ int_allbits(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
int_anybits(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
return bint_anybits(mrb, self, mrb_get_arg1(mrb));
|
||||
#endif
|
||||
mrb_int n, m;
|
||||
|
||||
mrb_get_args(mrb, "i", &m);
|
||||
@@ -46,6 +83,9 @@ int_anybits(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
int_nobits(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
return bint_nobits(mrb, self, mrb_get_arg1(mrb));
|
||||
#endif
|
||||
mrb_int n, m;
|
||||
|
||||
mrb_get_args(mrb, "i", &m);
|
||||
@@ -53,6 +93,10 @@ int_nobits(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value((n & m) == 0);
|
||||
}
|
||||
|
||||
#ifndef MRB_NO_FLOAT
|
||||
static mrb_value flo_remainder(mrb_state *mrb, mrb_value self);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* num.remainder(numeric) -> real
|
||||
@@ -67,6 +111,14 @@ int_remainder(mrb_state *mrb, mrb_value x)
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
mrb_int a, b;
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
if (mrb_integer_p(y) || mrb_bigint_p(y)) {
|
||||
return mrb_bint_rem(mrb, x, y);
|
||||
}
|
||||
return flo_remainder(mrb, mrb_float_value(mrb, mrb_as_float(mrb, x)));
|
||||
}
|
||||
#endif
|
||||
a = mrb_integer(x);
|
||||
if (mrb_integer_p(y)) {
|
||||
b = mrb_integer(y);
|
||||
@@ -77,11 +129,7 @@ int_remainder(mrb_state *mrb, mrb_value x)
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non integer remainder");
|
||||
#else
|
||||
mrb_float n = (mrb_float)a;
|
||||
mrb_float m = mrb_as_float(mrb, y);
|
||||
|
||||
if (isinf(m)) return mrb_float_value(mrb, n);
|
||||
return mrb_float_value(mrb, n-m*trunc(n/m));
|
||||
return flo_remainder(mrb, mrb_float_value(mrb, mrb_as_float(mrb, x)));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -100,14 +148,25 @@ mrb_value mrb_int_pow(mrb_state *mrb, mrb_value x);
|
||||
static mrb_value
|
||||
int_powm(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value m;
|
||||
mrb_int base, exp, mod, result = 1;
|
||||
|
||||
if (mrb_get_argc(mrb) == 1) {
|
||||
return mrb_int_pow(mrb, x);
|
||||
}
|
||||
mrb_get_args(mrb, "ii", &exp, &mod);
|
||||
if (exp < 0) mrb_raise(mrb, E_TYPE_ERROR, "int.pow(n,m): n must be positive");
|
||||
if (mod < 0) mrb_raise(mrb, E_TYPE_ERROR, "int.pow(n,m): m must be positive");
|
||||
mrb_get_args(mrb, "io", &exp, &m);
|
||||
if (exp < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "int.pow(n,m): n must be positive");
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_powm(mrb, x, exp, m);
|
||||
}
|
||||
if (mrb_bigint_p(m)) {
|
||||
return mrb_bint_powm(mrb, mrb_bint_new_int(mrb, mrb_integer(x)), exp, m);
|
||||
}
|
||||
#endif
|
||||
if (!mrb_integer_p(m)) mrb_raise(mrb, E_TYPE_ERROR, "int.pow(n,m): m must be integer");
|
||||
mod = mrb_integer(m);
|
||||
if (mod < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "int.pow(n,m): m must be positive");
|
||||
if (mod == 0) mrb_int_zerodiv(mrb);
|
||||
if (mod == 1) return mrb_fixnum_value(0);
|
||||
base = mrb_integer(x);
|
||||
|
||||
@@ -128,23 +128,24 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj)
|
||||
case MRB_TT_INTEGER:
|
||||
if (mrb_immediate_p(obj))
|
||||
break;
|
||||
case MRB_TT_RATIONAL:
|
||||
case MRB_TT_RATIONAL:
|
||||
#if defined(MRB_USE_RATIONAL)
|
||||
#if defined(MRB_INT64) && defined(MRB_32BIT)
|
||||
size += sizeof(mrb_int)*2;
|
||||
size += sizeof(mrb_int)*2;
|
||||
#endif
|
||||
size += mrb_objspace_page_slot_size();
|
||||
size += mrb_objspace_page_slot_size();
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
|
||||
case MRB_TT_COMPLEX:
|
||||
case MRB_TT_COMPLEX:
|
||||
#if defined(MRB_USE_COMPLEX)
|
||||
#if defined(MRB_32BIT) && !defined(MRB_USE_FLOAT32)
|
||||
size += sizeof(mrb_float)*2;
|
||||
size += sizeof(mrb_float)*2;
|
||||
#endif
|
||||
size += mrb_objspace_page_slot_size();
|
||||
size += mrb_objspace_page_slot_size();
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
case MRB_TT_BIGINT:
|
||||
case MRB_TT_DATA:
|
||||
case MRB_TT_ISTRUCT:
|
||||
size += mrb_objspace_page_slot_size();
|
||||
|
||||
+1
-1
@@ -847,7 +847,7 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
|
||||
return mrb_ary_new_from_values(mrb, len, ARY_PTR(a)+beg);
|
||||
}
|
||||
ary_make_shared(mrb, a);
|
||||
b = MRB_OBJ_ALLOC(mrb, MRB_TT_ARRAY, mrb->array_class);
|
||||
b = MRB_OBJ_ALLOC(mrb, MRB_TT_ARRAY, mrb->array_class);
|
||||
b->as.heap.ptr = a->as.heap.ptr + beg;
|
||||
b->as.heap.len = len;
|
||||
b->as.heap.aux.shared = a->as.heap.aux.shared;
|
||||
|
||||
+1410
File diff suppressed because it is too large
Load Diff
@@ -555,6 +555,7 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
|
||||
ttype != MRB_TT_SCLASS &&
|
||||
ttype != MRB_TT_ICLASS &&
|
||||
ttype != MRB_TT_ENV &&
|
||||
ttype != MRB_TT_BIGINT &&
|
||||
ttype != tt) {
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %C", cls);
|
||||
}
|
||||
@@ -909,6 +910,12 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
case MRB_TT_BIGINT:
|
||||
mrb_gc_free_bint(mrb, obj);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, const uint8_t *end, size_
|
||||
pool_data_len = bin_to_uint8(src); /* pool data length */
|
||||
src += sizeof(uint8_t);
|
||||
if (src + pool_data_len > end) return FALSE;
|
||||
{
|
||||
{
|
||||
char *p;
|
||||
pool[i].tt = IREP_TT_BIGINT;
|
||||
p = (char*)mrb_malloc(mrb, pool_data_len+2);
|
||||
|
||||
+171
-8
@@ -45,6 +45,18 @@ mrb_int_zerodiv(mrb_state *mrb)
|
||||
mrb_value
|
||||
mrb_int_pow(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
#ifndef MRB_NO_FLOAT
|
||||
if (mrb_float_p(y)) {
|
||||
return mrb_float_value(mrb, pow(mrb_bint_as_float(mrb, x), mrb_float(y)));
|
||||
}
|
||||
#endif
|
||||
return mrb_bint_pow(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
mrb_int base = mrb_integer(x);
|
||||
mrb_int result = 1;
|
||||
mrb_int exp;
|
||||
@@ -79,7 +91,11 @@ mrb_int_pow(mrb_state *mrb, mrb_value x)
|
||||
exp >>= 1;
|
||||
if (exp == 0) break;
|
||||
if (mrb_int_mul_overflow(base, base, &base)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
return mrb_bint_pow(mrb, mrb_bint_new_int(mrb, mrb_integer(x)), y);
|
||||
#else
|
||||
mrb_int_overflow(mrb, "power");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return mrb_int_value(mrb, result);
|
||||
@@ -121,13 +137,28 @@ static mrb_value
|
||||
int_div(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_div(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
mrb_int a = mrb_integer(x);
|
||||
|
||||
if (mrb_integer_p(y)) {
|
||||
mrb_int div = mrb_div_int(mrb, a, mrb_integer(y));
|
||||
mrb_int b = mrb_integer(y);
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if(a == MRB_INT_MIN && b == -1) {
|
||||
return mrb_bint_mul_ii(mrb, a, b);
|
||||
}
|
||||
#endif
|
||||
mrb_int div = mrb_div_int(mrb, a, b);
|
||||
return mrb_int_value(mrb, div);
|
||||
}
|
||||
switch (mrb_type(y)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
case MRB_TT_BIGINT:
|
||||
return mrb_bint_div(mrb, mrb_bint_new_int(mrb, a), y);
|
||||
#endif
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
return mrb_rational_div(mrb, mrb_rational_new(mrb, a, 1), y);
|
||||
@@ -163,6 +194,11 @@ int_div(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
int_idiv(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_div(mrb, x, mrb_get_arg1(mrb));
|
||||
}
|
||||
#endif
|
||||
mrb_int y;
|
||||
|
||||
mrb_get_args(mrb, "i", &y);
|
||||
@@ -182,6 +218,11 @@ int_quo(mrb_state *mrb, mrb_value x)
|
||||
if (y == 0) {
|
||||
mrb_int_zerodiv(mrb);
|
||||
}
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_float_value(mrb, mrb_bint_as_float(mrb, x) / y);
|
||||
}
|
||||
#endif
|
||||
return mrb_float_value(mrb, mrb_integer(x) / y);
|
||||
#endif
|
||||
#else
|
||||
@@ -502,6 +543,11 @@ int_eql(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bool_value(mrb_bint_cmp(mrb, x, y) == 0);
|
||||
}
|
||||
#endif
|
||||
if (!mrb_integer_p(y)) return mrb_false_value();
|
||||
return mrb_bool_value(mrb_integer(x) == mrb_integer(y));
|
||||
}
|
||||
@@ -1038,16 +1084,25 @@ mrb_int_mul(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (a == 0) return x;
|
||||
b = mrb_integer(y);
|
||||
if (mrb_int_mul_overflow(a, b, &c)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
x = mrb_bint_new_int(mrb, a);
|
||||
return mrb_bint_mul(mrb, x, y);
|
||||
#else
|
||||
mrb_int_overflow(mrb, "multiplication");
|
||||
#endif
|
||||
}
|
||||
return mrb_int_value(mrb, c);
|
||||
}
|
||||
switch (mrb_type(y)) {
|
||||
#if defined(MRB_USE_RATIONAL)
|
||||
#ifdef MRB_USE_BIGINT
|
||||
case MRB_TT_BIGINT:
|
||||
return mrb_bint_mul(mrb, y, x);
|
||||
#endif
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
return mrb_rational_mul(mrb, y, x);
|
||||
#endif
|
||||
#if defined(MRB_USE_COMPLEX)
|
||||
#ifdef MRB_USE_COMPLEX
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_complex_mul(mrb, y, x);
|
||||
#endif
|
||||
@@ -1075,6 +1130,11 @@ int_mul(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_mul(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
return mrb_int_mul(mrb, x, y);
|
||||
}
|
||||
|
||||
@@ -1115,6 +1175,11 @@ int_mod(mrb_state *mrb, mrb_value x)
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
mrb_int a, b;
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_mod(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
a = mrb_integer(x);
|
||||
if (mrb_integer_p(y)) {
|
||||
b = mrb_integer(y);
|
||||
@@ -1151,6 +1216,17 @@ int_divmod(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
#ifndef MRB_NO_FLOAT
|
||||
if (mrb_float_p(y)) {
|
||||
mrb_float f = mrb_bint_as_float(mrb, x);
|
||||
return flo_divmod(mrb, mrb_float_value(mrb, f));
|
||||
}
|
||||
#endif
|
||||
return mrb_bint_divmod(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
if (mrb_integer_p(y)) {
|
||||
mrb_int div, mod;
|
||||
|
||||
@@ -1206,6 +1282,10 @@ int_equal(mrb_state *mrb, mrb_value x)
|
||||
case MRB_TT_FLOAT:
|
||||
return mrb_bool_value((mrb_float)mrb_integer(x) == mrb_float(y));
|
||||
#endif
|
||||
#ifdef MRB_USE_BIGINT
|
||||
case MRB_TT_BIGINT:
|
||||
return mrb_bool_value(mrb_bint_cmp(mrb, y, x) == 0);
|
||||
#endif
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
return mrb_bool_value(mrb_equal(mrb, y, x));
|
||||
@@ -1235,6 +1315,11 @@ int_rev(mrb_state *mrb, mrb_value num)
|
||||
{
|
||||
mrb_int val = mrb_integer(num);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(num)) {
|
||||
mrb_bint_rev(mrb, num);
|
||||
}
|
||||
#endif
|
||||
return mrb_int_value(mrb, ~val);
|
||||
}
|
||||
|
||||
@@ -1265,6 +1350,11 @@ int_and(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_and(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
bit_op(x, y, and, &);
|
||||
}
|
||||
|
||||
@@ -1281,6 +1371,11 @@ int_or(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_or(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
bit_op(x, y, or, |);
|
||||
}
|
||||
|
||||
@@ -1297,6 +1392,11 @@ int_xor(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_xor(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
bit_op(x, y, or, ^);
|
||||
}
|
||||
|
||||
@@ -1355,10 +1455,20 @@ int_lshift(mrb_state *mrb, mrb_value x)
|
||||
if (width == 0) {
|
||||
return x;
|
||||
}
|
||||
if (width == MRB_INT_MIN) mrb_int_overflow(mrb, "bit shift");
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_lshift(mrb, x, width);
|
||||
}
|
||||
#endif
|
||||
val = mrb_integer(x);
|
||||
if (val == 0) return x;
|
||||
if (!mrb_num_shift(mrb, val, width, &val)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
return mrb_bint_lshift(mrb, mrb_bint_new_int(mrb, val), width);
|
||||
#else
|
||||
mrb_int_overflow(mrb, "bit shift");
|
||||
#endif
|
||||
}
|
||||
return mrb_int_value(mrb, val);
|
||||
}
|
||||
@@ -1380,11 +1490,20 @@ int_rshift(mrb_state *mrb, mrb_value x)
|
||||
if (width == 0) {
|
||||
return x;
|
||||
}
|
||||
if (width == MRB_INT_MIN) mrb_int_overflow(mrb, "bit shift");
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_rshift(mrb, x, width);
|
||||
}
|
||||
#endif
|
||||
val = mrb_integer(x);
|
||||
if (val == 0) return x;
|
||||
if (width == MRB_INT_MIN) mrb_int_overflow(mrb, "bit shift");
|
||||
if (!mrb_num_shift(mrb, val, -width, &val)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
return mrb_bint_rshift(mrb, mrb_bint_new_int(mrb, val), width);
|
||||
#else
|
||||
mrb_int_overflow(mrb, "bit shift");
|
||||
#endif
|
||||
}
|
||||
return mrb_int_value(mrb, val);
|
||||
}
|
||||
@@ -1402,6 +1521,11 @@ int_rshift(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
int_to_f(mrb_state *mrb, mrb_value num)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(num)) {
|
||||
return mrb_float_value(mrb, mrb_bint_as_float(mrb, num));
|
||||
}
|
||||
#endif
|
||||
return mrb_float_value(mrb, (mrb_float)mrb_integer(num));
|
||||
}
|
||||
|
||||
@@ -1454,16 +1578,25 @@ mrb_int_add(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (a == 0) return y;
|
||||
b = mrb_integer(y);
|
||||
if (mrb_int_add_overflow(a, b, &c)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
x = mrb_bint_new_int(mrb, a);
|
||||
return mrb_bint_add(mrb, x, y);
|
||||
#else
|
||||
mrb_int_overflow(mrb, "addition");
|
||||
#endif
|
||||
}
|
||||
return mrb_int_value(mrb, c);
|
||||
}
|
||||
switch (mrb_type(y)) {
|
||||
#if defined(MRB_USE_RATIONAL)
|
||||
#ifdef MRB_USE_BIGINT
|
||||
case MRB_TT_BIGINT:
|
||||
return mrb_bint_add(mrb, y, x);
|
||||
#endif
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
return mrb_rational_add(mrb, y, x);
|
||||
#endif
|
||||
#if defined(MRB_USE_COMPLEX)
|
||||
#ifdef MRB_USE_COMPLEX
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_complex_add(mrb, y, x);
|
||||
#endif
|
||||
@@ -1490,6 +1623,11 @@ int_add(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(self)) {
|
||||
return mrb_bint_add(mrb, self, other);
|
||||
}
|
||||
#endif
|
||||
return mrb_int_add(mrb, self, other);
|
||||
}
|
||||
|
||||
@@ -1504,16 +1642,25 @@ mrb_int_sub(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
|
||||
b = mrb_integer(y);
|
||||
if (mrb_int_sub_overflow(a, b, &c)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
x = mrb_bint_new_int(mrb, a);
|
||||
return mrb_bint_sub(mrb, x, y);
|
||||
#else
|
||||
mrb_int_overflow(mrb, "subtraction");
|
||||
#endif
|
||||
}
|
||||
return mrb_int_value(mrb, c);
|
||||
}
|
||||
switch (mrb_type(y)) {
|
||||
#if defined(MRB_USE_RATIONAL)
|
||||
#ifdef MRB_USE_BIGINT
|
||||
case MRB_TT_BIGINT:
|
||||
return mrb_bint_sub(mrb, mrb_bint_new_int(mrb, a), y);
|
||||
#endif
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
return mrb_rational_sub(mrb, mrb_rational_new(mrb, a, 1), y);
|
||||
#endif
|
||||
#if defined(MRB_USE_COMPLEX)
|
||||
#ifdef MRB_USE_COMPLEX
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_complex_sub(mrb, mrb_complex_new(mrb, (mrb_float)a, 0), y);
|
||||
#endif
|
||||
@@ -1541,6 +1688,11 @@ int_sub(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(self)) {
|
||||
return mrb_bint_sub(mrb, self, other);
|
||||
}
|
||||
#endif
|
||||
return mrb_int_sub(mrb, self, other);
|
||||
}
|
||||
|
||||
@@ -1615,6 +1767,11 @@ int_to_s(mrb_state *mrb, mrb_value self)
|
||||
mrb_int base = 10;
|
||||
|
||||
mrb_get_args(mrb, "|i", &base);
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(self)) {
|
||||
return mrb_bint_to_s(mrb, self, base);
|
||||
}
|
||||
#endif
|
||||
return mrb_integer_to_str(mrb, self, base);
|
||||
}
|
||||
|
||||
@@ -1622,6 +1779,12 @@ int_to_s(mrb_state *mrb, mrb_value self)
|
||||
static mrb_int
|
||||
cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(v2)) {
|
||||
return mrb_bint_cmp(mrb, v1, v2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_int x, y;
|
||||
#else
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
MRB_API mrb_value
|
||||
mrb_num_add(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_add(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
if (mrb_integer_p(x)) {
|
||||
return mrb_int_add(mrb, x, y);
|
||||
}
|
||||
@@ -41,6 +46,11 @@ mrb_num_add(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
MRB_API mrb_value
|
||||
mrb_num_sub(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_sub(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
if (mrb_integer_p(x)) {
|
||||
return mrb_int_sub(mrb, x, y);
|
||||
}
|
||||
@@ -70,6 +80,11 @@ mrb_num_sub(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
MRB_API mrb_value
|
||||
mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
#ifdef MRB_USE_BIGINT
|
||||
if (mrb_bigint_p(x)) {
|
||||
return mrb_bint_mul(mrb, x, y);
|
||||
}
|
||||
#endif
|
||||
if (mrb_integer_p(x)) {
|
||||
return mrb_int_mul(mrb, x, y);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <mruby/numeric.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/internal.h>
|
||||
#include <mruby/presym.h>
|
||||
|
||||
MRB_API mrb_bool
|
||||
@@ -547,6 +548,11 @@ mrb_ensure_float_type(mrb_state *mrb, mrb_value val)
|
||||
return mrb_complex_to_f(mrb, val);
|
||||
#endif
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
case MRB_TT_BIGINT:
|
||||
return mrb_float_value(mrb, mrb_bint_as_float(mrb, val));
|
||||
#endif
|
||||
|
||||
default:
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "%Y cannot be converted to Float", val);
|
||||
/* not reached */
|
||||
|
||||
+30
-7
@@ -2150,11 +2150,24 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
|
||||
return result;
|
||||
}
|
||||
|
||||
static mrb_bool
|
||||
trailingbad(const char *str, const char *p, const char *pend)
|
||||
{
|
||||
if (p == str) return TRUE; /* no number */
|
||||
if (*(p - 1) == '_') return TRUE; /* trailing '_' */
|
||||
while (p<pend && ISSPACE(*p)) p++;
|
||||
if (p<pend) return TRUE; /* trailing garbage */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_str_len_to_integer(mrb_state *mrb, const char *str, size_t len, mrb_int base, int badcheck)
|
||||
{
|
||||
const char *p = str;
|
||||
const char *pend = str + len;
|
||||
#ifdef MRB_USE_BIGINT
|
||||
const char *p2 = NULL;
|
||||
#endif
|
||||
char sign = 1;
|
||||
int c;
|
||||
mrb_int n = 0;
|
||||
@@ -2265,6 +2278,9 @@ mrb_str_len_to_integer(mrb_state *mrb, const char *str, size_t len, mrb_int base
|
||||
if (badcheck) goto bad;
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
#ifdef MRB_USE_BIGINT
|
||||
p2 = p;
|
||||
#endif
|
||||
for ( ;p<pend;p++) {
|
||||
if (*p == '_') {
|
||||
p++;
|
||||
@@ -2292,18 +2308,25 @@ mrb_str_len_to_integer(mrb_state *mrb, const char *str, size_t len, mrb_int base
|
||||
break;
|
||||
}
|
||||
overflow:
|
||||
#ifdef MRB_USE_BIGINT
|
||||
;
|
||||
const char *p3 = p2;
|
||||
while (p3 < pend) {
|
||||
char c = TOLOWER(*p3);
|
||||
const char *p4 = strchr(mrb_digitmap, c);
|
||||
if (p4 == NULL && c != '_') break;
|
||||
if (p4 - mrb_digitmap >= base) break;
|
||||
p3++;
|
||||
}
|
||||
if (badcheck && trailingbad(str, p, pend)) goto bad;
|
||||
return mrb_bint_new_str(mrb, p2, (mrb_int)(p3-p2), sign ? base : -base);
|
||||
#endif
|
||||
mrb_raisef(mrb, E_RANGE_ERROR, "string (%l) too big for integer", str, pend-str);
|
||||
}
|
||||
n += c;
|
||||
}
|
||||
val = (mrb_int)n;
|
||||
if (badcheck) {
|
||||
if (p == str) goto bad; /* no number */
|
||||
if (*(p - 1) == '_') goto bad; /* trailing '_' */
|
||||
while (p<pend && ISSPACE(*p)) p++;
|
||||
if (p<pend) goto bad; /* trailing garbage */
|
||||
}
|
||||
|
||||
if (badcheck && trailingbad(str, p, pend)) goto bad;
|
||||
return mrb_int_value(mrb, sign ? val : -val);
|
||||
bad:
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%!l)", str, pend-str);
|
||||
|
||||
@@ -1267,7 +1267,15 @@ RETRY_TRY_BLOCK:
|
||||
goto L_INT_OVERFLOW;
|
||||
#endif
|
||||
case IREP_TT_BIGINT:
|
||||
#ifdef MRB_USE_BIGINT
|
||||
{
|
||||
const char *s = pool[b].u.str;
|
||||
regs[a] = mrb_bint_new_str(mrb, s+2, (mrb_int)s[0], (mrb_int)s[1]);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
goto L_INT_OVERFLOW;
|
||||
#endif
|
||||
#ifndef MRB_NO_FLOAT
|
||||
case IREP_TT_FLOAT:
|
||||
regs[a] = mrb_float_value(mrb, pool[b].u.f);
|
||||
@@ -2376,12 +2384,14 @@ RETRY_TRY_BLOCK:
|
||||
NEXT;
|
||||
}
|
||||
|
||||
#if !defined(MRB_USE_BIGINT) || (defined(MRB_INT32) && MRB_32BIT)
|
||||
L_INT_OVERFLOW:
|
||||
{
|
||||
mrb_value exc = mrb_exc_new_lit(mrb, E_RANGE_ERROR, "integer overflow");
|
||||
mrb_exc_set(mrb, exc);
|
||||
}
|
||||
goto L_RAISE;
|
||||
#endif
|
||||
|
||||
#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
|
||||
#define OP_MATH(op_name) \
|
||||
@@ -2401,8 +2411,9 @@ RETRY_TRY_BLOCK:
|
||||
case TYPES2(MRB_TT_INTEGER, MRB_TT_INTEGER): \
|
||||
{ \
|
||||
mrb_int x = mrb_integer(regs[a]), y = mrb_integer(regs[a+1]), z; \
|
||||
if (mrb_int_##op_name##_overflow(x, y, &z)) \
|
||||
OP_MATH_OVERFLOW_INT(); \
|
||||
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
||||
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
||||
} \
|
||||
else \
|
||||
SET_INT_VALUE(mrb,regs[a], z); \
|
||||
} \
|
||||
@@ -2418,7 +2429,11 @@ RETRY_TRY_BLOCK:
|
||||
} \
|
||||
break
|
||||
#endif
|
||||
#define OP_MATH_OVERFLOW_INT() goto L_INT_OVERFLOW
|
||||
#ifdef MRB_USE_BIGINT
|
||||
#define OP_MATH_OVERFLOW_INT(op,x,y) regs[a] = mrb_bint_##op##_ii(mrb,x,y)
|
||||
#else
|
||||
#define OP_MATH_OVERFLOW_INT(op,x,y) goto L_INT_OVERFLOW
|
||||
#endif
|
||||
#define OP_MATH_CASE_STRING_add() \
|
||||
case TYPES2(MRB_TT_STRING, MRB_TT_STRING): \
|
||||
regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); \
|
||||
@@ -2500,8 +2515,9 @@ RETRY_TRY_BLOCK:
|
||||
case MRB_TT_INTEGER: \
|
||||
{ \
|
||||
mrb_int x = mrb_integer(regs[a]), y = (mrb_int)b, z; \
|
||||
if (mrb_int_##op_name##_overflow(x, y, &z)) \
|
||||
OP_MATH_OVERFLOW_INT(); \
|
||||
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
||||
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
||||
} \
|
||||
else \
|
||||
SET_INT_VALUE(mrb,regs[a], z); \
|
||||
} \
|
||||
|
||||
Reference in New Issue
Block a user