[前][次][番号順一覧][スレッド一覧]

ruby-changes:1839

From: ko1@a...
Date: 1 Sep 2007 21:02:50 +0900
Subject: [ruby-changes:1839] akr - Ruby:r13330 (trunk): * include/ruby/ruby.h (struct RBignum): embed digits in RBignum for

akr	2007-09-01 21:02:36 +0900 (Sat, 01 Sep 2007)

  New Revision: 13330

  Modified files:
    trunk/.gdbinit
    trunk/ChangeLog
    trunk/bignum.c
    trunk/compar.c
    trunk/gc.c
    trunk/include/ruby/intern.h
    trunk/include/ruby/ruby.h
    trunk/marshal.c
    trunk/numeric.c
    trunk/random.c
    trunk/sprintf.c
    trunk/test/ruby/test_integer.rb

  Log:
    * include/ruby/ruby.h (struct RBignum): embed digits in RBignum for
      small bignums.
    
    * bignum.c: RBignum embeded digits implemented.
    
    * include/ruby/intern.h: declare rb_big_resize.
    
    * gc.c: don't free embedded digits.
    
    * numeric.c: replace direct bignum field accessor by abstract field
      accessor such as RBIGNUM(val)->sign to RBIGNUM_SIGN(val).
    
    * sprintf.c: ditto.
    
    * compar.c: ditto.
    
    * marshal.c: ditto.
    
    * random.c: ditto.
    
    * .gdbinit: support embedded small bignums.
    


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/numeric.c?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/include/ruby/ruby.h?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/.gdbinit?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bignum.c?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/gc.c?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/sprintf.c?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/marshal.c?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/ruby/test_integer.rb?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/random.c?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/include/ruby/intern.h?r1=13330&r2=13329
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/compar.c?r1=13330&r2=13329

Index: .gdbinit
===================================================================
--- .gdbinit	(revision 13329)
+++ .gdbinit	(revision 13330)
@@ -95,9 +95,17 @@
   else
   if ($flags & 0x1f) == 0x0d
     printf "T_BIGNUM: sign=%d len=%d ", \
-      ((struct RBignum*)$arg0)->sign, ((struct RBignum*)$arg0)->len
+      (($flags & RUBY_FL_USER1) != 0), \
+      (($flags & RUBY_FL_USER2) ? \
+       ($flags & (RUBY_FL_USER5|RUBY_FL_USER4|RUBY_FL_USER3)) >> (RUBY_FL_USHIFT+3) : \
+       ((struct RBignum*)$arg0)->as.heap.len)
+    if $flags & RUBY_FL_USER2
+      printf "(embed) "
+    end
     print (struct RBignum *)$arg0
-    x/xw ((struct RBignum*)$arg0)->digits
+    x/xw (($flags & RUBY_FL_USER2) ? \
+          ((struct RBignum*)$arg0)->as.ary : \
+          ((struct RBignum*)$arg0)->as.heap.digits)
   else
   if ($flags & 0x1f) == 0x0e
     printf "T_FILE: "
Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 13329)
+++ include/ruby/intern.h	(revision 13330)
@@ -77,6 +77,7 @@
 VALUE rb_big_clone(VALUE);
 void rb_big_2comp(VALUE);
 VALUE rb_big_norm(VALUE);
+void rb_big_resize(VALUE big, long len);
 VALUE rb_uint2big(VALUE);
 VALUE rb_int2big(SIGNED_VALUE);
 VALUE rb_uint2inum(VALUE);
Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 13329)
+++ include/ruby/ruby.h	(revision 13330)
@@ -547,13 +547,39 @@
      RSTRUCT(st)->as.ary : \
      RSTRUCT(st)->as.heap.ptr)
 
+#define RBIGNUM_EMBED_LEN_MAX ((sizeof(VALUE)*3)/sizeof(BDIGIT))
 struct RBignum {
     struct RBasic basic;
-    char sign; /* positive:1, negative:0 */
-    long len;
-    void *digits;
+    union {
+        struct {
+            long len;
+            BDIGIT *digits;
+        } heap;
+        BDIGIT ary[RBIGNUM_EMBED_LEN_MAX];
+    } as;
 };
+#define RBIGNUM_SIGN_BIT FL_USER1
+/* sign: positive:1, negative:0 */
+#define RBIGNUM_SIGN(b) ((RBASIC(b)->flags & RBIGNUM_SIGN_BIT) != 0)
+#define RBIGNUM_SET_SIGN(b,sign) \
+  ((sign) ? (RBASIC(b)->flags |= RBIGNUM_SIGN_BIT) \
+          : (RBASIC(b)->flags &= ~RBIGNUM_SIGN_BIT))
+#define RBIGNUM_POSITIVE_P(b) RBIGNUM_SIGN(b)
+#define RBIGNUM_NEGATIVE_P(b) (!RBIGNUM_SIGN(b))
 
+#define RBIGNUM_EMBED_FLAG FL_USER2
+#define RBIGNUM_EMBED_LEN_MASK (FL_USER5|FL_USER4|FL_USER3)
+#define RBIGNUM_EMBED_LEN_SHIFT (FL_USHIFT+3)
+#define RBIGNUM_LEN(b) \
+    ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
+     (long)((RBASIC(b)->flags >> RBIGNUM_EMBED_LEN_SHIFT) & \
+            (RBIGNUM_EMBED_LEN_MASK >> RBIGNUM_EMBED_LEN_SHIFT)) : \
+     RBIGNUM(b)->as.heap.len)
+#define RBIGNUM_DIGITS(b) \
+    ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
+     RBIGNUM(b)->as.ary : \
+     RBIGNUM(b)->as.heap.digits)
+
 #define R_CAST(st)   (struct st*)
 #define RBASIC(obj)  (R_CAST(RBasic)(obj))
 #define ROBJECT(obj) (R_CAST(RObject)(obj))
@@ -631,6 +657,8 @@
 #define FL_USER19     RUBY_FL_USER19
     RUBY_FL_USER20     = (1<<(FL_USHIFT+20)),
 #define FL_USER20     RUBY_FL_USER20
+    RUBY_FL_DUMMY      = ~(VALUE)0 >> 1 /* make sizeof(enum ruby_value_flags)
+                                           equal to sizeof(VALUE). */
 };
 
 #define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 13329)
+++ ChangeLog	(revision 13330)
@@ -1,3 +1,27 @@
+Sat Sep  1 20:56:07 2007  Tanaka Akira  <akr@f...>
+
+	* include/ruby/ruby.h (struct RBignum): embed digits in RBignum for
+	  small bignums.
+
+	* bignum.c: RBignum embeded digits implemented.
+
+	* include/ruby/intern.h: declare rb_big_resize.
+
+	* gc.c: don't free embedded digits.
+
+	* numeric.c: replace direct bignum field accessor by abstract field
+	  accessor such as RBIGNUM(val)->sign to RBIGNUM_SIGN(val).
+
+	* sprintf.c: ditto.
+
+	* compar.c: ditto.
+
+	* marshal.c: ditto.
+
+	* random.c: ditto.
+
+	* .gdbinit: support embedded small bignums.
+
 Sat Sep  1 19:59:43 2007  Masaki Suketa  <masaki.suketa@n...>
 
 	* ext/win32ole/win32ole.c (ole_event_free): IConnectionPoint should be
