# Optimize small bignum space

**URL:** <https://www.ruby-forum.com/t/optimize-small-bignum-space/246512>\
**Category:** Development\
**Created:** [August 31, 2007, 8:04pm UTC](https://www.ruby-forum.com/t/optimize-small-bignum-space/246512 "2007-08-31T20:04:25Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [August 31, 2007, 8:04pm UTC](https://www.ruby-forum.com/t/optimize-small-bignum-space/246512/1 "2007-08-31T20:04:25Z")

</div>

e$B;W$$N)$C$F!"\>.$5$$e(B Bignum e$B$re(B RBignum  
e$B$K5M$a$k$h$&$K$7$F$\_$^e(B  
e$B$7$?!#$I$&$G$7$g$&$+!#e(B

3 word e$B;H$($k$N$G!“e(B32bit e$B$Ge(B 2**96 e$B$"$?$j$^$GF~$j$^$9!#e(B  
(64bit e$B$J$ie(B 2**192 e$B$”$?$j$^$Ge(B)

./ruby -e ‘a = []; 1000000.times { a \<\< 0xfffffffffffffffffffffffe+1 }’  
e$B$H$$$&?M9)E\*$J$b$N$G$"$l$PH\>J,6a$/%a%b%j\>CHq$,8:$i$;$^$9!#$de(B  
e$B$O$je(B malloc e$B\<+BN$rL5$/$9$H8z$-$^$9$M!#e(B

e$B$b$A$m$s!“8=\<B$K$Oe(B 2**31 e$B$+$ie(B 2**96 e$B$”$?$j$Ne(B Bignum  
e$B$r$I$N$/e(B  
e$B$i$$;H$&$+$,LdBj$K$J$j$^$9$,!"$$$^$N$^$^$@$He(B 32bit e$B$JCM$N7We(B  
e$B;;$r$9$k$H$-$K%a%b%j$NL5BL$J5$J,$,$9$k$N$G!"$I$s$J$b$N$G$7$ge(B  
e$B$&$+!#e(B

# Index: .gdbinit

— .gdbinit (e$B%j%S%8%g%se(B 13324)  
+++ .gdbinit (e$B:n6H%3%T!\<e(B)  
@@ -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 (e$B%j%S%8%g%se(B 13324)  
+++ include/ruby/intern.h (e$B:n6H%3%T!\<e(B)  
@@ -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 (e$B%j%S%8%g%se(B 13324)  
+++ include/ruby/ruby.h (e$B:n6H%3%T!\<e(B)  
@@ -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: sprintf.c

— sprintf.c (e$B%j%S%8%g%se(B 13324)  
+++ sprintf.c (e$B:n6H%3%T!\<e(B)  
@@ -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 (e$B%j%S%8%g%se(B 13324)  
+++ gc.c (e$B:n6H%3%T!\<e(B)  
@@ -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 (e$B%j%S%8%g%se(B 13324)  
+++ numeric.c (e$B:n6H%3%T!\<e(B)  
@@ -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 (e$B%j%S%8%g%se(B 13324)  
+++ compar.c (e$B:n6H%3%T!\<e(B)  
@@ -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 (e$B%j%S%8%g%se(B 13324)  
+++ bignum.c (e$B:n6H%3%T!\<e(B)  
@@ -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,66 @@  
#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);

```

- 

```
       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);

```

- }

- 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 +116,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 +127,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 +144,19 @@  
static VALUE  
bigtrunc(VALUE x)  
{

- long len = RBIGNUM(x)-\>len;

- long len = RBIGNUM\_LEN(x);  
BDIGIT \*ds = BDIGITS(x);

- 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 (RBIGNUM(x)->sign) {

```

- 

```
 if (RBIGNUM_SIGN(x)) {

```

if (POSFIXABLE(num)) return LONG2FIX(num);  
}  
else {  
@@ -158,7 +208,7 @@

i = DIGSPERLONG;  
while (–i && !digits[i]) ;

- RBIGNUM(big)-\>len = i+1;

- RBIGNUM\_SET\_LEN(big, i+1);  
return big;  
}

@@ -174,7 +224,7 @@  
}  
big = rb\_uint2big(n);  
if (neg) {

- RBIGNUM(big)-\>sign = 0;

- RBIGNUM\_SET\_SIGN(big, 0);  
}  
return big;  
}  
@@ -205,7 +255,7 @@  
q = FIX2LONG(val);  
}  
else {

- long len = RBIGNUM(val)-\>len;

- long len = RBIGNUM\_LEN(val);  
BDIGIT \*ds;

- if (!RBIGNUM(val)-\>sign) q = -q;

- if (!RBIGNUM\_SIGN(val)) q = -q;  
}  
memcpy(buf, (char\*)&q, SIZEOF\_LONG\_LONG);  
}  
@@ -253,10 +303,10 @@

- RBIGNUM(big)-\>len = i+1;

- RBIGNUM\_SET\_LEN(big, i+1);

- RBIGNUM(big)-\>sign = 0;

- RBIGNUM\_SET\_SIGN(big, 0);  
}  
return bignorm(big);  
}  
@@ -275,12 +325,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 +351,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 +499,7 @@  
}  
else {  
VALUE big = rb\_uint2big(val);

- 

```
 RBIGNUM(big)->sign = sign;

```

- 

```
 RBIGNUM_SET_SIGN(big, sign);
 return bignorm(big);

```

}  
}  
@@ -546,7 +596,7 @@

i = DIGSPERLL;  
while (i-- && !digits[i]) ;

- RBIGNUM(big)-\>len = i+1;

- RBIGNUM\_SET\_LEN(big, i+1);  
return big;  
}

@@ -562,7 +612,7 @@  
}  
big = rb\_ull2big(n);  
if (neg) {

- RBIGNUM(big)-\>sign = 0;

- RBIGNUM\_SET\_SIGN(big, 0);  
}  
return big;  
}  
@@ -722,7 +772,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 +809,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 +818,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);

- ptr[0] = RBIGNUM(x)-\>sign ? ‘+’ : ‘-’;

- ptr[0] = RBIGNUM\_SIGN(x) ? ‘+’ : ‘-’;

- 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 +970,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 +992,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 +1003,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 +1018,10 @@  
VALUE num = big2ulong(x, “long”, Qtrue);

- (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 +1030,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 +1050,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 +1059,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 +1111,13 @@  
big2dbl(VALUE x)  
{  
double d = 0.0;

- long i = RBIGNUM(x)-\>len;

- long i = RBIGNUM\_LEN(x);  
BDIGIT \*ds = BDIGITS(x);

- if (!RBIGNUM(x)-\>sign) d = -d;

- if (!RBIGNUM\_SIGN(x)) d = -d;  
return d;  
}

@@ -1111,7 +1161,7 @@  
VALUE  
rb\_big\_cmp(VALUE x, VALUE y)  
{

- long xlen = RBIGNUM(x)-\>len;

- long xlen = RBIGNUM\_LEN(x);

- 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);

- (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 +1224,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 +1245,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 +1263,7 @@  
{  
VALUE z = rb\_big\_clone(x);

- RBIGNUM(z)-\>sign = !RBIGNUM(x)-\>sign;

- RBIGNUM\_SET\_SIGN(z, !RBIGNUM\_SIGN(x));

- 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);

- long i = RBIGNUM(x)-\>len;

- long i = RBIGNUM\_LEN(x);

- 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 +1325,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 +1353,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 +1462,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 +1499,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 +1525,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 +1604,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 +1619,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 +1630,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 +1817,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 +1826,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 +1862,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 +1877,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 +1943,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 +1986,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);

- if (!RBIGNUM(z)-\>sign) get2comp(z);

- if (!RBIGNUM\_SIGN(z)) get2comp(z);  
return bignorm(z);  
}

@@ -1988,29 +2042,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);

- if (!RBIGNUM(z)-\>sign) get2comp(z);

- if (!RBIGNUM\_SIGN(z)) get2comp(z);

- 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);

- if (!RBIGNUM(z)-\>sign) get2comp(z);

- if (!RBIGNUM\_SIGN(z)) get2comp(z);

- 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 +2171,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 +2196,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 +2235,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 +2263,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 +2289,7 @@  
zds[j] = BIGLO(num);  
num = BIGUP(xds[i]);  
}

- if (!RBIGNUM(x)-\>sign) {

- if (!RBIGNUM\_SIGN(x)) {  
get2comp(z);  
}  
return bignorm(z);  
@@ -2269,11 +2323,11 @@  
long i, s1, s2;

- 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 +2339,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 +2367,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 +2404,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 +2426,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 (e$B%j%S%8%g%se(B 13324)  
+++ marshal.c (e$B:n6H%3%T!\<e(B)  
@@ -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);

- 

```
 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 (e$B%j%S%8%g%se(B 13324)  
+++ test/ruby/test\_integer.rb (e$B:n6H%3%T!\<e(B)  
@@ -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 (e$B%j%S%8%g%se(B 13324)  
+++ random.c (e$B:n6H%3%T!\<e(B)  
@@ -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;

- 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)) {
