summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c147
1 files changed, 78 insertions, 69 deletions
diff --git a/bignum.c b/bignum.c
index 84bda92821..a9bbe9b272 100644
--- a/bignum.c
+++ b/bignum.c
@@ -12,8 +12,8 @@
#include <ctype.h>
#include <math.h>
-extern VALUE C_Integer;
-VALUE C_Bignum;
+extern VALUE cInteger;
+VALUE cBignum;
#define BDIGITS(x) RBIGNUM(x)->digits
#define BITSPERDIG (sizeof(USHORT)*CHAR_BIT)
@@ -23,9 +23,6 @@ VALUE C_Bignum;
#define BIGDN(x) ((x) >> BITSPERDIG)
#define BIGLO(x) ((x) & (BIGRAD-1))
-#define MAX(a,b) ((a)>(b)?(a):(b))
-#define MIN(a,b) ((a)<(b)?(a):(b))
-
static VALUE
bignew_1(class, len, sign)
VALUE class;
@@ -33,7 +30,7 @@ bignew_1(class, len, sign)
char sign;
{
NEWOBJ(big, struct RBignum);
- OBJSETUP(big, C_Bignum, T_BIGNUM);
+ OBJSETUP(big, cBignum, T_BIGNUM);
big->sign = sign;
big->len = len;
BDIGITS(big) = ALLOC_N(USHORT, len);
@@ -41,10 +38,10 @@ bignew_1(class, len, sign)
return (VALUE)big;
}
-#define bignew(len,sign) bignew_1(C_Bignum,len,sign)
+#define bignew(len,sign) bignew_1(cBignum,len,sign)
static VALUE
-Sbig_new(class, y)
+big_s_new(class, y)
VALUE class;
struct RBignum *y;
{
@@ -201,7 +198,7 @@ str2inum(str, base)
}
if (len <= (sizeof(VALUE)*CHAR_BIT)) {
- int result = strtoul(str, Qnil, base);
+ int result = strtoul(str, 0, base);
if (!sign) result = -result;
if (FIXABLE(result)) return INT2FIX(result);
@@ -283,6 +280,8 @@ big2str(x, base)
hbase = 020;
}
else {
+ j = 0;
+ hbase = 0;
Fail("bignum cannot treat base %d", base);
}
@@ -318,7 +317,7 @@ big2str(x, base)
}
static VALUE
-Fbig_to_s(x)
+big_to_s(x)
struct RBignum *x;
{
return big2str(x, 10);
@@ -345,7 +344,7 @@ big2int(x)
}
VALUE
-Fbig_to_i(x)
+big_to_i(x)
VALUE x;
{
int v = big2int(x);
@@ -396,14 +395,14 @@ big2dbl(x)
}
VALUE
-Fbig_to_f(x)
+big_to_f(x)
VALUE x;
{
return float_new(big2dbl(x));
}
static VALUE
-Fbig_uminus(x)
+big_uminus(x)
struct RBignum *x;
{
VALUE z = big_clone(x);
@@ -423,7 +422,12 @@ bigadd(x, y, sign)
long num;
UINT i, len;
- len = MAX(x->len, y->len) + 1;
+ if (x->len > y->len) {
+ len = x->len + 1;
+ }
+ else {
+ len = y->len + 1;
+ }
z = (struct RBignum*)bignew(len, sign==y->sign);
zds = BDIGITS(z);
@@ -486,7 +490,7 @@ bigadd(x, y, sign)
}
VALUE
-Fbig_plus(x, y)
+big_plus(x, y)
VALUE x, y;
{
VALUE z;
@@ -501,7 +505,7 @@ Fbig_plus(x, y)
}
VALUE
-Fbig_minus(x, y)
+big_minus(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) y = int2big(FIX2INT(y));
@@ -514,7 +518,7 @@ Fbig_minus(x, y)
}
VALUE
-Fbig_mul(x, y)
+big_mul(x, y)
struct RBignum *x, *y;
{
UINT i = 0, j;
@@ -674,7 +678,7 @@ bigdivmod(x, y, div, mod)
}
static VALUE
-Fbig_div(x, y)
+big_div(x, y)
VALUE x, y;
{
VALUE z;
@@ -683,13 +687,13 @@ Fbig_div(x, y)
else {
Check_Type(y, T_BIGNUM);
}
- bigdivmod(x, y, &z, Qnil);
+ bigdivmod(x, y, &z, 0);
return z;
}
static VALUE
-Fbig_mod(x, y)
+big_mod(x, y)
VALUE x, y;
{
VALUE z;
@@ -698,13 +702,13 @@ Fbig_mod(x, y)
else {
Check_Type(y, T_BIGNUM);
}
- bigdivmod(x, y, Qnil, &z);
+ bigdivmod(x, y, 0, &z);
return z;
}
static VALUE
-Fbig_divmod(x, y)
+big_divmod(x, y)
VALUE x, y;
{
VALUE div, mod;
@@ -719,10 +723,9 @@ Fbig_divmod(x, y)
}
VALUE
-Fbig_pow(x, y)
+big_pow(x, y)
VALUE x, y;
{
- double d1, d2;
VALUE z;
int n;
@@ -739,15 +742,15 @@ Fbig_pow(x, y)
while (--n) {
while (!(n % 2)) {
n = n /2;
- x = Fbig_mul(x, x);
+ x = big_mul(x, x);
}
- z = Fbig_mul(z, x);
+ z = big_mul(z, x);
}
return z;
}
VALUE
-Fbig_and(x, y)
+big_and(x, y)
struct RBignum *x, *y;
{
VALUE z;
@@ -798,7 +801,7 @@ Fbig_and(x, y)
}
VALUE
-Fbig_or(x, y)
+big_or(x, y)
struct RBignum *x, *y;
{
VALUE z;
@@ -850,7 +853,7 @@ Fbig_or(x, y)
}
VALUE
-Fbig_xor(x, y)
+big_xor(x, y)
struct RBignum *x, *y;
{
VALUE z;
@@ -904,7 +907,7 @@ Fbig_xor(x, y)
}
static VALUE
-Fbig_neg(x)
+big_neg(x)
struct RBignum *x;
{
VALUE z = big_clone(x);
@@ -919,22 +922,22 @@ Fbig_neg(x)
return bignorm(z);
}
-static VALUE Fbig_rshift();
+static VALUE big_rshift();
VALUE
-Fbig_lshift(x, y)
+big_lshift(x, y)
struct RBignum *x;
VALUE y;
{
USHORT *xds, *zds;
- UINT shift = NUM2INT(y);
+ int shift = NUM2INT(y);
UINT s1 = shift/(sizeof(USHORT)*CHAR_BIT);
UINT s2 = shift%(sizeof(USHORT)*CHAR_BIT);
VALUE z;
unsigned long num = 0;
UINT len, i;
- if (shift < 0) return Fbig_rshift(x, INT2FIX(-shift));
+ if (shift < 0) return big_rshift(x, INT2FIX(-shift));
xds = BDIGITS(x);
len = x->len;
z = bignew(len+s1+1, x->sign);
@@ -952,19 +955,19 @@ Fbig_lshift(x, y)
}
static VALUE
-Fbig_rshift(x, y)
+big_rshift(x, y)
struct RBignum *x;
VALUE y;
{
USHORT *xds, *zds;
- UINT shift = NUM2INT(y);
+ int shift = NUM2INT(y);
UINT s1 = shift/(sizeof(USHORT)*CHAR_BIT);
UINT s2 = shift%(sizeof(USHORT)*CHAR_BIT);
VALUE z;
unsigned long num = 0;
UINT i = x->len, j;
- if (shift < 0) return Fbig_lshift(x, INT2FIX(-shift));
+ if (shift < 0) return big_lshift(x, INT2FIX(-shift));
if (s1 > x->len) {
if (x->sign)
return INT2FIX(0);
@@ -984,7 +987,7 @@ Fbig_rshift(x, y)
}
static VALUE
-Fbig_aref(x, y)
+big_aref(x, y)
struct RBignum *x;
VALUE y;
{
@@ -1011,12 +1014,17 @@ Fbig_aref(x, y)
}
static VALUE
-Fbig_cmp(x, y)
+big_cmp(x, y)
struct RBignum *x, *y;
{
int xlen = x->len;
- Check_Type(x, T_BIGNUM);
+ if (FIXNUM_P(y)) {
+ y = (struct RBignum*)int2big(FIX2INT(y));
+ }
+ else {
+ Check_Type(y, T_BIGNUM);
+ }
if (x->sign > y->sign) return INT2FIX(1);
if (x->sign < y->sign) return INT2FIX(-1);
if (xlen < y->len)
@@ -1032,7 +1040,7 @@ Fbig_cmp(x, y)
}
static VALUE
-Fbig_hash(x)
+big_hash(x)
struct RBignum *x;
{
int i, len, key;
@@ -1046,7 +1054,7 @@ Fbig_hash(x)
}
static VALUE
-Fbig_coerce(x, y)
+big_coerce(x, y)
struct RBignum *x;
VALUE y;
{
@@ -1061,7 +1069,7 @@ Fbig_coerce(x, y)
}
static VALUE
-Fbig_abs(x)
+big_abs(x)
struct RBignum *x;
{
if (!x->sign) {
@@ -1071,32 +1079,33 @@ Fbig_abs(x)
return (VALUE)x;
}
+void
Init_Bignum()
{
- C_Bignum = rb_define_class("Bignum", C_Integer);
- rb_define_single_method(C_Bignum, "new", Sbig_new, 1);
-
- rb_define_method(C_Bignum, "to_s", Fbig_to_s, 0);
- rb_define_method(C_Bignum, "coerce", Fbig_coerce, 1);
- rb_define_method(C_Bignum, "-@", Fbig_uminus, 0);
- rb_define_method(C_Bignum, "+", Fbig_plus, 1);
- rb_define_method(C_Bignum, "-", Fbig_minus, 1);
- rb_define_method(C_Bignum, "*", Fbig_mul, 1);
- rb_define_method(C_Bignum, "/", Fbig_div, 1);
- rb_define_method(C_Bignum, "%", Fbig_mod, 1);
- rb_define_method(C_Bignum, "divmod", Fbig_divmod, 1);
- rb_define_method(C_Bignum, "**", Fbig_pow, 1);
- rb_define_method(C_Bignum, "&", Fbig_and, 1);
- rb_define_method(C_Bignum, "|", Fbig_or, 1);
- rb_define_method(C_Bignum, "^", Fbig_xor, 1);
- rb_define_method(C_Bignum, "~", Fbig_neg, 0);
- rb_define_method(C_Bignum, "<<", Fbig_lshift, 1);
- rb_define_method(C_Bignum, ">>", Fbig_rshift, 1);
- rb_define_method(C_Bignum, "[]", Fbig_aref, 1);
-
- rb_define_method(C_Bignum, "<=>", Fbig_cmp, 1);
- rb_define_method(C_Bignum, "hash", Fbig_hash, 0);
- rb_define_method(C_Bignum, "to_i", Fbig_to_i, 0);
- rb_define_method(C_Bignum, "to_f", Fbig_to_f, 0);
- rb_define_method(C_Bignum, "abs_f", Fbig_abs, 0);
+ cBignum = rb_define_class("Bignum", cInteger);
+ rb_define_singleton_method(cBignum, "new", big_s_new, 1);
+
+ rb_define_method(cBignum, "to_s", big_to_s, 0);
+ rb_define_method(cBignum, "coerce", big_coerce, 1);
+ rb_define_method(cBignum, "-@", big_uminus, 0);
+ rb_define_method(cBignum, "+", big_plus, 1);
+ rb_define_method(cBignum, "-", big_minus, 1);
+ rb_define_method(cBignum, "*", big_mul, 1);
+ rb_define_method(cBignum, "/", big_div, 1);
+ rb_define_method(cBignum, "%", big_mod, 1);
+ rb_define_method(cBignum, "divmod", big_divmod, 1);
+ rb_define_method(cBignum, "**", big_pow, 1);
+ rb_define_method(cBignum, "&", big_and, 1);
+ rb_define_method(cBignum, "|", big_or, 1);
+ rb_define_method(cBignum, "^", big_xor, 1);
+ rb_define_method(cBignum, "~", big_neg, 0);
+ rb_define_method(cBignum, "<<", big_lshift, 1);
+ rb_define_method(cBignum, ">>", big_rshift, 1);
+ rb_define_method(cBignum, "[]", big_aref, 1);
+
+ rb_define_method(cBignum, "<=>", big_cmp, 1);
+ rb_define_method(cBignum, "hash", big_hash, 0);
+ rb_define_method(cBignum, "to_i", big_to_i, 0);
+ rb_define_method(cBignum, "to_f", big_to_f, 0);
+ rb_define_method(cBignum, "abs_f", big_abs, 0);
}