Index: sprintf.c
===================================================================
--- sprintf.c	(revision 13329)
+++ sprintf.c	(revision 13330)
@@ -658,11 +658,11 @@
 		    }
 		    else {
                         volatile VALUE tmp1;
-			if (!RBIGNUM(val)->sign) {
+			if (!RBIGNUM_SIGN(val)) {
 			    val = rb_big_clone(val);
 			    rb_big_2comp(val);
 			}
-			tmp1 = tmp = rb_big2str0(val, base, RBIGNUM(val)->sign);
+			tmp1 = tmp = rb_big2str0(val, base, RBIGNUM_SIGN(val));
 			s = RSTRING_PTR(tmp);
 			if (*s == '-') {
 			    if (base == 10) {
@@ -729,7 +729,7 @@
 		else {
 		    char c;
 
-		    if (!sign && bignum && !RBIGNUM(val)->sign)
+		    if (!sign && bignum && !RBIGNUM_SIGN(val))
 			c = sign_bits(base, p);
 		    else
 			c = '0';
Index: gc.c
===================================================================
--- gc.c	(revision 13329)
+++ gc.c	(revision 13330)
@@ -1311,8 +1311,8 @@
 	break;
 
       case T_BIGNUM:
-	if (RANY(obj)->as.bignum.digits) {
-	    RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits));
+	if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
+	    RUBY_CRITICAL(free(RBIGNUM_DIGITS(obj)));
 	}
 	break;
       case T_NODE:
Index: numeric.c
===================================================================
--- numeric.c	(revision 13329)
+++ numeric.c	(revision 13330)
@@ -2684,7 +2684,7 @@
     if (TYPE(idx) == T_BIGNUM) {
 	idx = rb_big_norm(idx);
 	if (!FIXNUM_P(idx)) {
-	    if (!RBIGNUM(idx)->sign || val >= 0)
+	    if (!RBIGNUM_SIGN(idx) || val >= 0)
 		return INT2FIX(0);
 	    return INT2FIX(1);
 	}
Index: compar.c
===================================================================
--- compar.c	(revision 13329)
+++ compar.c	(revision 13330)
@@ -24,7 +24,7 @@
     }
     if (FIXNUM_P(val)) return FIX2INT(val);
     if (TYPE(val) == T_BIGNUM) {
-	if (RBIGNUM(val)->sign) return 1;
+	if (RBIGNUM_SIGN(val)) return 1;
 	return -1;
     }
     if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
Index: bignum.c
===================================================================
--- bignum.c	(revision 13329)
+++ bignum.c	(revision 13330)
@@ -25,7 +25,7 @@
 #define USHORT _USHORT
 #endif
 
-#define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
+#define BDIGITS(x) (RBIGNUM_DIGITS(x))
 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
 #define DIGSPERLONG ((unsigned int)(SIZEOF_LONG/SIZEOF_BDIGITS))
@@ -37,16 +37,68 @@
 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
 #define BDIGMAX ((BDIGIT)-1)
 
-#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || (RBIGNUM(x)->len == 1 && BDIGITS(x)[0] == 0))
+#define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || (RBIGNUM_LEN(x) == 1 && BDIGITS(x)[0] == 0))
 
+#define RBIGNUM_SET_LEN(b,l) \
+  ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
+   (RBASIC(b)->flags = (RBASIC(b)->flags & ~RBIGNUM_EMBED_LEN_MASK) | \
+      ((l) << RBIGNUM_EMBED_LEN_SHIFT)) : \
+   (RBIGNUM(b)->as.heap.len = (l)))
+
+static void
+rb_big_realloc(VALUE big, long len)
+{
+    BDIGIT *ds;
+    if (RBASIC(big)->flags & RBIGNUM_EMBED_FLAG) {
+        if (RBIGNUM_EMBED_LEN_MAX < len) {
+            ds = ALLOC_N(BDIGIT, len);
+            MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, RBIGNUM_EMBED_LEN_MAX);
+            RBIGNUM(big)->as.heap.len = RBIGNUM_LEN(big);
+            RBIGNUM(big)->as.heap.digits = ds;
+            RBASIC(big)->flags &= ~RBIGNUM_EMBED_FLAG;
+        }
+    }
+    else {
+        if (len <= RBIGNUM_EMBED_LEN_MAX) {
+            ds = RBIGNUM(big)->as.heap.digits;
+            RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
+            RBIGNUM_SET_LEN(big, len);
+            if (ds) {
+                MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
+                free(ds);
+            }
+        }
+        else {
+            if (RBIGNUM_LEN(big) == 0) {
+                RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
+            }
+            else {
+                REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
+            }
+        }
+    }
+}
+
+void
+rb_big_resize(VALUE big, long len)
+{
+    rb_big_realloc(big, len);
+    RBIGNUM_SET_LEN(big, len);
+}
+
 static VALUE
 bignew_1(VALUE klass, long len, int sign)
 {
     NEWOBJ(big, struct RBignum);
     OBJSETUP(big, klass, T_BIGNUM);
-    big->sign = sign?1:0;
-    big->len = len;
-    big->digits = ALLOC_N(BDIGIT, len);
+    RBIGNUM_SET_SIGN(big, sign?1:0);
+    if (len <= RBIGNUM_EMBED_LEN_MAX) {
+        RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
+        RBIGNUM_SET_LEN(big, len);
+    }
+    else {
+        rb_big_resize((VALUE)big, len);
+    }
 
     return (VALUE)big;
 }
@@ -56,9 +108,9 @@
 VALUE
 rb_big_clone(VALUE x)
 {
-    VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign);
+    VALUE z = bignew_1(CLASS_OF(x), RBIGNUM_LEN(x), RBIGNUM_SIGN(x));
 
-    MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM(x)->len);
+    MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM_LEN(x));
     return z;
 }
 
@@ -66,7 +118,7 @@
 static void
 get2comp(VALUE x)
 {
-    long i = RBIGNUM(x)->len;
+    long i = RBIGNUM_LEN(x);
     BDIGIT *ds = BDIGITS(x);
     BDIGIT_DBL num;
 
@@ -77,11 +129,11 @@
 	num += ds[i];
 	ds[i++] = BIGLO(num);
 	num = BIGDN(num);
-    } while (i < RBIGNUM(x)->len);
+    } while (i < RBIGNUM_LEN(x));
     if (num != 0) {
-	REALLOC_N(RBIGNUM(x)->digits, BDIGIT, ++RBIGNUM(x)->len);
+        rb_big_resize(x, RBIGNUM_LEN(x)+1);
 	ds = BDIGITS(x);
-	ds[RBIGNUM(x)->len-1] = 1;
+	ds[RBIGNUM_LEN(x)-1] = 1;
     }
 }
 
