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.
|
||||
|
||||
Reference in New Issue
Block a user