@@ -94,19 +146,19 @@
 static VALUE
 bigtrunc(VALUE x)
 {
-    long len = RBIGNUM(x)->len;
+    long len = RBIGNUM_LEN(x);
     BDIGIT *ds = BDIGITS(x);
 
     if (len == 0) return x;
     while (--len && !ds[len]);
-    RBIGNUM(x)->len = ++len;
+    rb_big_resize(x, len+1);
     return x;
 }
 
 static VALUE
 bigfixize(VALUE x)
 {
-    long len = RBIGNUM(x)->len;
+    long len = RBIGNUM_LEN(x);
     BDIGIT *ds = BDIGITS(x);
 
     if (len*SIZEOF_BDIGITS <= sizeof(long)) {
@@ -115,7 +167,7 @@
 	    num = BIGUP(num) + ds[len];
 	}
 	if (num >= 0) {
-	    if (RBIGNUM(x)->sign) {
+	    if (RBIGNUM_SIGN(x)) {
 		if (POSFIXABLE(num)) return LONG2FIX(num);
 	    }
 	    else {
@@ -158,7 +210,7 @@
 
     i = DIGSPERLONG;
     while (--i && !digits[i]) ;
-    RBIGNUM(big)->len = i+1;
+    RBIGNUM_SET_LEN(big, i+1);
     return big;
 }
 
@@ -174,7 +226,7 @@
     }
     big = rb_uint2big(n);
     if (neg) {
-	RBIGNUM(big)->sign = 0;
+	RBIGNUM_SET_SIGN(big, 0);
     }
     return big;
 }
@@ -205,7 +257,7 @@
 	q = FIX2LONG(val);
     }
     else {
-	long len = RBIGNUM(val)->len;
+	long len = RBIGNUM_LEN(val);
 	BDIGIT *ds;
 
 	if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) {
@@ -217,7 +269,7 @@
 	    q = BIGUP(q);
 	    q += ds[len];
 	}
-	if (!RBIGNUM(val)->sign) q = -q;
+	if (!RBIGNUM_SIGN(val)) q = -q;
     }
     memcpy(buf, (char*)&q, SIZEOF_LONG_LONG);
 }
@@ -253,10 +305,10 @@
 
     i = DIGSPERLL;
     while (i-- && !digits[i]) ;
-    RBIGNUM(big)->len = i+1;
+    RBIGNUM_SET_LEN(big, i+1);
 
     if (neg) {
-	RBIGNUM(big)->sign = 0;
+	RBIGNUM_SET_SIGN(big, 0);
     }
     return bignorm(big);
 }
@@ -275,12 +327,12 @@
     if (FIXNUM_P(val)) {
 	val = rb_int2big(FIX2LONG(val));
     }
-    len = RBIGNUM(val)->len * SIZEOF_BDIGITS;
+    len = RBIGNUM_LEN(val) * SIZEOF_BDIGITS;
     if (len > QUAD_SIZE) {
 	rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
     }
     memcpy(buf, (char*)BDIGITS(val), len);
-    if (!RBIGNUM(val)->sign) {
+    if (!RBIGNUM_SIGN(val)) {
 	len = QUAD_SIZE;
 	while (len--) {
 	    *buf = ~*buf;
@@ -301,7 +353,7 @@
 	long len = QUAD_SIZE;
 	char *tmp = (char*)BDIGITS(big);
 
-	RBIGNUM(big)->sign = 0;
+	RBIGNUM_SET_SIGN(big, 0);
 	while (len--) {
 	    *tmp = ~*tmp;
 	    tmp++;
@@ -449,7 +501,7 @@
 	}
 	else {
 	    VALUE big = rb_uint2big(val);
-	    RBIGNUM(big)->sign = sign;
+	    RBIGNUM_SET_SIGN(big, sign);
 	    return bignorm(big);
 	}
     }
@@ -546,7 +598,7 @@
 
     i = DIGSPERLL;
     while (i-- && !digits[i]) ;
-    RBIGNUM(big)->len = i+1;
+    RBIGNUM_SET_LEN(big, i+1);
     return big;
 }
 
@@ -562,7 +614,7 @@
     }
     big = rb_ull2big(n);
     if (neg) {
-	RBIGNUM(big)->sign = 0;
+	RBIGNUM_SET_SIGN(big, 0);
     }
     return big;
 }
@@ -722,7 +774,7 @@
  * Let a natural number x is given by:
  * x = 2^0 * x_0 + 2^1 * x_1 + ... + 2^(B*n_0 - 1) * x_{B*n_0 - 1},
  * where B is BITSPERDIG (i.e. BDIGITS*CHAR_BIT) and n_0 is
- * RBIGNUM(x)->len.
+ * RBIGNUM_LEN(x).
  *
  * Now, we assume n_1 = min_n \{ n | 2^(B*n_0/2) <= b_1^(n_1) \}, so
  * it is realized that 2^(B*n_0) <= {b_1}^{2*n_1}, where b_1 is a
@@ -759,7 +811,7 @@
         return 0;
     }
     else {
-        bits = BITSPERDIG*RBIGNUM(x)->len;
+        bits = BITSPERDIG*RBIGNUM_LEN(x);
     }
 
     return (long)ceil(bits/(2*log_2[base - 2]));
@@ -768,7 +820,7 @@
 static long
 big2str_orig(VALUE x, int base, char* ptr, long len, long hbase, int trim)
 {
-    long i = RBIGNUM(x)->len, j = len;
+    long i = RBIGNUM_LEN(x), j = len;
     BDIGIT* ds = BDIGITS(x);
 
     while (i && j > 0) {
@@ -862,15 +914,15 @@
     n1 = big2str_find_n1(x, base);
     ss = rb_str_new(0, 2*n1 + 1); /* plus one for sign */
     ptr = RSTRING_PTR(ss);
-    ptr[0] = RBIGNUM(x)->sign ? '+' : '-';
+    ptr[0] = RBIGNUM_SIGN(x) ? '+' : '-';
 
     hbase = base*base;
 #if SIZEOF_BDIGITS > 2
     hbase *= hbase;
 #endif
-    off = !(trim && RBIGNUM(x)->sign); /* erase plus sign if trim */
+    off = !(trim && RBIGNUM_SIGN(x)); /* erase plus sign if trim */
     xx = rb_big_clone(x);
-    RBIGNUM(xx)->sign = 1;
+    RBIGNUM_SET_SIGN(xx, 1);
     if (n1 <= KARATSUBA_DIGITS) {
         len = off + big2str_orig(xx, base, ptr + off, 2*n1, hbase, trim);
     }
@@ -920,7 +972,7 @@
 static VALUE
 big2ulong(VALUE x, const char *type, int check)
 {
-    long len = RBIGNUM(x)->len;
+    long len = RBIGNUM_LEN(x);
     BDIGIT_DBL num;
     BDIGIT *ds;
 
@@ -942,7 +994,7 @@
 rb_big2ulong_pack(VALUE x)
 {
     VALUE num = big2ulong(x, "unsigned long", Qfalse);
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	return -num;
     }
     return num;
@@ -953,7 +1005,7 @@
 {
     VALUE num = big2ulong(x, "unsigned long", Qtrue);
 
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	if ((SIGNED_VALUE)num < 0) {
 	    rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
 	}
@@ -968,10 +1020,10 @@
     VALUE num = big2ulong(x, "long", Qtrue);
 
     if ((SIGNED_VALUE)num < 0 &&
-	(RBIGNUM(x)->sign || (SIGNED_VALUE)num != LONG_MIN)) {
+	(RBIGNUM_SIGN(x) || (SIGNED_VALUE)num != LONG_MIN)) {
 	rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
     }
-    if (!RBIGNUM(x)->sign) return -(SIGNED_VALUE)num;
+    if (!RBIGNUM_SIGN(x)) return -(SIGNED_VALUE)num;
     return num;
 }
 
@@ -980,7 +1032,7 @@
 static unsigned LONG_LONG
 big2ull(VALUE x, const char *type)
 {
-    long len = RBIGNUM(x)->len;
+    long len = RBIGNUM_LEN(x);
     BDIGIT_DBL num;
     BDIGIT *ds;
 
@@ -1000,7 +1052,7 @@
 {
     unsigned LONG_LONG num = big2ull(x, "unsigned long long");
 
-    if (!RBIGNUM(x)->sign) return -num;
+    if (!RBIGNUM_SIGN(x)) return -num;
     return num;
 }
 
@@ -1009,11 +1061,11 @@
 {
     unsigned LONG_LONG num = big2ull(x, "long long");
 
-    if ((LONG_LONG)num < 0 && (RBIGNUM(x)->sign
+    if ((LONG_LONG)num < 0 && (RBIGNUM_SIGN(x)
 			       || (LONG_LONG)num != LLONG_MIN)) {
 	rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
     }
-    if (!RBIGNUM(x)->sign) return -(LONG_LONG)num;
+    if (!RBIGNUM_SIGN(x)) return -(LONG_LONG)num;
     return num;
 }
 
@@ -1061,13 +1113,13 @@
 big2dbl(VALUE x)
 {
     double d = 0.0;
-    long i = RBIGNUM(x)->len;
+    long i = RBIGNUM_LEN(x);
     BDIGIT *ds = BDIGITS(x);
 
     while (i--) {
 	d = ds[i] + BIGRAD*d;
     }
-    if (!RBIGNUM(x)->sign) d = -d;
+    if (!RBIGNUM_SIGN(x)) d = -d;
     return d;
 }
 
@@ -1111,7 +1163,7 @@
 VALUE
 rb_big_cmp(VALUE x, VALUE y)
 {
-    long xlen = RBIGNUM(x)->len;
+    long xlen = RBIGNUM_LEN(x);
 
     switch (TYPE(y)) {
       case T_FIXNUM:
@@ -1128,18 +1180,18 @@
 	return rb_num_coerce_cmp(x, y);
     }
 
-    if (RBIGNUM(x)->sign > RBIGNUM(y)->sign) return INT2FIX(1);
-    if (RBIGNUM(x)->sign < RBIGNUM(y)->sign) return INT2FIX(-1);
-    if (xlen < RBIGNUM(y)->len)
-	return (RBIGNUM(x)->sign) ? INT2FIX(-1) : INT2FIX(1);
-    if (xlen > RBIGNUM(y)->len)
-	return (RBIGNUM(x)->sign) ? INT2FIX(1) : INT2FIX(-1);
+    if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1);
+    if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1);
+    if (xlen < RBIGNUM_LEN(y))
+	return (RBIGNUM_SIGN(x)) ? INT2FIX(-1) : INT2FIX(1);
+    if (xlen > RBIGNUM_LEN(y))
+	return (RBIGNUM_SIGN(x)) ? INT2FIX(1) : INT2FIX(-1);
 
     while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen]));
     if (-1 == xlen) return INT2FIX(0);
     return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ?
-	(RBIGNUM(x)->sign ? INT2FIX(1) : INT2FIX(-1)) :
-	    (RBIGNUM(x)->sign ? INT2FIX(-1) : INT2FIX(1));
+	(RBIGNUM_SIGN(x) ? INT2FIX(1) : INT2FIX(-1)) :
+	    (RBIGNUM_SIGN(x) ? INT2FIX(-1) : INT2FIX(1));
 }
 
 /*
@@ -1174,9 +1226,9 @@
       default:
 	return rb_equal(y, x);
     }
-    if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
-    if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
-    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
+    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
+    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
+    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
     return Qtrue;
 }
 
@@ -1195,9 +1247,9 @@
 rb_big_eql(VALUE x, VALUE y)
 {
     if (TYPE(y) != T_BIGNUM) return Qfalse;
-    if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
-    if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
-    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
+    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
+    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
+    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
     return Qtrue;
 }
 
@@ -1213,7 +1265,7 @@
 {
     VALUE z = rb_big_clone(x);
 
-    RBIGNUM(z)->sign = !RBIGNUM(x)->sign;
+    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
 
     return bignorm(z);
 }
@@ -1237,15 +1289,15 @@
     BDIGIT *ds;
     long i;
 
-    if (!RBIGNUM(x)->sign) get2comp(z);
+    if (!RBIGNUM_SIGN(x)) get2comp(z);
     ds = BDIGITS(z);
-    i = RBIGNUM(x)->len;
+    i = RBIGNUM_LEN(x);
     if (!i) return INT2FIX(~(SIGNED_VALUE)0);
     while (i--) {
 	ds[i] = ~ds[i];
     }
-    RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
-    if (RBIGNUM(x)->sign) get2comp(z);
+    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(z));
+    if (RBIGNUM_SIGN(x)) get2comp(z);
 
     return bignorm(z);
 }
@@ -1256,13 +1308,13 @@
     VALUE z = 0;
     BDIGIT *zds;
     BDIGIT_DBL_SIGNED num;
-    long i = RBIGNUM(x)->len;
+    long i = RBIGNUM_LEN(x);
 
     /* if x is larger than y, swap */
-    if (RBIGNUM(x)->len < RBIGNUM(y)->len) {
+    if (RBIGNUM_LEN(x) < RBIGNUM_LEN(y)) {
 	z = x; x = y; y = z;	/* swap x y */
     }
-    else if (RBIGNUM(x)->len == RBIGNUM(y)->len) {
+    else if (RBIGNUM_LEN(x) == RBIGNUM_LEN(y)) {
 	while (i > 0) {
 	    i--;
 	    if (BDIGITS(x)[i] > BDIGITS(y)[i]) {
@@ -1275,20 +1327,20 @@
 	}
     }
 
-    z = bignew(RBIGNUM(x)->len, z==0);
+    z = bignew(RBIGNUM_LEN(x), z==0);
     zds = BDIGITS(z);
 
-    for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
+    for (i = 0, num = 0; i < RBIGNUM_LEN(y); i++) {
 	num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i];
 	zds[i] = BIGLO(num);
 	num = BIGDN(num);
     }
-    while (num && i < RBIGNUM(x)->len) {
+    while (num && i < RBIGNUM_LEN(x)) {
 	num += BDIGITS(x)[i];
 	zds[i++] = BIGLO(num);
 	num = BIGDN(num);
     }
-    while (i < RBIGNUM(x)->len) {
+    while (i < RBIGNUM_LEN(x)) {
 	zds[i] = BDIGITS(x)[i];
 	i++;
     }
@@ -1303,28 +1355,28 @@
     BDIGIT_DBL num;
     long i, len;
 
-    sign = (sign == RBIGNUM(y)->sign);
-    if (RBIGNUM(x)->sign != sign) {
+    sign = (sign == RBIGNUM_SIGN(y));
+    if (RBIGNUM_SIGN(x) != sign) {
 	if (sign) return bigsub(y, x);
 	return bigsub(x, y);
     }
 
-    if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
-	len = RBIGNUM(x)->len + 1;
+    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
+	len = RBIGNUM_LEN(x) + 1;
 	z = x; x = y; y = z;
     }
     else {
-	len = RBIGNUM(y)->len + 1;
+	len = RBIGNUM_LEN(y) + 1;
     }
     z = bignew(len, sign);
 
-    len = RBIGNUM(x)->len;
+    len = RBIGNUM_LEN(x);
     for (i = 0, num = 0; i < len; i++) {
 	num += (BDIGIT_DBL)BDIGITS(x)[i] + BDIGITS(y)[i];
 	BDIGITS(z)[i] = BIGLO(num);
 	num = BIGDN(num);
     }
-    len = RBIGNUM(y)->len;
+    len = RBIGNUM_LEN(y);
     while (num && i < len) {
 	num += BDIGITS(y)[i];
 	BDIGITS(z)[i++] = BIGLO(num);
@@ -1412,15 +1464,15 @@
 	return rb_num_coerce_bin(x, y);
     }
 
-    j = RBIGNUM(x)->len + RBIGNUM(y)->len + 1;
-    z = bignew(j, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
+    j = RBIGNUM_LEN(x) + RBIGNUM_LEN(y) + 1;
+    z = bignew(j, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
     zds = BDIGITS(z);
     while (j--) zds[j] = 0;
-    for (i = 0; i < RBIGNUM(x)->len; i++) {
+    for (i = 0; i < RBIGNUM_LEN(x); i++) {
 	BDIGIT_DBL dd = BDIGITS(x)[i];
 	if (dd == 0) continue;
 	n = 0;
-	for (j = 0; j < RBIGNUM(y)->len; j++) {
+	for (j = 0; j < RBIGNUM_LEN(y); j++) {
 	    BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * BDIGITS(y)[j];
 	    n = zds[i + j] + ee;
 	    if (ee) zds[i + j] = BIGLO(n);
@@ -1449,7 +1501,7 @@
 static void
 bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
 {
-    long nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
+    long nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y);
     long i, j;
     VALUE yy, z;
     BDIGIT *xds, *yds, *zds, *tds;
@@ -1475,15 +1527,15 @@
 	    zds[i] = (BDIGIT)(t2 / dd);
 	    t2 %= dd;
 	}
-	RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign;
+	RBIGNUM_SET_SIGN(z, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
 	if (modp) {
 	    *modp = rb_uint2big((VALUE)t2);
-	    RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
+	    RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x));
 	}
 	if (divp) *divp = z;
 	return;
     }
-    z = bignew(nx==ny?nx+2:nx+1, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
+    z = bignew(nx==ny?nx+2:nx+1, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
     zds = BDIGITS(z);
     if (nx==ny) zds[nx+1] = 0;
     while (!yds[ny-1]) ny--;
@@ -1554,7 +1606,7 @@
 	zds = BDIGITS(*divp);
 	j = (nx==ny ? nx+2 : nx+1) - ny;
 	for (i = 0;i < j;i++) zds[i] = zds[i+ny];
-	RBIGNUM(*divp)->len = i;
+	RBIGNUM_SET_LEN(*divp, i);
     }
     if (modp) {			/* normalize remainder */
 	*modp = rb_big_clone(z);
@@ -1569,8 +1621,8 @@
 		t2 = BIGUP(q);
 	    }
 	}
-	RBIGNUM(*modp)->len = ny;
-	RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
+	RBIGNUM_SET_LEN(*modp, ny);
+	RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x));
     }
 }
 
@@ -1580,7 +1632,7 @@
     VALUE mod;
 
     bigdivrem(x, y, divp, &mod);
-    if (RBIGNUM(x)->sign != RBIGNUM(y)->sign && !BIGZEROP(mod)) {
+    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y) && !BIGZEROP(mod)) {
 	if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
 	if (modp) *modp = bigadd(mod, y, 1);
     }
@@ -1767,8 +1819,8 @@
 	VALUE z;
 	int ex, ey;
 
-	ex = (RBIGNUM(bigtrunc(x))->len - 1) * BITSPERDIG;
-	ex += bdigbitsize(BDIGITS(x)[RBIGNUM(x)->len - 1]);
+	ex = (RBIGNUM_LEN(bigtrunc(x)) - 1) * BITSPERDIG;
+	ex += bdigbitsize(BDIGITS(x)[RBIGNUM_LEN(x) - 1]);
 	ex -= 2 * DBL_BIGDIG * BITSPERDIG;
 	if (ex) x = big_shift(x, ex);
 
@@ -1776,8 +1828,8 @@
 	  case T_FIXNUM:
 	    y = rb_int2big(FIX2LONG(y));
 	  case T_BIGNUM: {
-	    ey = (RBIGNUM(bigtrunc(y))->len - 1) * BITSPERDIG;
-	    ey += bdigbitsize(BDIGITS(y)[RBIGNUM(y)->len - 1]);
+	    ey = (RBIGNUM_LEN(bigtrunc(y)) - 1) * BITSPERDIG;
+	    ey += bdigbitsize(BDIGITS(y)[RBIGNUM_LEN(y) - 1]);
 	    ey -= DBL_BIGDIG * BITSPERDIG;
 	    if (ey) y = big_shift(y, ey);
 	  bignum:
@@ -1812,7 +1864,7 @@
 static VALUE
 bigsqr(VALUE x)
 {
-    long len = RBIGNUM(x)->len, k = len / 2, i;
+    long len = RBIGNUM_LEN(x), k = len / 2, i;
     VALUE a, b, a2, z;
     BDIGIT_DBL num;
 
@@ -1827,26 +1879,30 @@
 
     a2 = bigtrunc(bigsqr(a));
     z = bigsqr(b);
-    REALLOC_N(RBIGNUM(z)->digits, BDIGIT, (len = 2 * k + RBIGNUM(a2)->len) + 1);
-    while (RBIGNUM(z)->len < 2 * k) BDIGITS(z)[RBIGNUM(z)->len++] = 0;
-    MEMCPY(BDIGITS(z) + 2 * k, BDIGITS(a2), BDIGIT, RBIGNUM(a2)->len);
-    RBIGNUM(z)->len = len;
+    rb_big_realloc(z, (len = 2 * k + RBIGNUM_LEN(a2)) + 1);
+    while (RBIGNUM_LEN(z) < 2 * k) {
+          BDIGITS(z)[RBIGNUM_LEN(z)] = 0;
+          RBIGNUM_SET_LEN(z, RBIGNUM_LEN(z)+1);
+    }
+    MEMCPY(BDIGITS(z) + 2 * k, BDIGITS(a2), BDIGIT, RBIGNUM_LEN(a2));
+    RBIGNUM_SET_LEN(z, len);
     a2 = bigtrunc(rb_big_mul0(a, b));
-    len = RBIGNUM(a2)->len;
+    len = RBIGNUM_LEN(a2);
     for (i = 0, num = 0; i < len; i++) {
 	num += (BDIGIT_DBL)BDIGITS(z)[i + k] + ((BDIGIT_DBL)BDIGITS(a2)[i] << 1);
 	BDIGITS(z)[i + k] = BIGLO(num);
 	num = BIGDN(num);
     }
     if (num) {
-	len = RBIGNUM(z)->len;
+	len = RBIGNUM_LEN(z);
 	for (i += k; i < len && num; ++i) {
 	    num += (BDIGIT_DBL)BDIGITS(z)[i];
 	    BDIGITS(z)[i] = BIGLO(num);
 	    num = BIGDN(num);
 	}
 	if (num) {
-	    BDIGITS(z)[RBIGNUM(z)->len++] = BIGLO(num);
+	    BDIGITS(z)[RBIGNUM_LEN(z)] = BIGLO(num);
+            RBIGNUM_SET_LEN(z, RBIGNUM_LEN(z)+1);
 	}
     }
     return bigtrunc(z);
@@ -1889,8 +1945,8 @@
 	    SIGNED_VALUE mask;
 	    const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
 
-	    if ((RBIGNUM(x)->len > BIGLEN_LIMIT) ||
-		(RBIGNUM(x)->len > BIGLEN_LIMIT / yy)) {
+	    if ((RBIGNUM_LEN(x) > BIGLEN_LIMIT) ||
+		(RBIGNUM_LEN(x) > BIGLEN_LIMIT / yy)) {
 		rb_warn("in a**b, b may be too big");
 		d = (double)yy;
 		break;
@@ -1932,29 +1988,29 @@
     if (FIXNUM_P(y)) {
 	y = rb_int2big(FIX2LONG(y));
     }
-    if (!RBIGNUM(y)->sign) {
+    if (!RBIGNUM_SIGN(y)) {
 	y = rb_big_clone(y);
 	get2comp(y);
     }
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	x = rb_big_clone(x);
 	get2comp(x);
     }
-    if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
-	l1 = RBIGNUM(y)->len;
-	l2 = RBIGNUM(x)->len;
+    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
+	l1 = RBIGNUM_LEN(y);
+	l2 = RBIGNUM_LEN(x);
 	ds1 = BDIGITS(y);
 	ds2 = BDIGITS(x);
-	sign = RBIGNUM(y)->sign;
+	sign = RBIGNUM_SIGN(y);
     }
     else {
-	l1 = RBIGNUM(x)->len;
-	l2 = RBIGNUM(y)->len;
+	l1 = RBIGNUM_LEN(x);
+	l2 = RBIGNUM_LEN(y);
 	ds1 = BDIGITS(x);
 	ds2 = BDIGITS(y);
-	sign = RBIGNUM(x)->sign;
+	sign = RBIGNUM_SIGN(x);
     }
-    z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign);
+    z = bignew(l2, RBIGNUM_SIGN(x) || RBIGNUM_SIGN(y));
     zds = BDIGITS(z);
 
     for (i=0; i<l1; i++) {
@@ -1963,7 +2019,7 @@
     for (; i<l2; i++) {
 	zds[i] = sign?0:ds2[i];
     }
-    if (!RBIGNUM(z)->sign) get2comp(z);
+    if (!RBIGNUM_SIGN(z)) get2comp(z);
     return bignorm(z);
 }
 
@@ -1988,29 +2044,29 @@
 	y = rb_int2big(FIX2LONG(y));
     }
 
-    if (!RBIGNUM(y)->sign) {
+    if (!RBIGNUM_SIGN(y)) {
 	y = rb_big_clone(y);
 	get2comp(y);
     }
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	x = rb_big_clone(x);
 	get2comp(x);
     }
-    if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
-	l1 = RBIGNUM(y)->len;
-	l2 = RBIGNUM(x)->len;
+    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
+	l1 = RBIGNUM_LEN(y);
+	l2 = RBIGNUM_LEN(x);
 	ds1 = BDIGITS(y);
 	ds2 = BDIGITS(x);
-	sign = RBIGNUM(y)->sign;
+	sign = RBIGNUM_SIGN(y);
     }
     else {
-	l1 = RBIGNUM(x)->len;
-	l2 = RBIGNUM(y)->len;
+	l1 = RBIGNUM_LEN(x);
+	l2 = RBIGNUM_LEN(y);
 	ds1 = BDIGITS(x);
 	ds2 = BDIGITS(y);
-	sign = RBIGNUM(x)->sign;
+	sign = RBIGNUM_SIGN(x);
     }
-    z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
+    z = bignew(l2, RBIGNUM_SIGN(x) && RBIGNUM_SIGN(y));
     zds = BDIGITS(z);
 
     for (i=0; i<l1; i++) {
@@ -2019,7 +2075,7 @@
     for (; i<l2; i++) {
 	zds[i] = sign?ds2[i]:(BIGRAD-1);
     }
-    if (!RBIGNUM(z)->sign) get2comp(z);
+    if (!RBIGNUM_SIGN(z)) get2comp(z);
 
     return bignorm(z);
 }
@@ -2046,31 +2102,31 @@
 	y = rb_int2big(FIX2LONG(y));
     }
 
-    if (!RBIGNUM(y)->sign) {
+    if (!RBIGNUM_SIGN(y)) {
 	y = rb_big_clone(y);
 	get2comp(y);
     }
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	x = rb_big_clone(x);
 	get2comp(x);
     }
-    if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
-	l1 = RBIGNUM(y)->len;
-	l2 = RBIGNUM(x)->len;
+    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
+	l1 = RBIGNUM_LEN(y);
+	l2 = RBIGNUM_LEN(x);
 	ds1 = BDIGITS(y);
 	ds2 = BDIGITS(x);
-	sign = RBIGNUM(y)->sign;
+	sign = RBIGNUM_SIGN(y);
     }
     else {
-	l1 = RBIGNUM(x)->len;
-	l2 = RBIGNUM(y)->len;
+	l1 = RBIGNUM_LEN(x);
+	l2 = RBIGNUM_LEN(y);
 	ds1 = BDIGITS(x);
 	ds2 = BDIGITS(y);
-	sign = RBIGNUM(x)->sign;
+	sign = RBIGNUM_SIGN(x);
     }
-    RBIGNUM(x)->sign = RBIGNUM(x)->sign?1:0;
-    RBIGNUM(y)->sign = RBIGNUM(y)->sign?1:0;
-    z = bignew(l2, !(RBIGNUM(x)->sign ^ RBIGNUM(y)->sign));
+    RBIGNUM_SET_SIGN(x, RBIGNUM_SIGN(x)?1:0);
+    RBIGNUM_SET_SIGN(y, RBIGNUM_SIGN(y)?1:0);
+    z = bignew(l2, !(RBIGNUM_SIGN(x) ^ RBIGNUM_SIGN(y)));
     zds = BDIGITS(z);
 
     for (i=0; i<l1; i++) {
@@ -2079,7 +2135,7 @@
     for (; i<l2; i++) {
 	zds[i] = sign?ds2[i]:~ds2[i];
     }
-    if (!RBIGNUM(z)->sign) get2comp(z);
+    if (!RBIGNUM_SIGN(z)) get2comp(z);
 
     return bignorm(z);
 }
@@ -2087,9 +2143,9 @@
 static VALUE
 check_shiftdown(VALUE y, VALUE x)
 {
-    if (!RBIGNUM(x)->len) return INT2FIX(0);
-    if (RBIGNUM(y)->len > SIZEOF_LONG / SIZEOF_BDIGITS) {
-	return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(-1);
+    if (!RBIGNUM_LEN(x)) return INT2FIX(0);
+    if (RBIGNUM_LEN(y) > SIZEOF_LONG / SIZEOF_BDIGITS) {
+	return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(-1);
     }
     return Qnil;
 }
@@ -2117,7 +2173,7 @@
 	    break;
 	}
 	else if (TYPE(y) == T_BIGNUM) {
-	    if (!RBIGNUM(y)->sign) {
+	    if (!RBIGNUM_SIGN(y)) {
 		VALUE t = check_shiftdown(y, x);
 		if (!NIL_P(t)) return t;
 		neg = 1;
@@ -2142,8 +2198,8 @@
     BDIGIT_DBL num = 0;
     long len, i;
 
-    len = RBIGNUM(x)->len;
-    z = bignew(len+s1+1, RBIGNUM(x)->sign);
+    len = RBIGNUM_LEN(x);
+    z = bignew(len+s1+1, RBIGNUM_SIGN(x));
     zds = BDIGITS(z);
     for (i=0; i<s1; i++) {
 	*zds++ = 0;
@@ -2181,7 +2237,7 @@
 	    break;
 	}
 	else if (TYPE(y) == T_BIGNUM) {
-	    if (RBIGNUM(y)->sign) {
+	    if (RBIGNUM_SIGN(y)) {
 		VALUE t = check_shiftdown(y, x);
 		if (!NIL_P(t)) return t;
 	    }
@@ -2209,24 +2265,24 @@
     long i, j;
     volatile VALUE save_x;
 
-    if (s1 > RBIGNUM(x)->len) {
-	if (RBIGNUM(x)->sign)
+    if (s1 > RBIGNUM_LEN(x)) {
+	if (RBIGNUM_SIGN(x))
 	    return INT2FIX(0);
 	else
 	    return INT2FIX(-1);
     }
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	save_x = x = rb_big_clone(x);
 	get2comp(x);
     }
     xds = BDIGITS(x);
-    i = RBIGNUM(x)->len; j = i - s1;
+    i = RBIGNUM_LEN(x); j = i - s1;
     if (j == 0) {
-	if (RBIGNUM(x)->sign) return INT2FIX(0);
+	if (RBIGNUM_SIGN(x)) return INT2FIX(0);
 	else return INT2FIX(-1);
     }
-    z = bignew(j, RBIGNUM(x)->sign);
-    if (!RBIGNUM(x)->sign) {
+    z = bignew(j, RBIGNUM_SIGN(x));
+    if (!RBIGNUM_SIGN(x)) {
 	num = ((BDIGIT_DBL)~0) << BITSPERDIG;
     }
     zds = BDIGITS(z);
@@ -2235,7 +2291,7 @@
 	zds[j] = BIGLO(num);
 	num = BIGUP(xds[i]);
     }
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	get2comp(z);
     }
     return bignorm(z);
@@ -2269,11 +2325,11 @@
     long i, s1, s2;
 
     if (TYPE(y) == T_BIGNUM) {
-	if (!RBIGNUM(y)->sign)
+	if (!RBIGNUM_SIGN(y))
 	    return INT2FIX(0);
-	if (RBIGNUM(bigtrunc(y))->len > SIZEOF_VALUE/SIZEOF_BDIGITS) {
+	if (RBIGNUM_LEN(bigtrunc(y)) > SIZEOF_VALUE/SIZEOF_BDIGITS) {
 	  out_of_range:
-	    return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1);
+	    return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
 	}
 	shift = big2ulong(y, "long", Qfalse);
     }
@@ -2285,8 +2341,8 @@
     s1 = shift/BITSPERDIG;
     s2 = shift%BITSPERDIG;
 
-    if (s1 >= RBIGNUM(x)->len) goto out_of_range;
-    if (!RBIGNUM(x)->sign) {
+    if (s1 >= RBIGNUM_LEN(x)) goto out_of_range;
+    if (!RBIGNUM_SIGN(x)) {
 	xds = BDIGITS(x);
 	i = 0; num = 1;
 	while (num += ~xds[i], ++i <= s1) {
@@ -2313,7 +2369,7 @@
 {
     int hash;
 
-    hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM(x)->len) ^ RBIGNUM(x)->sign;
+    hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM_LEN(x)) ^ RBIGNUM_SIGN(x);
     return INT2FIX(hash);
 }
 
@@ -2350,9 +2406,9 @@
 static VALUE
 rb_big_abs(VALUE x)
 {
-    if (!RBIGNUM(x)->sign) {
+    if (!RBIGNUM_SIGN(x)) {
 	x = rb_big_clone(x);
-	RBIGNUM(x)->sign = 1;
+	RBIGNUM_SET_SIGN(x, 1);
     }
     return x;
 }
@@ -2372,7 +2428,7 @@
 static VALUE
 rb_big_size(VALUE big)
 {
-    return LONG2FIX(RBIGNUM(big)->len*SIZEOF_BDIGITS);
+    return LONG2FIX(RBIGNUM_LEN(big)*SIZEOF_BDIGITS);
 }
 
 /*
Index: marshal.c
===================================================================
--- marshal.c	(revision 13329)
+++ marshal.c	(revision 13330)
@@ -514,9 +514,9 @@
 	  case T_BIGNUM:
 	    w_byte(TYPE_BIGNUM, arg);
 	    {
-		char sign = RBIGNUM(obj)->sign ? '+' : '-';
-		long len = RBIGNUM(obj)->len;
-		BDIGIT *d = RBIGNUM(obj)->digits;
+		char sign = RBIGNUM_SIGN(obj) ? '+' : '-';
+		long len = RBIGNUM_LEN(obj);
+		BDIGIT *d = RBIGNUM_DIGITS(obj);
 
 		w_byte(sign, arg);
 		w_long(SHORTLEN(len), arg); /* w_short? */
@@ -1060,21 +1060,21 @@
 
 	    NEWOBJ(big, struct RBignum);
 	    OBJSETUP(big, rb_cBignum, T_BIGNUM);
-	    big->sign = (r_byte(arg) == '+');
+	    RBIGNUM_SET_SIGN(big, (r_byte(arg) == '+'));
 	    len = r_long(arg);
 	    data = r_bytes0(len * 2, arg);
 #if SIZEOF_BDIGITS == SIZEOF_SHORT
-	    big->len = len;
+            rb_big_resize((VALUE)big, len);
 #else
-	    big->len = (len + 1) * 2 / sizeof(BDIGIT);
+            rb_big_resize((VALUE)big, (len + 1) * 2 / sizeof(BDIGIT));
 #endif
-	    big->digits = digits = ALLOC_N(BDIGIT, big->len);
+            digits = RBIGNUM_DIGITS(big);
 	    MEMCPY(digits, RSTRING_PTR(data), char, len * 2);
 #if SIZEOF_BDIGITS > SIZEOF_SHORT
 	    MEMZERO((char *)digits + len * 2, char,
-		    big->len * sizeof(BDIGIT) - len * 2);
+		    RBIGNUM_LEN(big) * sizeof(BDIGIT) - len * 2);
 #endif
-	    len = big->len;
+	    len = RBIGNUM_LEN(big);
 	    while (len > 0) {
 		unsigned char *p = (unsigned char *)digits;
 		BDIGIT num = 0;
Index: test/ruby/test_integer.rb
===================================================================
--- test/ruby/test_integer.rb	(revision 13329)
+++ test/ruby/test_integer.rb	(revision 13330)
@@ -2,6 +2,12 @@
 
 class TestInteger < Test::Unit::TestCase
   VS = [
+    -0x1000000000000000000000000000000000000000000000002,
+    -0x1000000000000000000000000000000000000000000000001,
+    -0x1000000000000000000000000000000000000000000000000,
+    -0x1000000000000000000000002,
+    -0x1000000000000000000000001,
+    -0x1000000000000000000000000,
     -0x10000000000000002,
     -0x10000000000000001,
     -0x10000000000000000,
@@ -89,6 +95,12 @@
     0xffffffffffffffff,
     0x10000000000000000,
     0x10000000000000001,
+    0xffffffffffffffffffffffff,
+    0x1000000000000000000000000,
+    0x1000000000000000000000001,
+    0xffffffffffffffffffffffffffffffffffffffffffffffff,
+    0x1000000000000000000000000000000000000000000000000,
+    0x1000000000000000000000000000000000000000000000001
   ]
 
   #VS.map! {|v| 0x4000000000000000.coerce(v)[0] }
Index: random.c
===================================================================
--- random.c	(revision 13329)
+++ random.c	(revision 13330)
@@ -204,7 +204,7 @@
           len = sizeof(VALUE);
           break;
       case T_BIGNUM:
-          len = RBIGNUM(seed)->len * SIZEOF_BDIGITS;
+          len = RBIGNUM_LEN(seed) * SIZEOF_BDIGITS;
           if (len == 0)
               len = 4;
           break;
@@ -223,12 +223,12 @@
     }
     else {
         int i, j;
-        for (i = RBIGNUM(seed)->len-1; 0 <= i; i--) {
+        for (i = RBIGNUM_LEN(seed)-1; 0 <= i; i--) {
             j = i * SIZEOF_BDIGITS / 4;
 #if SIZEOF_BDIGITS < 4
             buf[j] <<= SIZEOF_BDIGITS * 8;
 #endif
-            buf[j] |= ((BDIGIT *)RBIGNUM(seed)->digits)[i];
+            buf[j] |= RBIGNUM_DIGITS(seed)[i];
         }
     }
     while (1 < len && buf[len-1] == 0) {
@@ -263,12 +263,12 @@
     OBJSETUP(big, rb_cBignum, T_BIGNUM);
 
     seed_len = 4 * sizeof(long);
-    big->sign = 1;
-    big->len = seed_len / SIZEOF_BDIGITS + 1;
-    digits = big->digits = ALLOC_N(BDIGIT, big->len);
-    seed = (unsigned long *)big->digits;
+    RBIGNUM_SET_SIGN(big, 1);
+    rb_big_resize((VALUE)big, seed_len / SIZEOF_BDIGITS + 1);
+    digits = RBIGNUM_DIGITS(big);
+    seed = (unsigned long *)RBIGNUM_DIGITS(big);
 
-    memset(digits, 0, big->len * SIZEOF_BDIGITS);
+    memset(digits, 0, RBIGNUM_LEN(big) * SIZEOF_BDIGITS);
 
 #ifdef S_ISCHR
     if ((fd = open("/dev/urandom", O_RDONLY
@@ -296,7 +296,7 @@
     seed[3] ^= (unsigned long)&seed;
 
     /* set leading-zero-guard if need. */
-    digits[big->len-1] = digits[big->len-2] <= 1 ? 1 : 0;
+    digits[RBIGNUM_LEN(big)-1] = digits[RBIGNUM_LEN(big)-2] <= 1 ? 1 : 0;
 
     return rb_big_norm((VALUE)big);
 }
@@ -370,20 +370,20 @@
     struct RBignum *val;
     int i, len, boundary;
 
-    len = (limit->len * SIZEOF_BDIGITS + 3) / 4;
+    len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4;
     val = (struct RBignum *)rb_big_clone((VALUE)limit);
-    val->sign = 1;
+    RBIGNUM_SET_SIGN(val, 1);
 #if SIZEOF_BDIGITS == 2
-# define BIG_GET32(big,i) (((BDIGIT *)(big)->digits)[(i)*2] | \
-                           ((i)*2+1 < (big)->len ? (((BDIGIT *)(big)->digits)[(i)*2+1] << 16) \
+# define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[(i)*2] | \
+                           ((i)*2+1 < RBIGNUM_DIGITS(big) ? (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) \
                                                  : 0))
-# define BIG_SET32(big,i,d) ((((BDIGIT *)(big)->digits)[(i)*2] = (d) & 0xffff), \
-                             ((i)*2+1 < (big)->len ? (((BDIGIT *)(big)->digits)[(i)*2+1] = (d) >> 16) \
+# define BIG_SET32(big,i,d) ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \
+                             ((i)*2+1 < RBIGNUM_DIGITS(big) ? (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) \
                                                    : 0))
 #else
     /* SIZEOF_BDIGITS == 4 */
-# define BIG_GET32(big,i) (((BDIGIT *)(big)->digits)[i])
-# define BIG_SET32(big,i,d) (((BDIGIT *)(big)->digits)[i] = (d))
+# define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[i])
+# define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[i] = (d))
 #endif
   retry:
     mask = 0;
@@ -450,9 +450,9 @@
       bignum:
         {
             struct RBignum *limit = (struct RBignum *)vmax;
-            if (!limit->sign) {
+            if (!RBIGNUM_SIGN(limit)) {
                 limit = (struct RBignum *)rb_big_clone(vmax);
-                limit->sign = 1;
+                RBIGNUM_SET_SIGN(limit, 1);
             }
             limit = (struct RBignum *)rb_big_minus((VALUE)limit, INT2FIX(1));
             if (FIXNUM_P((VALUE)limit)) {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧]