00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "ruby/util.h"
00014
00015 #include <math.h>
00016 #include <float.h>
00017 #include <ctype.h>
00018 #ifdef HAVE_IEEEFP_H
00019 #include <ieeefp.h>
00020 #endif
00021 #include <assert.h>
00022
00023 VALUE rb_cBignum;
00024
00025 #if defined __MINGW32__
00026 #define USHORT _USHORT
00027 #endif
00028
00029 #define BDIGITS(x) (RBIGNUM_DIGITS(x))
00030 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
00031 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
00032 #define DIGSPERLONG (SIZEOF_LONG/SIZEOF_BDIGITS)
00033 #if HAVE_LONG_LONG
00034 # define DIGSPERLL (SIZEOF_LONG_LONG/SIZEOF_BDIGITS)
00035 #endif
00036 #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
00037 #define BIGDN(x) RSHIFT(x,BITSPERDIG)
00038 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
00039 #define BDIGMAX ((BDIGIT)-1)
00040
00041 #define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || \
00042 (BDIGITS(x)[0] == 0 && \
00043 (RBIGNUM_LEN(x) == 1 || bigzero_p(x))))
00044
00045 static int
00046 bigzero_p(VALUE x)
00047 {
00048 long i;
00049 BDIGIT *ds = BDIGITS(x);
00050
00051 for (i = RBIGNUM_LEN(x) - 1; 0 <= i; i--) {
00052 if (ds[i]) return 0;
00053 }
00054 return 1;
00055 }
00056
00057 int
00058 rb_bigzero_p(VALUE x)
00059 {
00060 return BIGZEROP(x);
00061 }
00062
00063 int
00064 rb_cmpint(VALUE val, VALUE a, VALUE b)
00065 {
00066 if (NIL_P(val)) {
00067 rb_cmperr(a, b);
00068 }
00069 if (FIXNUM_P(val)) {
00070 long l = FIX2LONG(val);
00071 if (l > 0) return 1;
00072 if (l < 0) return -1;
00073 return 0;
00074 }
00075 if (TYPE(val) == T_BIGNUM) {
00076 if (BIGZEROP(val)) return 0;
00077 if (RBIGNUM_SIGN(val)) return 1;
00078 return -1;
00079 }
00080 if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
00081 if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
00082 return 0;
00083 }
00084
00085 #define RBIGNUM_SET_LEN(b,l) \
00086 ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
00087 (void)(RBASIC(b)->flags = \
00088 (RBASIC(b)->flags & ~RBIGNUM_EMBED_LEN_MASK) | \
00089 ((l) << RBIGNUM_EMBED_LEN_SHIFT)) : \
00090 (void)(RBIGNUM(b)->as.heap.len = (l)))
00091
00092 static void
00093 rb_big_realloc(VALUE big, long len)
00094 {
00095 BDIGIT *ds;
00096 if (RBASIC(big)->flags & RBIGNUM_EMBED_FLAG) {
00097 if (RBIGNUM_EMBED_LEN_MAX < len) {
00098 ds = ALLOC_N(BDIGIT, len);
00099 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, RBIGNUM_EMBED_LEN_MAX);
00100 RBIGNUM(big)->as.heap.len = RBIGNUM_LEN(big);
00101 RBIGNUM(big)->as.heap.digits = ds;
00102 RBASIC(big)->flags &= ~RBIGNUM_EMBED_FLAG;
00103 }
00104 }
00105 else {
00106 if (len <= RBIGNUM_EMBED_LEN_MAX) {
00107 ds = RBIGNUM(big)->as.heap.digits;
00108 RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
00109 RBIGNUM_SET_LEN(big, len);
00110 if (ds) {
00111 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
00112 xfree(ds);
00113 }
00114 }
00115 else {
00116 if (RBIGNUM_LEN(big) == 0) {
00117 RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
00118 }
00119 else {
00120 REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
00121 }
00122 }
00123 }
00124 }
00125
00126 void
00127 rb_big_resize(VALUE big, long len)
00128 {
00129 rb_big_realloc(big, len);
00130 RBIGNUM_SET_LEN(big, len);
00131 }
00132
00133 static VALUE
00134 bignew_1(VALUE klass, long len, int sign)
00135 {
00136 NEWOBJ(big, struct RBignum);
00137 OBJSETUP(big, klass, T_BIGNUM);
00138 RBIGNUM_SET_SIGN(big, sign?1:0);
00139 if (len <= RBIGNUM_EMBED_LEN_MAX) {
00140 RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
00141 RBIGNUM_SET_LEN(big, len);
00142 }
00143 else {
00144 RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
00145 RBIGNUM(big)->as.heap.len = len;
00146 }
00147
00148 return (VALUE)big;
00149 }
00150
00151 #define bignew(len,sign) bignew_1(rb_cBignum,len,sign)
00152
00153 VALUE
00154 rb_big_new(long len, int sign)
00155 {
00156 return bignew(len, sign != 0);
00157 }
00158
00159 VALUE
00160 rb_big_clone(VALUE x)
00161 {
00162 long len = RBIGNUM_LEN(x);
00163 VALUE z = bignew_1(CLASS_OF(x), len, RBIGNUM_SIGN(x));
00164
00165 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len);
00166 return z;
00167 }
00168
00169
00170 static void
00171 get2comp(VALUE x)
00172 {
00173 long i = RBIGNUM_LEN(x);
00174 BDIGIT *ds = BDIGITS(x);
00175 BDIGIT_DBL num;
00176
00177 if (!i) return;
00178 while (i--) ds[i] = ~ds[i];
00179 i = 0; num = 1;
00180 do {
00181 num += ds[i];
00182 ds[i++] = BIGLO(num);
00183 num = BIGDN(num);
00184 } while (i < RBIGNUM_LEN(x));
00185 if (num != 0) {
00186 rb_big_resize(x, RBIGNUM_LEN(x)+1);
00187 ds = BDIGITS(x);
00188 ds[RBIGNUM_LEN(x)-1] = 1;
00189 }
00190 }
00191
00192 void
00193 rb_big_2comp(VALUE x)
00194 {
00195 get2comp(x);
00196 }
00197
00198 static inline VALUE
00199 bigtrunc(VALUE x)
00200 {
00201 long len = RBIGNUM_LEN(x);
00202 BDIGIT *ds = BDIGITS(x);
00203
00204 if (len == 0) return x;
00205 while (--len && !ds[len]);
00206 if (RBIGNUM_LEN(x) > len+1) {
00207 rb_big_resize(x, len+1);
00208 }
00209 return x;
00210 }
00211
00212 static inline VALUE
00213 bigfixize(VALUE x)
00214 {
00215 long len = RBIGNUM_LEN(x);
00216 BDIGIT *ds = BDIGITS(x);
00217
00218 if (len == 0) return INT2FIX(0);
00219 if ((size_t)(len*SIZEOF_BDIGITS) <= sizeof(long)) {
00220 long num = 0;
00221 #if 2*SIZEOF_BDIGITS > SIZEOF_LONG
00222 num = (long)ds[0];
00223 #else
00224 while (len--) {
00225 num = (long)(BIGUP(num) + ds[len]);
00226 }
00227 #endif
00228 if (num >= 0) {
00229 if (RBIGNUM_SIGN(x)) {
00230 if (POSFIXABLE(num)) return LONG2FIX(num);
00231 }
00232 else {
00233 if (NEGFIXABLE(-num)) return LONG2FIX(-num);
00234 }
00235 }
00236 }
00237 return x;
00238 }
00239
00240 static VALUE
00241 bignorm(VALUE x)
00242 {
00243 if (!FIXNUM_P(x) && TYPE(x) == T_BIGNUM) {
00244 x = bigfixize(bigtrunc(x));
00245 }
00246 return x;
00247 }
00248
00249 VALUE
00250 rb_big_norm(VALUE x)
00251 {
00252 return bignorm(x);
00253 }
00254
00255 VALUE
00256 rb_uint2big(VALUE n)
00257 {
00258 BDIGIT_DBL num = n;
00259 long i = 0;
00260 BDIGIT *digits;
00261 VALUE big;
00262
00263 big = bignew(DIGSPERLONG, 1);
00264 digits = BDIGITS(big);
00265 while (i < DIGSPERLONG) {
00266 digits[i++] = BIGLO(num);
00267 num = BIGDN(num);
00268 }
00269
00270 i = DIGSPERLONG;
00271 while (--i && !digits[i]) ;
00272 RBIGNUM_SET_LEN(big, i+1);
00273 return big;
00274 }
00275
00276 VALUE
00277 rb_int2big(SIGNED_VALUE n)
00278 {
00279 long neg = 0;
00280 VALUE big;
00281
00282 if (n < 0) {
00283 n = -n;
00284 neg = 1;
00285 }
00286 big = rb_uint2big(n);
00287 if (neg) {
00288 RBIGNUM_SET_SIGN(big, 0);
00289 }
00290 return big;
00291 }
00292
00293 VALUE
00294 rb_uint2inum(VALUE n)
00295 {
00296 if (POSFIXABLE(n)) return LONG2FIX(n);
00297 return rb_uint2big(n);
00298 }
00299
00300 VALUE
00301 rb_int2inum(SIGNED_VALUE n)
00302 {
00303 if (FIXABLE(n)) return LONG2FIX(n);
00304 return rb_int2big(n);
00305 }
00306
00307 #if SIZEOF_LONG % SIZEOF_BDIGITS != 0
00308 # error unexpected SIZEOF_LONG : SIZEOF_BDIGITS ratio
00309 #endif
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 void
00325 rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
00326 {
00327 val = rb_to_int(val);
00328 if (num_longs == 0)
00329 return;
00330 if (FIXNUM_P(val)) {
00331 long i;
00332 long tmp = FIX2LONG(val);
00333 buf[0] = (unsigned long)tmp;
00334 tmp = tmp < 0 ? ~0L : 0;
00335 for (i = 1; i < num_longs; i++)
00336 buf[i] = (unsigned long)tmp;
00337 return;
00338 }
00339 else {
00340 long len = RBIGNUM_LEN(val);
00341 BDIGIT *ds = BDIGITS(val), *dend = ds + len;
00342 long i, j;
00343 for (i = 0; i < num_longs && ds < dend; i++) {
00344 unsigned long l = 0;
00345 for (j = 0; j < DIGSPERLONG && ds < dend; j++, ds++) {
00346 l |= ((unsigned long)*ds << (j * BITSPERDIG));
00347 }
00348 buf[i] = l;
00349 }
00350 for (; i < num_longs; i++)
00351 buf[i] = 0;
00352 if (RBIGNUM_NEGATIVE_P(val)) {
00353 for (i = 0; i < num_longs; i++) {
00354 buf[i] = ~buf[i];
00355 }
00356 for (i = 0; i < num_longs; i++) {
00357 buf[i]++;
00358 if (buf[i] != 0)
00359 return;
00360 }
00361 }
00362 }
00363 }
00364
00365
00366 VALUE
00367 rb_big_unpack(unsigned long *buf, long num_longs)
00368 {
00369 while (2 <= num_longs) {
00370 if (buf[num_longs-1] == 0 && (long)buf[num_longs-2] >= 0)
00371 num_longs--;
00372 else if (buf[num_longs-1] == ~0UL && (long)buf[num_longs-2] < 0)
00373 num_longs--;
00374 else
00375 break;
00376 }
00377 if (num_longs == 0)
00378 return INT2FIX(0);
00379 else if (num_longs == 1)
00380 return LONG2NUM((long)buf[0]);
00381 else {
00382 VALUE big;
00383 BDIGIT *ds;
00384 long len = num_longs * DIGSPERLONG;
00385 long i;
00386 big = bignew(len, 1);
00387 ds = BDIGITS(big);
00388 for (i = 0; i < num_longs; i++) {
00389 unsigned long d = buf[i];
00390 #if SIZEOF_LONG == SIZEOF_BDIGITS
00391 *ds++ = d;
00392 #else
00393 int j;
00394 for (j = 0; j < DIGSPERLONG; j++) {
00395 *ds++ = BIGLO(d);
00396 d = BIGDN(d);
00397 }
00398 #endif
00399 }
00400 if ((long)buf[num_longs-1] < 0) {
00401 get2comp(big);
00402 RBIGNUM_SET_SIGN(big, 0);
00403 }
00404 return bignorm(big);
00405 }
00406 }
00407
00408 #define QUAD_SIZE 8
00409
00410 #if SIZEOF_LONG_LONG == QUAD_SIZE && SIZEOF_BDIGITS*2 == SIZEOF_LONG_LONG
00411
00412 void
00413 rb_quad_pack(char *buf, VALUE val)
00414 {
00415 LONG_LONG q;
00416
00417 val = rb_to_int(val);
00418 if (FIXNUM_P(val)) {
00419 q = FIX2LONG(val);
00420 }
00421 else {
00422 long len = RBIGNUM_LEN(val);
00423 BDIGIT *ds;
00424
00425 if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) {
00426 len = SIZEOF_LONG_LONG/SIZEOF_BDIGITS;
00427 }
00428 ds = BDIGITS(val);
00429 q = 0;
00430 while (len--) {
00431 q = BIGUP(q);
00432 q += ds[len];
00433 }
00434 if (!RBIGNUM_SIGN(val)) q = -q;
00435 }
00436 memcpy(buf, (char*)&q, SIZEOF_LONG_LONG);
00437 }
00438
00439 VALUE
00440 rb_quad_unpack(const char *buf, int sign)
00441 {
00442 unsigned LONG_LONG q;
00443 long neg = 0;
00444 long i;
00445 BDIGIT *digits;
00446 VALUE big;
00447
00448 memcpy(&q, buf, SIZEOF_LONG_LONG);
00449 if (sign) {
00450 if (FIXABLE((LONG_LONG)q)) return LONG2FIX((LONG_LONG)q);
00451 if ((LONG_LONG)q < 0) {
00452 q = -(LONG_LONG)q;
00453 neg = 1;
00454 }
00455 }
00456 else {
00457 if (POSFIXABLE(q)) return LONG2FIX(q);
00458 }
00459
00460 i = 0;
00461 big = bignew(DIGSPERLL, 1);
00462 digits = BDIGITS(big);
00463 while (i < DIGSPERLL) {
00464 digits[i++] = BIGLO(q);
00465 q = BIGDN(q);
00466 }
00467
00468 i = DIGSPERLL;
00469 while (i-- && !digits[i]) ;
00470 RBIGNUM_SET_LEN(big, i+1);
00471
00472 if (neg) {
00473 RBIGNUM_SET_SIGN(big, 0);
00474 }
00475 return bignorm(big);
00476 }
00477
00478 #else
00479
00480 static int
00481 quad_buf_complement(char *buf, size_t len)
00482 {
00483 size_t i;
00484 for (i = 0; i < len; i++)
00485 buf[i] = ~buf[i];
00486 for (i = 0; i < len; i++) {
00487 buf[i]++;
00488 if (buf[i] != 0)
00489 return 0;
00490 }
00491 return 1;
00492 }
00493
00494 void
00495 rb_quad_pack(char *buf, VALUE val)
00496 {
00497 long len;
00498
00499 memset(buf, 0, QUAD_SIZE);
00500 val = rb_to_int(val);
00501 if (FIXNUM_P(val)) {
00502 val = rb_int2big(FIX2LONG(val));
00503 }
00504 len = RBIGNUM_LEN(val) * SIZEOF_BDIGITS;
00505 if (len > QUAD_SIZE) {
00506 len = QUAD_SIZE;
00507 }
00508 memcpy(buf, (char*)BDIGITS(val), len);
00509 if (RBIGNUM_NEGATIVE_P(val)) {
00510 quad_buf_complement(buf, QUAD_SIZE);
00511 }
00512 }
00513
00514 #define BNEG(b) (RSHIFT(((BDIGIT*)b)[QUAD_SIZE/SIZEOF_BDIGITS-1],BITSPERDIG-1) != 0)
00515
00516 VALUE
00517 rb_quad_unpack(const char *buf, int sign)
00518 {
00519 VALUE big = bignew(QUAD_SIZE/SIZEOF_BDIGITS, 1);
00520
00521 memcpy((char*)BDIGITS(big), buf, QUAD_SIZE);
00522 if (sign && BNEG(buf)) {
00523 char *tmp = (char*)BDIGITS(big);
00524
00525 RBIGNUM_SET_SIGN(big, 0);
00526 quad_buf_complement(tmp, QUAD_SIZE);
00527 }
00528
00529 return bignorm(big);
00530 }
00531
00532 #endif
00533
00534 VALUE
00535 rb_cstr_to_inum(const char *str, int base, int badcheck)
00536 {
00537 const char *s = str;
00538 char *end;
00539 char sign = 1, nondigit = 0;
00540 int c;
00541 BDIGIT_DBL num;
00542 long len, blen = 1;
00543 long i;
00544 VALUE z;
00545 BDIGIT *zds;
00546
00547 #undef ISDIGIT
00548 #define ISDIGIT(c) ('0' <= (c) && (c) <= '9')
00549 #define conv_digit(c) \
00550 (!ISASCII(c) ? -1 : \
00551 ISDIGIT(c) ? ((c) - '0') : \
00552 ISLOWER(c) ? ((c) - 'a' + 10) : \
00553 ISUPPER(c) ? ((c) - 'A' + 10) : \
00554 -1)
00555
00556 if (!str) {
00557 if (badcheck) goto bad;
00558 return INT2FIX(0);
00559 }
00560 while (ISSPACE(*str)) str++;
00561
00562 if (str[0] == '+') {
00563 str++;
00564 }
00565 else if (str[0] == '-') {
00566 str++;
00567 sign = 0;
00568 }
00569 if (str[0] == '+' || str[0] == '-') {
00570 if (badcheck) goto bad;
00571 return INT2FIX(0);
00572 }
00573 if (base <= 0) {
00574 if (str[0] == '0') {
00575 switch (str[1]) {
00576 case 'x': case 'X':
00577 base = 16;
00578 break;
00579 case 'b': case 'B':
00580 base = 2;
00581 break;
00582 case 'o': case 'O':
00583 base = 8;
00584 break;
00585 case 'd': case 'D':
00586 base = 10;
00587 break;
00588 default:
00589 base = 8;
00590 }
00591 }
00592 else if (base < -1) {
00593 base = -base;
00594 }
00595 else {
00596 base = 10;
00597 }
00598 }
00599 switch (base) {
00600 case 2:
00601 len = 1;
00602 if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
00603 str += 2;
00604 }
00605 break;
00606 case 3:
00607 len = 2;
00608 break;
00609 case 8:
00610 if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
00611 str += 2;
00612 }
00613 case 4: case 5: case 6: case 7:
00614 len = 3;
00615 break;
00616 case 10:
00617 if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
00618 str += 2;
00619 }
00620 case 9: case 11: case 12: case 13: case 14: case 15:
00621 len = 4;
00622 break;
00623 case 16:
00624 len = 4;
00625 if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
00626 str += 2;
00627 }
00628 break;
00629 default:
00630 if (base < 2 || 36 < base) {
00631 rb_raise(rb_eArgError, "invalid radix %d", base);
00632 }
00633 if (base <= 32) {
00634 len = 5;
00635 }
00636 else {
00637 len = 6;
00638 }
00639 break;
00640 }
00641 if (*str == '0') {
00642 int us = 0;
00643 while ((c = *++str) == '0' || c == '_') {
00644 if (c == '_') {
00645 if (++us >= 2)
00646 break;
00647 } else
00648 us = 0;
00649 }
00650 if (!(c = *str) || ISSPACE(c)) --str;
00651 }
00652 c = *str;
00653 c = conv_digit(c);
00654 if (c < 0 || c >= base) {
00655 if (badcheck) goto bad;
00656 return INT2FIX(0);
00657 }
00658 len *= strlen(str)*sizeof(char);
00659
00660 if ((size_t)len <= (sizeof(long)*CHAR_BIT)) {
00661 unsigned long val = STRTOUL(str, &end, base);
00662
00663 if (str < end && *end == '_') goto bigparse;
00664 if (badcheck) {
00665 if (end == str) goto bad;
00666 while (*end && ISSPACE(*end)) end++;
00667 if (*end) goto bad;
00668 }
00669
00670 if (POSFIXABLE(val)) {
00671 if (sign) return LONG2FIX(val);
00672 else {
00673 long result = -(long)val;
00674 return LONG2FIX(result);
00675 }
00676 }
00677 else {
00678 VALUE big = rb_uint2big(val);
00679 RBIGNUM_SET_SIGN(big, sign);
00680 return bignorm(big);
00681 }
00682 }
00683 bigparse:
00684 len = (len/BITSPERDIG)+1;
00685 if (badcheck && *str == '_') goto bad;
00686
00687 z = bignew(len, sign);
00688 zds = BDIGITS(z);
00689 for (i=len;i--;) zds[i]=0;
00690 while ((c = *str++) != 0) {
00691 if (c == '_') {
00692 if (nondigit) {
00693 if (badcheck) goto bad;
00694 break;
00695 }
00696 nondigit = c;
00697 continue;
00698 }
00699 else if ((c = conv_digit(c)) < 0) {
00700 break;
00701 }
00702 if (c >= base) break;
00703 nondigit = 0;
00704 i = 0;
00705 num = c;
00706 for (;;) {
00707 while (i<blen) {
00708 num += (BDIGIT_DBL)zds[i]*base;
00709 zds[i++] = BIGLO(num);
00710 num = BIGDN(num);
00711 }
00712 if (num) {
00713 blen++;
00714 continue;
00715 }
00716 break;
00717 }
00718 }
00719 if (badcheck) {
00720 str--;
00721 if (s+1 < str && str[-1] == '_') goto bad;
00722 while (*str && ISSPACE(*str)) str++;
00723 if (*str) {
00724 bad:
00725 rb_invalid_str(s, "Integer()");
00726 }
00727 }
00728
00729 return bignorm(z);
00730 }
00731
00732 VALUE
00733 rb_str_to_inum(VALUE str, int base, int badcheck)
00734 {
00735 char *s;
00736 long len;
00737
00738 StringValue(str);
00739 if (badcheck) {
00740 s = StringValueCStr(str);
00741 }
00742 else {
00743 s = RSTRING_PTR(str);
00744 }
00745 if (s) {
00746 len = RSTRING_LEN(str);
00747 if (s[len]) {
00748 char *p = ALLOCA_N(char, len+1);
00749
00750 MEMCPY(p, s, char, len);
00751 p[len] = '\0';
00752 s = p;
00753 }
00754 }
00755 return rb_cstr_to_inum(s, base, badcheck);
00756 }
00757
00758 #if HAVE_LONG_LONG
00759
00760 static VALUE
00761 rb_ull2big(unsigned LONG_LONG n)
00762 {
00763 BDIGIT_DBL num = n;
00764 long i = 0;
00765 BDIGIT *digits;
00766 VALUE big;
00767
00768 big = bignew(DIGSPERLL, 1);
00769 digits = BDIGITS(big);
00770 while (i < DIGSPERLL) {
00771 digits[i++] = BIGLO(num);
00772 num = BIGDN(num);
00773 }
00774
00775 i = DIGSPERLL;
00776 while (i-- && !digits[i]) ;
00777 RBIGNUM_SET_LEN(big, i+1);
00778 return big;
00779 }
00780
00781 static VALUE
00782 rb_ll2big(LONG_LONG n)
00783 {
00784 long neg = 0;
00785 VALUE big;
00786
00787 if (n < 0) {
00788 n = -n;
00789 neg = 1;
00790 }
00791 big = rb_ull2big(n);
00792 if (neg) {
00793 RBIGNUM_SET_SIGN(big, 0);
00794 }
00795 return big;
00796 }
00797
00798 VALUE
00799 rb_ull2inum(unsigned LONG_LONG n)
00800 {
00801 if (POSFIXABLE(n)) return LONG2FIX(n);
00802 return rb_ull2big(n);
00803 }
00804
00805 VALUE
00806 rb_ll2inum(LONG_LONG n)
00807 {
00808 if (FIXABLE(n)) return LONG2FIX(n);
00809 return rb_ll2big(n);
00810 }
00811
00812 #endif
00813
00814 VALUE
00815 rb_cstr2inum(const char *str, int base)
00816 {
00817 return rb_cstr_to_inum(str, base, base==0);
00818 }
00819
00820 VALUE
00821 rb_str2inum(VALUE str, int base)
00822 {
00823 return rb_str_to_inum(str, base, base==0);
00824 }
00825
00826 const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
00827
00828 static VALUE bigsqr(VALUE x);
00829 static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp);
00830
00831 #define POW2_P(x) (((x)&((x)-1))==0)
00832
00833 static inline int
00834 ones(register unsigned long x)
00835 {
00836 #if SIZEOF_LONG == 8
00837 # define MASK_55 0x5555555555555555UL
00838 # define MASK_33 0x3333333333333333UL
00839 # define MASK_0f 0x0f0f0f0f0f0f0f0fUL
00840 #else
00841 # define MASK_55 0x55555555UL
00842 # define MASK_33 0x33333333UL
00843 # define MASK_0f 0x0f0f0f0fUL
00844 #endif
00845 x -= (x >> 1) & MASK_55;
00846 x = ((x >> 2) & MASK_33) + (x & MASK_33);
00847 x = ((x >> 4) + x) & MASK_0f;
00848 x += (x >> 8);
00849 x += (x >> 16);
00850 #if SIZEOF_LONG == 8
00851 x += (x >> 32);
00852 #endif
00853 return (int)(x & 0x7f);
00854 #undef MASK_0f
00855 #undef MASK_33
00856 #undef MASK_55
00857 }
00858
00859 static inline unsigned long
00860 next_pow2(register unsigned long x)
00861 {
00862 x |= x >> 1;
00863 x |= x >> 2;
00864 x |= x >> 4;
00865 x |= x >> 8;
00866 x |= x >> 16;
00867 #if SIZEOF_LONG == 8
00868 x |= x >> 32;
00869 #endif
00870 return x + 1;
00871 }
00872
00873 static inline int
00874 floor_log2(register unsigned long x)
00875 {
00876 x |= x >> 1;
00877 x |= x >> 2;
00878 x |= x >> 4;
00879 x |= x >> 8;
00880 x |= x >> 16;
00881 #if SIZEOF_LONG == 8
00882 x |= x >> 32;
00883 #endif
00884 return (int)ones(x) - 1;
00885 }
00886
00887 static inline int
00888 ceil_log2(register unsigned long x)
00889 {
00890 return floor_log2(x) + !POW2_P(x);
00891 }
00892
00893 #define LOG2_KARATSUBA_DIGITS 7
00894 #define KARATSUBA_DIGITS (1L<<LOG2_KARATSUBA_DIGITS)
00895 #define MAX_BIG2STR_TABLE_ENTRIES 64
00896
00897 static VALUE big2str_power_cache[35][MAX_BIG2STR_TABLE_ENTRIES];
00898
00899 static void
00900 power_cache_init(void)
00901 {
00902 int i, j;
00903 for (i = 0; i < 35; ++i) {
00904 for (j = 0; j < MAX_BIG2STR_TABLE_ENTRIES; ++j) {
00905 big2str_power_cache[i][j] = Qnil;
00906 }
00907 }
00908 }
00909
00910 static inline VALUE
00911 power_cache_get_power0(int base, int i)
00912 {
00913 if (NIL_P(big2str_power_cache[base - 2][i])) {
00914 big2str_power_cache[base - 2][i] =
00915 i == 0 ? rb_big_pow(rb_int2big(base), INT2FIX(KARATSUBA_DIGITS))
00916 : bigsqr(power_cache_get_power0(base, i - 1));
00917 rb_gc_register_mark_object(big2str_power_cache[base - 2][i]);
00918 }
00919 return big2str_power_cache[base - 2][i];
00920 }
00921
00922 static VALUE
00923 power_cache_get_power(int base, long n1, long* m1)
00924 {
00925 int i, m;
00926 long j;
00927 VALUE t;
00928
00929 if (n1 <= KARATSUBA_DIGITS)
00930 rb_bug("n1 > KARATSUBA_DIGITS");
00931
00932 m = ceil_log2(n1);
00933 if (m1) *m1 = 1 << m;
00934 i = m - LOG2_KARATSUBA_DIGITS;
00935 if (i >= MAX_BIG2STR_TABLE_ENTRIES)
00936 i = MAX_BIG2STR_TABLE_ENTRIES - 1;
00937 t = power_cache_get_power0(base, i);
00938
00939 j = KARATSUBA_DIGITS*(1 << i);
00940 while (n1 > j) {
00941 t = bigsqr(t);
00942 j *= 2;
00943 }
00944 return t;
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960 static long
00961 big2str_find_n1(VALUE x, int base)
00962 {
00963 static const double log_2[] = {
00964 1.0, 1.58496250072116, 2.0,
00965 2.32192809488736, 2.58496250072116, 2.8073549220576,
00966 3.0, 3.16992500144231, 3.32192809488736,
00967 3.4594316186373, 3.58496250072116, 3.70043971814109,
00968 3.8073549220576, 3.90689059560852, 4.0,
00969 4.08746284125034, 4.16992500144231, 4.24792751344359,
00970 4.32192809488736, 4.39231742277876, 4.4594316186373,
00971 4.52356195605701, 4.58496250072116, 4.64385618977472,
00972 4.70043971814109, 4.75488750216347, 4.8073549220576,
00973 4.85798099512757, 4.90689059560852, 4.95419631038688,
00974 5.0, 5.04439411935845, 5.08746284125034,
00975 5.12928301694497, 5.16992500144231
00976 };
00977 long bits;
00978
00979 if (base < 2 || 36 < base)
00980 rb_bug("invalid radix %d", base);
00981
00982 if (FIXNUM_P(x)) {
00983 bits = (SIZEOF_LONG*CHAR_BIT - 1)/2 + 1;
00984 }
00985 else if (BIGZEROP(x)) {
00986 return 0;
00987 }
00988 else if (RBIGNUM_LEN(x) >= LONG_MAX/BITSPERDIG) {
00989 rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
00990 }
00991 else {
00992 bits = BITSPERDIG*RBIGNUM_LEN(x);
00993 }
00994
00995 return (long)ceil(bits/log_2[base - 2]);
00996 }
00997
00998 static long
00999 big2str_orig(VALUE x, int base, char* ptr, long len, long hbase, int trim)
01000 {
01001 long i = RBIGNUM_LEN(x), j = len;
01002 BDIGIT* ds = BDIGITS(x);
01003
01004 while (i && j > 0) {
01005 long k = i;
01006 BDIGIT_DBL num = 0;
01007
01008 while (k--) {
01009 num = BIGUP(num) + ds[k];
01010 ds[k] = (BDIGIT)(num / hbase);
01011 num %= hbase;
01012 }
01013 if (trim && ds[i-1] == 0) i--;
01014 k = SIZEOF_BDIGITS;
01015 while (k--) {
01016 ptr[--j] = ruby_digitmap[num % base];
01017 num /= base;
01018 if (j <= 0) break;
01019 if (trim && i == 0 && num == 0) break;
01020 }
01021 }
01022 if (trim) {
01023 while (j < len && ptr[j] == '0') j++;
01024 MEMMOVE(ptr, ptr + j, char, len - j);
01025 len -= j;
01026 }
01027 return len;
01028 }
01029
01030 static long
01031 big2str_karatsuba(VALUE x, int base, char* ptr,
01032 long n1, long len, long hbase, int trim)
01033 {
01034 long lh, ll, m1;
01035 VALUE b, q, r;
01036
01037 if (BIGZEROP(x)) {
01038 if (trim) return 0;
01039 else {
01040 memset(ptr, '0', len);
01041 return len;
01042 }
01043 }
01044
01045 if (n1 <= KARATSUBA_DIGITS) {
01046 return big2str_orig(x, base, ptr, len, hbase, trim);
01047 }
01048
01049 b = power_cache_get_power(base, n1, &m1);
01050 bigdivmod(x, b, &q, &r);
01051 lh = big2str_karatsuba(q, base, ptr, (len - m1)/2,
01052 len - m1, hbase, trim);
01053 rb_big_resize(q, 0);
01054 ll = big2str_karatsuba(r, base, ptr + lh, m1/2,
01055 m1, hbase, !lh && trim);
01056 rb_big_resize(r, 0);
01057
01058 return lh + ll;
01059 }
01060
01061 VALUE
01062 rb_big2str0(VALUE x, int base, int trim)
01063 {
01064 int off;
01065 VALUE ss, xx;
01066 long n1, n2, len, hbase;
01067 char* ptr;
01068
01069 if (FIXNUM_P(x)) {
01070 return rb_fix2str(x, base);
01071 }
01072 if (BIGZEROP(x)) {
01073 return rb_usascii_str_new2("0");
01074 }
01075
01076 if (base < 2 || 36 < base)
01077 rb_raise(rb_eArgError, "invalid radix %d", base);
01078
01079 n2 = big2str_find_n1(x, base);
01080 n1 = (n2 + 1) / 2;
01081 ss = rb_usascii_str_new(0, n2 + 1);
01082 ptr = RSTRING_PTR(ss);
01083 ptr[0] = RBIGNUM_SIGN(x) ? '+' : '-';
01084
01085 hbase = base*base;
01086 #if SIZEOF_BDIGITS > 2
01087 hbase *= hbase;
01088 #endif
01089 off = !(trim && RBIGNUM_SIGN(x));
01090 xx = rb_big_clone(x);
01091 RBIGNUM_SET_SIGN(xx, 1);
01092 if (n1 <= KARATSUBA_DIGITS) {
01093 len = off + big2str_orig(xx, base, ptr + off, n2, hbase, trim);
01094 }
01095 else {
01096 len = off + big2str_karatsuba(xx, base, ptr + off, n1,
01097 n2, hbase, trim);
01098 }
01099 rb_big_resize(xx, 0);
01100
01101 ptr[len] = '\0';
01102 rb_str_resize(ss, len);
01103
01104 return ss;
01105 }
01106
01107 VALUE
01108 rb_big2str(VALUE x, int base)
01109 {
01110 return rb_big2str0(x, base, 1);
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 static VALUE
01128 rb_big_to_s(int argc, VALUE *argv, VALUE x)
01129 {
01130 int base;
01131
01132 if (argc == 0) base = 10;
01133 else {
01134 VALUE b;
01135
01136 rb_scan_args(argc, argv, "01", &b);
01137 base = NUM2INT(b);
01138 }
01139 return rb_big2str(x, base);
01140 }
01141
01142 static VALUE
01143 big2ulong(VALUE x, const char *type, int check)
01144 {
01145 long len = RBIGNUM_LEN(x);
01146 BDIGIT_DBL num;
01147 BDIGIT *ds;
01148
01149 if (len > DIGSPERLONG) {
01150 if (check)
01151 rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
01152 len = DIGSPERLONG;
01153 }
01154 ds = BDIGITS(x);
01155 num = 0;
01156 while (len--) {
01157 num = BIGUP(num);
01158 num += ds[len];
01159 }
01160 return (VALUE)num;
01161 }
01162
01163 VALUE
01164 rb_big2ulong_pack(VALUE x)
01165 {
01166 VALUE num = big2ulong(x, "unsigned long", FALSE);
01167 if (!RBIGNUM_SIGN(x)) {
01168 return (VALUE)(-(SIGNED_VALUE)num);
01169 }
01170 return num;
01171 }
01172
01173 VALUE
01174 rb_big2ulong(VALUE x)
01175 {
01176 VALUE num = big2ulong(x, "unsigned long", TRUE);
01177
01178 if (!RBIGNUM_SIGN(x)) {
01179 if ((SIGNED_VALUE)num < 0) {
01180 rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
01181 }
01182 return (VALUE)(-(SIGNED_VALUE)num);
01183 }
01184 return num;
01185 }
01186
01187 SIGNED_VALUE
01188 rb_big2long(VALUE x)
01189 {
01190 VALUE num = big2ulong(x, "long", TRUE);
01191
01192 if ((SIGNED_VALUE)num < 0 &&
01193 (RBIGNUM_SIGN(x) || (SIGNED_VALUE)num != LONG_MIN)) {
01194 rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
01195 }
01196 if (!RBIGNUM_SIGN(x)) return -(SIGNED_VALUE)num;
01197 return num;
01198 }
01199
01200 #if HAVE_LONG_LONG
01201
01202 static unsigned LONG_LONG
01203 big2ull(VALUE x, const char *type)
01204 {
01205 long len = RBIGNUM_LEN(x);
01206 BDIGIT_DBL num;
01207 BDIGIT *ds;
01208
01209 if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS)
01210 rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
01211 ds = BDIGITS(x);
01212 num = 0;
01213 while (len--) {
01214 num = BIGUP(num);
01215 num += ds[len];
01216 }
01217 return num;
01218 }
01219
01220 unsigned LONG_LONG
01221 rb_big2ull(VALUE x)
01222 {
01223 unsigned LONG_LONG num = big2ull(x, "unsigned long long");
01224
01225 if (!RBIGNUM_SIGN(x))
01226 return (VALUE)(-(SIGNED_VALUE)num);
01227 return num;
01228 }
01229
01230 LONG_LONG
01231 rb_big2ll(VALUE x)
01232 {
01233 unsigned LONG_LONG num = big2ull(x, "long long");
01234
01235 if ((LONG_LONG)num < 0 && (RBIGNUM_SIGN(x)
01236 || (LONG_LONG)num != LLONG_MIN)) {
01237 rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
01238 }
01239 if (!RBIGNUM_SIGN(x)) return -(LONG_LONG)num;
01240 return num;
01241 }
01242
01243 #endif
01244
01245 static VALUE
01246 dbl2big(double d)
01247 {
01248 long i = 0;
01249 BDIGIT c;
01250 BDIGIT *digits;
01251 VALUE z;
01252 double u = (d < 0)?-d:d;
01253
01254 if (isinf(d)) {
01255 rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
01256 }
01257 if (isnan(d)) {
01258 rb_raise(rb_eFloatDomainError, "NaN");
01259 }
01260
01261 while (!POSFIXABLE(u) || 0 != (long)u) {
01262 u /= (double)(BIGRAD);
01263 i++;
01264 }
01265 z = bignew(i, d>=0);
01266 digits = BDIGITS(z);
01267 while (i--) {
01268 u *= BIGRAD;
01269 c = (BDIGIT)u;
01270 u -= c;
01271 digits[i] = c;
01272 }
01273
01274 return z;
01275 }
01276
01277 VALUE
01278 rb_dbl2big(double d)
01279 {
01280 return bignorm(dbl2big(d));
01281 }
01282
01283 static int
01284 nlz(BDIGIT x)
01285 {
01286 BDIGIT y;
01287 int n = BITSPERDIG;
01288 #if BITSPERDIG > 64
01289 y = x >> 64; if (y) {n -= 64; x = y;}
01290 #endif
01291 #if BITSPERDIG > 32
01292 y = x >> 32; if (y) {n -= 32; x = y;}
01293 #endif
01294 #if BITSPERDIG > 16
01295 y = x >> 16; if (y) {n -= 16; x = y;}
01296 #endif
01297 y = x >> 8; if (y) {n -= 8; x = y;}
01298 y = x >> 4; if (y) {n -= 4; x = y;}
01299 y = x >> 2; if (y) {n -= 2; x = y;}
01300 y = x >> 1; if (y) {return n - 2;}
01301 return n - x;
01302 }
01303
01304 static double
01305 big2dbl(VALUE x)
01306 {
01307 double d = 0.0;
01308 long i = (bigtrunc(x), RBIGNUM_LEN(x)), lo = 0, bits;
01309 BDIGIT *ds = BDIGITS(x), dl;
01310
01311 if (i) {
01312 bits = i * BITSPERDIG - nlz(ds[i-1]);
01313 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
01314 d = HUGE_VAL;
01315 }
01316 else {
01317 if (bits > DBL_MANT_DIG+1)
01318 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
01319 else
01320 bits = 0;
01321 while (--i > lo) {
01322 d = ds[i] + BIGRAD*d;
01323 }
01324 dl = ds[i];
01325 if (bits && (dl & (1UL << (bits %= BITSPERDIG)))) {
01326 int carry = dl & ~(~(BDIGIT)0 << bits);
01327 if (!carry) {
01328 while (i-- > 0) {
01329 if ((carry = ds[i]) != 0) break;
01330 }
01331 }
01332 if (carry) {
01333 dl &= (BDIGIT)~0 << bits;
01334 dl += (BDIGIT)1 << bits;
01335 if (!dl) d += 1;
01336 }
01337 }
01338 d = dl + BIGRAD*d;
01339 if (lo) {
01340 if (lo > INT_MAX / BITSPERDIG)
01341 d = HUGE_VAL;
01342 else if (lo < INT_MIN / BITSPERDIG)
01343 d = 0.0;
01344 else
01345 d = ldexp(d, (int)(lo * BITSPERDIG));
01346 }
01347 }
01348 }
01349 if (!RBIGNUM_SIGN(x)) d = -d;
01350 return d;
01351 }
01352
01353 double
01354 rb_big2dbl(VALUE x)
01355 {
01356 double d = big2dbl(x);
01357
01358 if (isinf(d)) {
01359 rb_warning("Bignum out of Float range");
01360 if (d < 0.0)
01361 d = -HUGE_VAL;
01362 else
01363 d = HUGE_VAL;
01364 }
01365 return d;
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377 static VALUE
01378 rb_big_to_f(VALUE x)
01379 {
01380 return DBL2NUM(rb_big2dbl(x));
01381 }
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 VALUE
01394 rb_big_cmp(VALUE x, VALUE y)
01395 {
01396 long xlen = RBIGNUM_LEN(x);
01397 BDIGIT *xds, *yds;
01398
01399 switch (TYPE(y)) {
01400 case T_FIXNUM:
01401 y = rb_int2big(FIX2LONG(y));
01402 break;
01403
01404 case T_BIGNUM:
01405 break;
01406
01407 case T_FLOAT:
01408 {
01409 double a = RFLOAT_VALUE(y);
01410
01411 if (isinf(a)) {
01412 if (a > 0.0) return INT2FIX(-1);
01413 else return INT2FIX(1);
01414 }
01415 return rb_dbl_cmp(rb_big2dbl(x), a);
01416 }
01417
01418 default:
01419 return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
01420 }
01421
01422 if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1);
01423 if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1);
01424 if (xlen < RBIGNUM_LEN(y))
01425 return (RBIGNUM_SIGN(x)) ? INT2FIX(-1) : INT2FIX(1);
01426 if (xlen > RBIGNUM_LEN(y))
01427 return (RBIGNUM_SIGN(x)) ? INT2FIX(1) : INT2FIX(-1);
01428
01429 xds = BDIGITS(x);
01430 yds = BDIGITS(y);
01431
01432 while(xlen-- && (xds[xlen]==yds[xlen]));
01433 if (-1 == xlen) return INT2FIX(0);
01434 return (xds[xlen] > yds[xlen]) ?
01435 (RBIGNUM_SIGN(x) ? INT2FIX(1) : INT2FIX(-1)) :
01436 (RBIGNUM_SIGN(x) ? INT2FIX(-1) : INT2FIX(1));
01437 }
01438
01439 static VALUE
01440 big_op(VALUE x, VALUE y, int op)
01441 {
01442 VALUE rel;
01443 int n;
01444
01445 switch (TYPE(y)) {
01446 case T_FIXNUM:
01447 case T_BIGNUM:
01448 rel = rb_big_cmp(x, y);
01449 break;
01450
01451 case T_FLOAT:
01452 {
01453 double a = RFLOAT_VALUE(y);
01454
01455 if (isinf(a)) {
01456 if (a > 0.0) rel = INT2FIX(-1);
01457 else rel = INT2FIX(1);
01458 break;
01459 }
01460 rel = rb_dbl_cmp(rb_big2dbl(x), a);
01461 break;
01462 }
01463
01464 default:
01465 {
01466 ID id = 0;
01467 switch (op) {
01468 case 0: id = '>'; break;
01469 case 1: id = rb_intern(">="); break;
01470 case 2: id = '<'; break;
01471 case 3: id = rb_intern("<="); break;
01472 }
01473 return rb_num_coerce_relop(x, y, id);
01474 }
01475 }
01476
01477 if (NIL_P(rel)) return Qfalse;
01478 n = FIX2INT(rel);
01479
01480 switch (op) {
01481 case 0: return n > 0 ? Qtrue : Qfalse;
01482 case 1: return n >= 0 ? Qtrue : Qfalse;
01483 case 2: return n < 0 ? Qtrue : Qfalse;
01484 case 3: return n <= 0 ? Qtrue : Qfalse;
01485 }
01486 return Qundef;
01487 }
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497 static VALUE
01498 big_gt(VALUE x, VALUE y)
01499 {
01500 return big_op(x, y, 0);
01501 }
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511 static VALUE
01512 big_ge(VALUE x, VALUE y)
01513 {
01514 return big_op(x, y, 1);
01515 }
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525 static VALUE
01526 big_lt(VALUE x, VALUE y)
01527 {
01528 return big_op(x, y, 2);
01529 }
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539 static VALUE
01540 big_le(VALUE x, VALUE y)
01541 {
01542 return big_op(x, y, 3);
01543 }
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556 VALUE
01557 rb_big_eq(VALUE x, VALUE y)
01558 {
01559 switch (TYPE(y)) {
01560 case T_FIXNUM:
01561 y = rb_int2big(FIX2LONG(y));
01562 break;
01563 case T_BIGNUM:
01564 break;
01565 case T_FLOAT:
01566 {
01567 volatile double a, b;
01568
01569 a = RFLOAT_VALUE(y);
01570 if (isnan(a)) return Qfalse;
01571 b = rb_big2dbl(x);
01572 return (a == b)?Qtrue:Qfalse;
01573 }
01574 default:
01575 return rb_equal(y, x);
01576 }
01577 if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
01578 if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
01579 if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
01580 return Qtrue;
01581 }
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594 static VALUE
01595 rb_big_eql(VALUE x, VALUE y)
01596 {
01597 if (TYPE(y) != T_BIGNUM) return Qfalse;
01598 if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
01599 if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
01600 if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
01601 return Qtrue;
01602 }
01603
01604
01605
01606
01607
01608
01609
01610
01611 static VALUE
01612 rb_big_uminus(VALUE x)
01613 {
01614 VALUE z = rb_big_clone(x);
01615
01616 RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
01617
01618 return bignorm(z);
01619 }
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 static VALUE
01634 rb_big_neg(VALUE x)
01635 {
01636 VALUE z = rb_big_clone(x);
01637 BDIGIT *ds;
01638 long i;
01639
01640 if (!RBIGNUM_SIGN(x)) get2comp(z);
01641 ds = BDIGITS(z);
01642 i = RBIGNUM_LEN(x);
01643 if (!i) return INT2FIX(~(SIGNED_VALUE)0);
01644 while (i--) {
01645 ds[i] = ~ds[i];
01646 }
01647 RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(z));
01648 if (RBIGNUM_SIGN(x)) get2comp(z);
01649
01650 return bignorm(z);
01651 }
01652
01653 static void
01654 bigsub_core(BDIGIT *xds, long xn, BDIGIT *yds, long yn, BDIGIT *zds, long zn)
01655 {
01656 BDIGIT_DBL_SIGNED num;
01657 long i;
01658
01659 for (i = 0, num = 0; i < yn; i++) {
01660 num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
01661 zds[i] = BIGLO(num);
01662 num = BIGDN(num);
01663 }
01664 while (num && i < xn) {
01665 num += xds[i];
01666 zds[i++] = BIGLO(num);
01667 num = BIGDN(num);
01668 }
01669 while (i < xn) {
01670 zds[i] = xds[i];
01671 i++;
01672 }
01673 assert(i <= zn);
01674 while (i < zn) {
01675 zds[i++] = 0;
01676 }
01677 }
01678
01679 static VALUE
01680 bigsub(VALUE x, VALUE y)
01681 {
01682 VALUE z = 0;
01683 long i = RBIGNUM_LEN(x);
01684 BDIGIT *xds, *yds;
01685
01686
01687 if (RBIGNUM_LEN(x) < RBIGNUM_LEN(y)) {
01688 z = x; x = y; y = z;
01689 }
01690 else if (RBIGNUM_LEN(x) == RBIGNUM_LEN(y)) {
01691 xds = BDIGITS(x);
01692 yds = BDIGITS(y);
01693 while (i > 0) {
01694 i--;
01695 if (xds[i] > yds[i]) {
01696 break;
01697 }
01698 if (xds[i] < yds[i]) {
01699 z = x; x = y; y = z;
01700 break;
01701 }
01702 }
01703 }
01704
01705 z = bignew(RBIGNUM_LEN(x), z==0);
01706 bigsub_core(BDIGITS(x), RBIGNUM_LEN(x),
01707 BDIGITS(y), RBIGNUM_LEN(y),
01708 BDIGITS(z), RBIGNUM_LEN(z));
01709
01710 return z;
01711 }
01712
01713 static VALUE bigadd_int(VALUE x, long y);
01714
01715 static VALUE
01716 bigsub_int(VALUE x, long y0)
01717 {
01718 VALUE z;
01719 BDIGIT *xds, *zds;
01720 long xn;
01721 BDIGIT_DBL_SIGNED num;
01722 long i, y;
01723
01724 y = y0;
01725 xds = BDIGITS(x);
01726 xn = RBIGNUM_LEN(x);
01727
01728 z = bignew(xn, RBIGNUM_SIGN(x));
01729 zds = BDIGITS(z);
01730
01731 #if SIZEOF_BDIGITS == SIZEOF_LONG
01732 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
01733 if (xn == 1 && num < 0) {
01734 RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
01735 zds[0] = (BDIGIT)-num;
01736 return bignorm(z);
01737 }
01738 zds[0] = BIGLO(num);
01739 num = BIGDN(num);
01740 i = 1;
01741 #else
01742 num = 0;
01743 for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) {
01744 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
01745 zds[i] = BIGLO(num);
01746 num = BIGDN(num);
01747 y = BIGDN(y);
01748 }
01749 #endif
01750 while (num && i < xn) {
01751 num += xds[i];
01752 zds[i++] = BIGLO(num);
01753 num = BIGDN(num);
01754 }
01755 while (i < xn) {
01756 zds[i] = xds[i];
01757 i++;
01758 }
01759 if (num < 0) {
01760 z = bigsub(x, rb_int2big(y0));
01761 }
01762 return bignorm(z);
01763 }
01764
01765 static VALUE
01766 bigadd_int(VALUE x, long y)
01767 {
01768 VALUE z;
01769 BDIGIT *xds, *zds;
01770 long xn, zn;
01771 BDIGIT_DBL num;
01772 long i;
01773
01774 xds = BDIGITS(x);
01775 xn = RBIGNUM_LEN(x);
01776
01777 if (xn < 2) {
01778 zn = 3;
01779 }
01780 else {
01781 zn = xn + 1;
01782 }
01783 z = bignew(zn, RBIGNUM_SIGN(x));
01784 zds = BDIGITS(z);
01785
01786 #if SIZEOF_BDIGITS == SIZEOF_LONG
01787 num = (BDIGIT_DBL)xds[0] + y;
01788 zds[0] = BIGLO(num);
01789 num = BIGDN(num);
01790 i = 1;
01791 #else
01792 num = 0;
01793 for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) {
01794 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
01795 zds[i] = BIGLO(num);
01796 num = BIGDN(num);
01797 y = BIGDN(y);
01798 }
01799 #endif
01800 while (num && i < xn) {
01801 num += xds[i];
01802 zds[i++] = BIGLO(num);
01803 num = BIGDN(num);
01804 }
01805 if (num) zds[i++] = (BDIGIT)num;
01806 else while (i < xn) {
01807 zds[i] = xds[i];
01808 i++;
01809 }
01810 assert(i <= zn);
01811 while (i < zn) {
01812 zds[i++] = 0;
01813 }
01814 return bignorm(z);
01815 }
01816
01817 static void
01818 bigadd_core(BDIGIT *xds, long xn, BDIGIT *yds, long yn, BDIGIT *zds, long zn)
01819 {
01820 BDIGIT_DBL num = 0;
01821 long i;
01822
01823 if (xn > yn) {
01824 BDIGIT *tds;
01825 tds = xds; xds = yds; yds = tds;
01826 i = xn; xn = yn; yn = i;
01827 }
01828
01829 i = 0;
01830 while (i < xn) {
01831 num += (BDIGIT_DBL)xds[i] + yds[i];
01832 zds[i++] = BIGLO(num);
01833 num = BIGDN(num);
01834 }
01835 while (num && i < yn) {
01836 num += yds[i];
01837 zds[i++] = BIGLO(num);
01838 num = BIGDN(num);
01839 }
01840 while (i < yn) {
01841 zds[i] = yds[i];
01842 i++;
01843 }
01844 if (num) zds[i++] = (BDIGIT)num;
01845 assert(i <= zn);
01846 while (i < zn) {
01847 zds[i++] = 0;
01848 }
01849 }
01850
01851 static VALUE
01852 bigadd(VALUE x, VALUE y, int sign)
01853 {
01854 VALUE z;
01855 long len;
01856
01857 sign = (sign == RBIGNUM_SIGN(y));
01858 if (RBIGNUM_SIGN(x) != sign) {
01859 if (sign) return bigsub(y, x);
01860 return bigsub(x, y);
01861 }
01862
01863 if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
01864 len = RBIGNUM_LEN(x) + 1;
01865 }
01866 else {
01867 len = RBIGNUM_LEN(y) + 1;
01868 }
01869 z = bignew(len, sign);
01870
01871 bigadd_core(BDIGITS(x), RBIGNUM_LEN(x),
01872 BDIGITS(y), RBIGNUM_LEN(y),
01873 BDIGITS(z), RBIGNUM_LEN(z));
01874
01875 return z;
01876 }
01877
01878
01879
01880
01881
01882
01883
01884
01885 VALUE
01886 rb_big_plus(VALUE x, VALUE y)
01887 {
01888 long n;
01889
01890 switch (TYPE(y)) {
01891 case T_FIXNUM:
01892 n = FIX2LONG(y);
01893 if ((n > 0) != RBIGNUM_SIGN(x)) {
01894 if (n < 0) {
01895 n = -n;
01896 }
01897 return bigsub_int(x, n);
01898 }
01899 if (n < 0) {
01900 n = -n;
01901 }
01902 return bigadd_int(x, n);
01903
01904 case T_BIGNUM:
01905 return bignorm(bigadd(x, y, 1));
01906
01907 case T_FLOAT:
01908 return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
01909
01910 default:
01911 return rb_num_coerce_bin(x, y, '+');
01912 }
01913 }
01914
01915
01916
01917
01918
01919
01920
01921
01922 VALUE
01923 rb_big_minus(VALUE x, VALUE y)
01924 {
01925 long n;
01926
01927 switch (TYPE(y)) {
01928 case T_FIXNUM:
01929 n = FIX2LONG(y);
01930 if ((n > 0) != RBIGNUM_SIGN(x)) {
01931 if (n < 0) {
01932 n = -n;
01933 }
01934 return bigadd_int(x, n);
01935 }
01936 if (n < 0) {
01937 n = -n;
01938 }
01939 return bigsub_int(x, n);
01940
01941 case T_BIGNUM:
01942 return bignorm(bigadd(x, y, 0));
01943
01944 case T_FLOAT:
01945 return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
01946
01947 default:
01948 return rb_num_coerce_bin(x, y, '-');
01949 }
01950 }
01951
01952 static long
01953 big_real_len(VALUE x)
01954 {
01955 long i = RBIGNUM_LEN(x);
01956 BDIGIT *xds = BDIGITS(x);
01957 while (--i && !xds[i]);
01958 return i + 1;
01959 }
01960
01961 static VALUE
01962 bigmul1_single(VALUE x, VALUE y)
01963 {
01964 BDIGIT_DBL n;
01965 VALUE z = bignew(2, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
01966 BDIGIT *xds, *yds, *zds;
01967
01968 xds = BDIGITS(x);
01969 yds = BDIGITS(y);
01970 zds = BDIGITS(z);
01971
01972 n = (BDIGIT_DBL)xds[0] * yds[0];
01973 zds[0] = BIGLO(n);
01974 zds[1] = (BDIGIT)BIGDN(n);
01975
01976 return z;
01977 }
01978
01979 static VALUE
01980 bigmul1_normal(VALUE x, VALUE y)
01981 {
01982 long xl = RBIGNUM_LEN(x), yl = RBIGNUM_LEN(y), i, j = xl + yl + 1;
01983 BDIGIT_DBL n = 0;
01984 VALUE z = bignew(j, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
01985 BDIGIT *xds, *yds, *zds;
01986
01987 xds = BDIGITS(x);
01988 yds = BDIGITS(y);
01989 zds = BDIGITS(z);
01990 while (j--) zds[j] = 0;
01991 for (i = 0; i < xl; i++) {
01992 BDIGIT_DBL dd;
01993 dd = xds[i];
01994 if (dd == 0) continue;
01995 n = 0;
01996 for (j = 0; j < yl; j++) {
01997 BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * yds[j];
01998 n = zds[i + j] + ee;
01999 if (ee) zds[i + j] = BIGLO(n);
02000 n = BIGDN(n);
02001 }
02002 if (n) {
02003 zds[i + j] = (BDIGIT)n;
02004 }
02005 }
02006 rb_thread_check_ints();
02007 return z;
02008 }
02009
02010 static VALUE bigmul0(VALUE x, VALUE y);
02011
02012
02013 static VALUE
02014 bigmul1_balance(VALUE x, VALUE y)
02015 {
02016 VALUE z, t1, t2;
02017 long i, xn, yn, r, n;
02018 BDIGIT *yds, *zds, *t1ds;
02019
02020 xn = RBIGNUM_LEN(x);
02021 yn = RBIGNUM_LEN(y);
02022 assert(2 * xn <= yn);
02023
02024 z = bignew(xn + yn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02025 t1 = bignew(xn, 1);
02026
02027 yds = BDIGITS(y);
02028 zds = BDIGITS(z);
02029 t1ds = BDIGITS(t1);
02030
02031 for (i = 0; i < xn + yn; i++) zds[i] = 0;
02032
02033 n = 0;
02034 while (yn > 0) {
02035 r = xn > yn ? yn : xn;
02036 MEMCPY(t1ds, yds + n, BDIGIT, r);
02037 RBIGNUM_SET_LEN(t1, r);
02038 t2 = bigmul0(x, t1);
02039 bigadd_core(zds + n, RBIGNUM_LEN(z) - n,
02040 BDIGITS(t2), big_real_len(t2),
02041 zds + n, RBIGNUM_LEN(z) - n);
02042 yn -= r;
02043 n += r;
02044 }
02045
02046 return z;
02047 }
02048
02049
02050 static void
02051 big_split(VALUE v, long n, volatile VALUE *ph, volatile VALUE *pl)
02052 {
02053 long hn = 0, ln = RBIGNUM_LEN(v);
02054 VALUE h, l;
02055 BDIGIT *vds = BDIGITS(v);
02056
02057 if (ln > n) {
02058 hn = ln - n;
02059 ln = n;
02060 }
02061
02062 while (--hn && !vds[hn + ln]);
02063 h = bignew(hn += 2, 1);
02064 MEMCPY(BDIGITS(h), vds + ln, BDIGIT, hn - 1);
02065 BDIGITS(h)[hn - 1] = 0;
02066
02067 while (--ln && !vds[ln]);
02068 l = bignew(ln += 2, 1);
02069 MEMCPY(BDIGITS(l), vds, BDIGIT, ln - 1);
02070 BDIGITS(l)[ln - 1] = 0;
02071
02072 *pl = l;
02073 *ph = h;
02074 }
02075
02076
02077 static VALUE
02078 bigmul1_karatsuba(VALUE x, VALUE y)
02079 {
02080 long i, n, xn, yn, t1n, t2n;
02081 VALUE xh, xl, yh, yl, z, t1, t2, t3;
02082 BDIGIT *zds;
02083
02084 xn = RBIGNUM_LEN(x);
02085 yn = RBIGNUM_LEN(y);
02086 n = yn / 2;
02087 big_split(x, n, &xh, &xl);
02088 if (x == y) {
02089 yh = xh; yl = xl;
02090 }
02091 else big_split(y, n, &yh, &yl);
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107 z = bignew(xn + yn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02108 zds = BDIGITS(z);
02109
02110
02111 t1 = bigmul0(xh, yh);
02112 t1n = big_real_len(t1);
02113
02114
02115 MEMCPY(zds + 2 * n, BDIGITS(t1), BDIGIT, t1n);
02116 for (i = 2 * n + t1n; i < xn + yn; i++) zds[i] = 0;
02117
02118 if (!BIGZEROP(xl) && !BIGZEROP(yl)) {
02119
02120 t2 = bigmul0(xl, yl);
02121 t2n = big_real_len(t2);
02122
02123
02124 MEMCPY(zds, BDIGITS(t2), BDIGIT, t2n);
02125 for (i = t2n; i < 2 * n; i++) zds[i] = 0;
02126 }
02127 else {
02128 t2 = Qundef;
02129 t2n = 0;
02130
02131
02132 for (i = 0; i < 2 * n; i++) zds[i] = 0;
02133 }
02134
02135
02136 if (RBIGNUM_LEN(xl) > RBIGNUM_LEN(xh)) {
02137 t3 = xl; xl = xh; xh = t3;
02138 }
02139
02140 bigadd_core(BDIGITS(xh), RBIGNUM_LEN(xh),
02141 BDIGITS(xl), RBIGNUM_LEN(xl),
02142 BDIGITS(xh), RBIGNUM_LEN(xh));
02143
02144
02145 if (x != y) {
02146 if (RBIGNUM_LEN(yl) > RBIGNUM_LEN(yh)) {
02147 t3 = yl; yl = yh; yh = t3;
02148 }
02149
02150 bigadd_core(BDIGITS(yh), RBIGNUM_LEN(yh),
02151 BDIGITS(yl), RBIGNUM_LEN(yl),
02152 BDIGITS(yh), RBIGNUM_LEN(yh));
02153 }
02154 else yh = xh;
02155
02156
02157 t3 = bigmul0(xh, yh);
02158
02159 i = xn + yn - n;
02160
02161 bigsub_core(BDIGITS(t3), big_real_len(t3), BDIGITS(t1), t1n, BDIGITS(t3), big_real_len(t3));
02162
02163
02164 if (t2 != Qundef) bigsub_core(BDIGITS(t3), big_real_len(t3), BDIGITS(t2), t2n, BDIGITS(t3), big_real_len(t3));
02165
02166
02167 bigadd_core(zds + n, i, BDIGITS(t3), big_real_len(t3), zds + n, i);
02168
02169 return z;
02170 }
02171
02172
02173
02174
02175
02176 static VALUE
02177 bigsqr_fast(VALUE x)
02178 {
02179 long len = RBIGNUM_LEN(x), i, j;
02180 VALUE z = bignew(2 * len + 1, 1);
02181 BDIGIT *xds = BDIGITS(x), *zds = BDIGITS(z);
02182 BDIGIT_DBL c, v, w;
02183
02184 for (i = 2 * len + 1; i--; ) zds[i] = 0;
02185 for (i = 0; i < len; i++) {
02186 v = (BDIGIT_DBL)xds[i];
02187 if (!v) continue;
02188 c = (BDIGIT_DBL)zds[i + i] + v * v;
02189 zds[i + i] = BIGLO(c);
02190 c = BIGDN(c);
02191 v *= 2;
02192 for (j = i + 1; j < len; j++) {
02193 w = (BDIGIT_DBL)xds[j];
02194 c += (BDIGIT_DBL)zds[i + j] + BIGLO(v) * w;
02195 zds[i + j] = BIGLO(c);
02196 c = BIGDN(c);
02197 if (BIGDN(v)) c += w;
02198 }
02199 if (c) {
02200 c += (BDIGIT_DBL)zds[i + len];
02201 zds[i + len] = BIGLO(c);
02202 c = BIGDN(c);
02203 }
02204 if (c) zds[i + len + 1] += (BDIGIT)c;
02205 }
02206 return z;
02207 }
02208
02209 #define KARATSUBA_MUL_DIGITS 70
02210
02211
02212
02213 static inline VALUE
02214 big_sparse_p(VALUE x)
02215 {
02216 long c = 0, n = RBIGNUM_LEN(x);
02217 unsigned long rb_rand_internal(unsigned long i);
02218
02219 if ( BDIGITS(x)[rb_rand_internal(n / 2) + n / 4]) c++;
02220 if (c <= 1 && BDIGITS(x)[rb_rand_internal(n / 2) + n / 4]) c++;
02221 if (c <= 1 && BDIGITS(x)[rb_rand_internal(n / 2) + n / 4]) c++;
02222
02223 return (c <= 1) ? Qtrue : Qfalse;
02224 }
02225
02226 #if 0
02227 static void
02228 dump_bignum(VALUE x)
02229 {
02230 long i;
02231 printf("0x0");
02232 for (i = RBIGNUM_LEN(x); i--; ) {
02233 printf("_%08x", BDIGITS(x)[i]);
02234 }
02235 puts("");
02236 }
02237 #endif
02238
02239 static VALUE
02240 bigmul0(VALUE x, VALUE y)
02241 {
02242 long xn, yn;
02243
02244 xn = RBIGNUM_LEN(x);
02245 yn = RBIGNUM_LEN(y);
02246
02247
02248 if (xn > yn) {
02249 VALUE t;
02250 long tn;
02251 t = x; x = y; y = t;
02252 tn = xn; xn = yn; yn = tn;
02253 }
02254 assert(xn <= yn);
02255
02256
02257 if (xn < KARATSUBA_MUL_DIGITS) {
02258 normal:
02259 if (x == y) return bigsqr_fast(x);
02260 if (xn == 1 && yn == 1) return bigmul1_single(x, y);
02261 return bigmul1_normal(x, y);
02262 }
02263
02264
02265 if (big_sparse_p(x)) goto normal;
02266 if (big_sparse_p(y)) return bigmul1_normal(y, x);
02267
02268
02269 if (2 * xn <= yn) return bigmul1_balance(x, y);
02270
02271
02272 return bigmul1_karatsuba(x, y);
02273 }
02274
02275
02276
02277
02278
02279
02280
02281
02282 VALUE
02283 rb_big_mul(VALUE x, VALUE y)
02284 {
02285 switch (TYPE(y)) {
02286 case T_FIXNUM:
02287 y = rb_int2big(FIX2LONG(y));
02288 break;
02289
02290 case T_BIGNUM:
02291 break;
02292
02293 case T_FLOAT:
02294 return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
02295
02296 default:
02297 return rb_num_coerce_bin(x, y, '*');
02298 }
02299
02300 return bignorm(bigmul0(x, y));
02301 }
02302
02303 struct big_div_struct {
02304 long nx, ny;
02305 BDIGIT *yds, *zds;
02306 VALUE stop;
02307 };
02308
02309 static VALUE
02310 bigdivrem1(void *ptr)
02311 {
02312 struct big_div_struct *bds = (struct big_div_struct*)ptr;
02313 long nx = bds->nx, ny = bds->ny;
02314 long i, j, nyzero;
02315 BDIGIT *yds = bds->yds, *zds = bds->zds;
02316 BDIGIT_DBL t2;
02317 BDIGIT_DBL_SIGNED num;
02318 BDIGIT q;
02319
02320 j = nx==ny?nx+1:nx;
02321 for (nyzero = 0; !yds[nyzero]; nyzero++);
02322 do {
02323 if (bds->stop) return Qnil;
02324 if (zds[j] == yds[ny-1]) q = (BDIGIT)BIGRAD-1;
02325 else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
02326 if (q) {
02327 i = nyzero; num = 0; t2 = 0;
02328 do {
02329 BDIGIT_DBL ee;
02330 t2 += (BDIGIT_DBL)yds[i] * q;
02331 ee = num - BIGLO(t2);
02332 num = (BDIGIT_DBL)zds[j - ny + i] + ee;
02333 if (ee) zds[j - ny + i] = BIGLO(num);
02334 num = BIGDN(num);
02335 t2 = BIGDN(t2);
02336 } while (++i < ny);
02337 num += zds[j - ny + i] - t2;
02338 while (num) {
02339 i = 0; num = 0; q--;
02340 do {
02341 BDIGIT_DBL ee = num + yds[i];
02342 num = (BDIGIT_DBL)zds[j - ny + i] + ee;
02343 if (ee) zds[j - ny + i] = BIGLO(num);
02344 num = BIGDN(num);
02345 } while (++i < ny);
02346 num--;
02347 }
02348 }
02349 zds[j] = q;
02350 } while (--j >= ny);
02351 return Qnil;
02352 }
02353
02354 static void
02355 rb_big_stop(void *ptr)
02356 {
02357 VALUE *stop = (VALUE*)ptr;
02358 *stop = Qtrue;
02359 }
02360
02361 static VALUE
02362 bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
02363 {
02364 struct big_div_struct bds;
02365 long nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y);
02366 long i, j;
02367 VALUE z, yy, zz;
02368 BDIGIT *xds, *yds, *zds, *tds;
02369 BDIGIT_DBL t2;
02370 BDIGIT dd, q;
02371
02372 if (BIGZEROP(y)) rb_num_zerodiv();
02373 xds = BDIGITS(x);
02374 yds = BDIGITS(y);
02375 if (nx < ny || (nx == ny && xds[nx - 1] < yds[ny - 1])) {
02376 if (divp) *divp = rb_int2big(0);
02377 if (modp) *modp = x;
02378 return Qnil;
02379 }
02380 if (ny == 1) {
02381 dd = yds[0];
02382 z = rb_big_clone(x);
02383 zds = BDIGITS(z);
02384 t2 = 0; i = nx;
02385 while (i--) {
02386 t2 = BIGUP(t2) + zds[i];
02387 zds[i] = (BDIGIT)(t2 / dd);
02388 t2 %= dd;
02389 }
02390 RBIGNUM_SET_SIGN(z, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02391 if (modp) {
02392 *modp = rb_uint2big((VALUE)t2);
02393 RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x));
02394 }
02395 if (divp) *divp = z;
02396 return Qnil;
02397 }
02398 z = bignew(nx==ny?nx+2:nx+1, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02399 zds = BDIGITS(z);
02400 if (nx==ny) zds[nx+1] = 0;
02401 while (!yds[ny-1]) ny--;
02402
02403 dd = 0;
02404 q = yds[ny-1];
02405 while ((q & (BDIGIT)(1UL<<(BITSPERDIG-1))) == 0) {
02406 q <<= 1UL;
02407 dd++;
02408 }
02409 if (dd) {
02410 yy = rb_big_clone(y);
02411 tds = BDIGITS(yy);
02412 j = 0;
02413 t2 = 0;
02414 while (j<ny) {
02415 t2 += (BDIGIT_DBL)yds[j]<<dd;
02416 tds[j++] = BIGLO(t2);
02417 t2 = BIGDN(t2);
02418 }
02419 yds = tds;
02420 RB_GC_GUARD(y) = yy;
02421 j = 0;
02422 t2 = 0;
02423 while (j<nx) {
02424 t2 += (BDIGIT_DBL)xds[j]<<dd;
02425 zds[j++] = BIGLO(t2);
02426 t2 = BIGDN(t2);
02427 }
02428 zds[j] = (BDIGIT)t2;
02429 }
02430 else {
02431 zds[nx] = 0;
02432 j = nx;
02433 while (j--) zds[j] = xds[j];
02434 }
02435
02436 bds.nx = nx;
02437 bds.ny = ny;
02438 bds.zds = zds;
02439 bds.yds = yds;
02440 bds.stop = Qfalse;
02441 if (nx > 10000 || ny > 10000) {
02442 rb_thread_blocking_region(bigdivrem1, &bds, rb_big_stop, &bds.stop);
02443 }
02444 else {
02445 bigdivrem1(&bds);
02446 }
02447
02448 if (divp) {
02449 *divp = zz = rb_big_clone(z);
02450 zds = BDIGITS(zz);
02451 j = (nx==ny ? nx+2 : nx+1) - ny;
02452 for (i = 0;i < j;i++) zds[i] = zds[i+ny];
02453 if (!zds[i-1]) i--;
02454 RBIGNUM_SET_LEN(zz, i);
02455 }
02456 if (modp) {
02457 *modp = zz = rb_big_clone(z);
02458 zds = BDIGITS(zz);
02459 while (--ny && !zds[ny]); ++ny;
02460 if (dd) {
02461 t2 = 0; i = ny;
02462 while(i--) {
02463 t2 = (t2 | zds[i]) >> dd;
02464 q = zds[i];
02465 zds[i] = BIGLO(t2);
02466 t2 = BIGUP(q);
02467 }
02468 }
02469 if (!zds[ny-1]) ny--;
02470 RBIGNUM_SET_LEN(zz, ny);
02471 RBIGNUM_SET_SIGN(zz, RBIGNUM_SIGN(x));
02472 }
02473 return z;
02474 }
02475
02476 static void
02477 bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
02478 {
02479 VALUE mod;
02480
02481 bigdivrem(x, y, divp, &mod);
02482 if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y) && !BIGZEROP(mod)) {
02483 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
02484 if (modp) *modp = bigadd(mod, y, 1);
02485 }
02486 else if (modp) {
02487 *modp = mod;
02488 }
02489 }
02490
02491
02492 static VALUE
02493 rb_big_divide(VALUE x, VALUE y, ID op)
02494 {
02495 VALUE z;
02496
02497 switch (TYPE(y)) {
02498 case T_FIXNUM:
02499 y = rb_int2big(FIX2LONG(y));
02500 break;
02501
02502 case T_BIGNUM:
02503 break;
02504
02505 case T_FLOAT:
02506 {
02507 double div = rb_big2dbl(x) / RFLOAT_VALUE(y);
02508 if (op == '/') {
02509 return DBL2NUM(div);
02510 }
02511 else {
02512 return rb_dbl2big(div);
02513 }
02514 }
02515
02516 default:
02517 return rb_num_coerce_bin(x, y, op);
02518 }
02519 bigdivmod(x, y, &z, 0);
02520
02521 return bignorm(z);
02522 }
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533 VALUE
02534 rb_big_div(VALUE x, VALUE y)
02535 {
02536 return rb_big_divide(x, y, '/');
02537 }
02538
02539
02540
02541
02542
02543
02544
02545
02546 VALUE
02547 rb_big_idiv(VALUE x, VALUE y)
02548 {
02549 return rb_big_divide(x, y, rb_intern("div"));
02550 }
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561 VALUE
02562 rb_big_modulo(VALUE x, VALUE y)
02563 {
02564 VALUE z;
02565
02566 switch (TYPE(y)) {
02567 case T_FIXNUM:
02568 y = rb_int2big(FIX2LONG(y));
02569 break;
02570
02571 case T_BIGNUM:
02572 break;
02573
02574 default:
02575 return rb_num_coerce_bin(x, y, '%');
02576 }
02577 bigdivmod(x, y, 0, &z);
02578
02579 return bignorm(z);
02580 }
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591 static VALUE
02592 rb_big_remainder(VALUE x, VALUE y)
02593 {
02594 VALUE z;
02595
02596 switch (TYPE(y)) {
02597 case T_FIXNUM:
02598 y = rb_int2big(FIX2LONG(y));
02599 break;
02600
02601 case T_BIGNUM:
02602 break;
02603
02604 default:
02605 return rb_num_coerce_bin(x, y, rb_intern("remainder"));
02606 }
02607 bigdivrem(x, y, 0, &z);
02608
02609 return bignorm(z);
02610 }
02611
02612
02613
02614
02615
02616
02617
02618
02619 VALUE
02620 rb_big_divmod(VALUE x, VALUE y)
02621 {
02622 VALUE div, mod;
02623
02624 switch (TYPE(y)) {
02625 case T_FIXNUM:
02626 y = rb_int2big(FIX2LONG(y));
02627 break;
02628
02629 case T_BIGNUM:
02630 break;
02631
02632 default:
02633 return rb_num_coerce_bin(x, y, rb_intern("divmod"));
02634 }
02635 bigdivmod(x, y, &div, &mod);
02636
02637 return rb_assoc_new(bignorm(div), bignorm(mod));
02638 }
02639
02640 static int
02641 bdigbitsize(BDIGIT x)
02642 {
02643 int size = 1;
02644 int nb = BITSPERDIG / 2;
02645 BDIGIT bits = (~0 << nb);
02646
02647 if (!x) return 0;
02648 while (x > 1) {
02649 if (x & bits) {
02650 size += nb;
02651 x >>= nb;
02652 }
02653 x &= ~bits;
02654 nb /= 2;
02655 bits >>= nb;
02656 }
02657
02658 return size;
02659 }
02660
02661 static VALUE big_lshift(VALUE, unsigned long);
02662 static VALUE big_rshift(VALUE, unsigned long);
02663
02664 static VALUE
02665 big_shift(VALUE x, long n)
02666 {
02667 if (n < 0)
02668 return big_lshift(x, (unsigned long)-n);
02669 else if (n > 0)
02670 return big_rshift(x, (unsigned long)n);
02671 return x;
02672 }
02673
02674 static VALUE
02675 big_fdiv(VALUE x, VALUE y)
02676 {
02677 #define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)
02678 VALUE z;
02679 long l, ex, ey;
02680 int i;
02681
02682 bigtrunc(x);
02683 l = RBIGNUM_LEN(x) - 1;
02684 ex = l * BITSPERDIG;
02685 ex += bdigbitsize(BDIGITS(x)[l]);
02686 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
02687 if (ex) x = big_shift(x, ex);
02688
02689 switch (TYPE(y)) {
02690 case T_FIXNUM:
02691 y = rb_int2big(FIX2LONG(y));
02692 case T_BIGNUM: {
02693 bigtrunc(y);
02694 l = RBIGNUM_LEN(y) - 1;
02695 ey = l * BITSPERDIG;
02696 ey += bdigbitsize(BDIGITS(y)[l]);
02697 ey -= DBL_BIGDIG * BITSPERDIG;
02698 if (ey) y = big_shift(y, ey);
02699 bignum:
02700 bigdivrem(x, y, &z, 0);
02701 l = ex - ey;
02702 #if SIZEOF_LONG > SIZEOF_INT
02703 {
02704
02705 if (l > INT_MAX) return DBL2NUM(INFINITY);
02706 if (l < INT_MIN) return DBL2NUM(0.0);
02707 }
02708 #endif
02709 return DBL2NUM(ldexp(big2dbl(z), (int)l));
02710 }
02711 case T_FLOAT:
02712 y = dbl2big(ldexp(frexp(RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
02713 ey = i - DBL_MANT_DIG;
02714 goto bignum;
02715 }
02716 rb_bug("big_fdiv");
02717
02718 }
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733 VALUE
02734 rb_big_fdiv(VALUE x, VALUE y)
02735 {
02736 double dx, dy;
02737
02738 dx = big2dbl(x);
02739 switch (TYPE(y)) {
02740 case T_FIXNUM:
02741 dy = (double)FIX2LONG(y);
02742 if (isinf(dx))
02743 return big_fdiv(x, y);
02744 break;
02745
02746 case T_BIGNUM:
02747 dy = rb_big2dbl(y);
02748 if (isinf(dx) || isinf(dy))
02749 return big_fdiv(x, y);
02750 break;
02751
02752 case T_FLOAT:
02753 dy = RFLOAT_VALUE(y);
02754 if (isnan(dy))
02755 return y;
02756 if (isinf(dx))
02757 return big_fdiv(x, y);
02758 break;
02759
02760 default:
02761 return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
02762 }
02763 return DBL2NUM(dx / dy);
02764 }
02765
02766 static VALUE
02767 bigsqr(VALUE x)
02768 {
02769 return bigtrunc(bigmul0(x, x));
02770 }
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785 VALUE
02786 rb_big_pow(VALUE x, VALUE y)
02787 {
02788 double d;
02789 SIGNED_VALUE yy;
02790
02791 if (y == INT2FIX(0)) return INT2FIX(1);
02792 switch (TYPE(y)) {
02793 case T_FLOAT:
02794 d = RFLOAT_VALUE(y);
02795 if ((!RBIGNUM_SIGN(x) && !BIGZEROP(x)) && d != round(d))
02796 return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
02797 break;
02798
02799 case T_BIGNUM:
02800 rb_warn("in a**b, b may be too big");
02801 d = rb_big2dbl(y);
02802 break;
02803
02804 case T_FIXNUM:
02805 yy = FIX2LONG(y);
02806
02807 if (yy < 0)
02808 return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
02809 else {
02810 VALUE z = 0;
02811 SIGNED_VALUE mask;
02812 const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
02813
02814 if ((RBIGNUM_LEN(x) > BIGLEN_LIMIT) ||
02815 (RBIGNUM_LEN(x) > BIGLEN_LIMIT / yy)) {
02816 rb_warn("in a**b, b may be too big");
02817 d = (double)yy;
02818 break;
02819 }
02820 for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
02821 if (z) z = bigsqr(z);
02822 if (yy & mask) {
02823 z = z ? bigtrunc(bigmul0(z, x)) : x;
02824 }
02825 }
02826 return bignorm(z);
02827 }
02828
02829 break;
02830
02831 default:
02832 return rb_num_coerce_bin(x, y, rb_intern("**"));
02833 }
02834 return DBL2NUM(pow(rb_big2dbl(x), d));
02835 }
02836
02837 static inline VALUE
02838 bit_coerce(VALUE x)
02839 {
02840 while (!FIXNUM_P(x) && TYPE(x) != T_BIGNUM) {
02841 if (TYPE(x) == T_FLOAT) {
02842 rb_raise(rb_eTypeError, "can't convert Float into Integer");
02843 }
02844 x = rb_to_int(x);
02845 }
02846 return x;
02847 }
02848
02849 static VALUE
02850 bigand_int(VALUE x, long y)
02851 {
02852 VALUE z;
02853 BDIGIT *xds, *zds;
02854 long xn, zn;
02855 long i;
02856 char sign;
02857
02858 if (y == 0) return INT2FIX(0);
02859 sign = (y > 0);
02860 xds = BDIGITS(x);
02861 zn = xn = RBIGNUM_LEN(x);
02862 #if SIZEOF_BDIGITS == SIZEOF_LONG
02863 if (sign) {
02864 y &= xds[0];
02865 return LONG2NUM(y);
02866 }
02867 #endif
02868
02869 z = bignew(zn, RBIGNUM_SIGN(x) || sign);
02870 zds = BDIGITS(z);
02871
02872 #if SIZEOF_BDIGITS == SIZEOF_LONG
02873 i = 1;
02874 zds[0] = xds[0] & y;
02875 #else
02876 {
02877 BDIGIT_DBL num = y;
02878
02879 for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) {
02880 zds[i] = xds[i] & BIGLO(num);
02881 num = BIGDN(num);
02882 }
02883 }
02884 #endif
02885 while (i < xn) {
02886 zds[i] = sign?0:xds[i];
02887 i++;
02888 }
02889 if (!RBIGNUM_SIGN(z)) get2comp(z);
02890 return bignorm(z);
02891 }
02892
02893
02894
02895
02896
02897
02898
02899
02900 VALUE
02901 rb_big_and(VALUE xx, VALUE yy)
02902 {
02903 volatile VALUE x, y, z;
02904 BDIGIT *ds1, *ds2, *zds;
02905 long i, l1, l2;
02906 char sign;
02907
02908 x = xx;
02909 y = bit_coerce(yy);
02910 if (!RBIGNUM_SIGN(x)) {
02911 x = rb_big_clone(x);
02912 get2comp(x);
02913 }
02914 if (FIXNUM_P(y)) {
02915 return bigand_int(x, FIX2LONG(y));
02916 }
02917 if (!RBIGNUM_SIGN(y)) {
02918 y = rb_big_clone(y);
02919 get2comp(y);
02920 }
02921 if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
02922 l1 = RBIGNUM_LEN(y);
02923 l2 = RBIGNUM_LEN(x);
02924 ds1 = BDIGITS(y);
02925 ds2 = BDIGITS(x);
02926 sign = RBIGNUM_SIGN(y);
02927 }
02928 else {
02929 l1 = RBIGNUM_LEN(x);
02930 l2 = RBIGNUM_LEN(y);
02931 ds1 = BDIGITS(x);
02932 ds2 = BDIGITS(y);
02933 sign = RBIGNUM_SIGN(x);
02934 }
02935 z = bignew(l2, RBIGNUM_SIGN(x) || RBIGNUM_SIGN(y));
02936 zds = BDIGITS(z);
02937
02938 for (i=0; i<l1; i++) {
02939 zds[i] = ds1[i] & ds2[i];
02940 }
02941 for (; i<l2; i++) {
02942 zds[i] = sign?0:ds2[i];
02943 }
02944 if (!RBIGNUM_SIGN(z)) get2comp(z);
02945 return bignorm(z);
02946 }
02947
02948 static VALUE
02949 bigor_int(VALUE x, long y)
02950 {
02951 VALUE z;
02952 BDIGIT *xds, *zds;
02953 long xn, zn;
02954 long i;
02955 char sign;
02956
02957 sign = (y >= 0);
02958 xds = BDIGITS(x);
02959 zn = xn = RBIGNUM_LEN(x);
02960 z = bignew(zn, RBIGNUM_SIGN(x) && sign);
02961 zds = BDIGITS(z);
02962
02963 #if SIZEOF_BDIGITS == SIZEOF_LONG
02964 i = 1;
02965 zds[0] = xds[0] | y;
02966 #else
02967 {
02968 BDIGIT_DBL num = y;
02969
02970 for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) {
02971 zds[i] = xds[i] | BIGLO(num);
02972 num = BIGDN(num);
02973 }
02974 }
02975 #endif
02976 while (i < xn) {
02977 zds[i] = sign?xds[i]:(BDIGIT)(BIGRAD-1);
02978 i++;
02979 }
02980 if (!RBIGNUM_SIGN(z)) get2comp(z);
02981 return bignorm(z);
02982 }
02983
02984
02985
02986
02987
02988
02989
02990
02991 VALUE
02992 rb_big_or(VALUE xx, VALUE yy)
02993 {
02994 volatile VALUE x, y, z;
02995 BDIGIT *ds1, *ds2, *zds;
02996 long i, l1, l2;
02997 char sign;
02998
02999 x = xx;
03000 y = bit_coerce(yy);
03001
03002 if (!RBIGNUM_SIGN(x)) {
03003 x = rb_big_clone(x);
03004 get2comp(x);
03005 }
03006 if (FIXNUM_P(y)) {
03007 return bigor_int(x, FIX2LONG(y));
03008 }
03009 if (!RBIGNUM_SIGN(y)) {
03010 y = rb_big_clone(y);
03011 get2comp(y);
03012 }
03013 if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
03014 l1 = RBIGNUM_LEN(y);
03015 l2 = RBIGNUM_LEN(x);
03016 ds1 = BDIGITS(y);
03017 ds2 = BDIGITS(x);
03018 sign = RBIGNUM_SIGN(y);
03019 }
03020 else {
03021 l1 = RBIGNUM_LEN(x);
03022 l2 = RBIGNUM_LEN(y);
03023 ds1 = BDIGITS(x);
03024 ds2 = BDIGITS(y);
03025 sign = RBIGNUM_SIGN(x);
03026 }
03027 z = bignew(l2, RBIGNUM_SIGN(x) && RBIGNUM_SIGN(y));
03028 zds = BDIGITS(z);
03029
03030 for (i=0; i<l1; i++) {
03031 zds[i] = ds1[i] | ds2[i];
03032 }
03033 for (; i<l2; i++) {
03034 zds[i] = sign?ds2[i]:(BDIGIT)(BIGRAD-1);
03035 }
03036 if (!RBIGNUM_SIGN(z)) get2comp(z);
03037 return bignorm(z);
03038 }
03039
03040 static VALUE
03041 bigxor_int(VALUE x, long y)
03042 {
03043 VALUE z;
03044 BDIGIT *xds, *zds;
03045 long xn, zn;
03046 long i;
03047 char sign;
03048
03049 sign = (y >= 0) ? 1 : 0;
03050 xds = BDIGITS(x);
03051 zn = xn = RBIGNUM_LEN(x);
03052 z = bignew(zn, !(RBIGNUM_SIGN(x) ^ sign));
03053 zds = BDIGITS(z);
03054
03055 #if SIZEOF_BDIGITS == SIZEOF_LONG
03056 i = 1;
03057 zds[0] = xds[0] ^ y;
03058 #else
03059 {
03060 BDIGIT_DBL num = y;
03061
03062 for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) {
03063 zds[i] = xds[i] ^ BIGLO(num);
03064 num = BIGDN(num);
03065 }
03066 }
03067 #endif
03068 while (i < xn) {
03069 zds[i] = sign?xds[i]:~xds[i];
03070 i++;
03071 }
03072 if (!RBIGNUM_SIGN(z)) get2comp(z);
03073 return bignorm(z);
03074 }
03075
03076
03077
03078
03079
03080
03081
03082 VALUE
03083 rb_big_xor(VALUE xx, VALUE yy)
03084 {
03085 volatile VALUE x, y;
03086 VALUE z;
03087 BDIGIT *ds1, *ds2, *zds;
03088 long i, l1, l2;
03089 char sign;
03090
03091 x = xx;
03092 y = bit_coerce(yy);
03093
03094 if (!RBIGNUM_SIGN(x)) {
03095 x = rb_big_clone(x);
03096 get2comp(x);
03097 }
03098 if (FIXNUM_P(y)) {
03099 return bigxor_int(x, FIX2LONG(y));
03100 }
03101 if (!RBIGNUM_SIGN(y)) {
03102 y = rb_big_clone(y);
03103 get2comp(y);
03104 }
03105 if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
03106 l1 = RBIGNUM_LEN(y);
03107 l2 = RBIGNUM_LEN(x);
03108 ds1 = BDIGITS(y);
03109 ds2 = BDIGITS(x);
03110 sign = RBIGNUM_SIGN(y);
03111 }
03112 else {
03113 l1 = RBIGNUM_LEN(x);
03114 l2 = RBIGNUM_LEN(y);
03115 ds1 = BDIGITS(x);
03116 ds2 = BDIGITS(y);
03117 sign = RBIGNUM_SIGN(x);
03118 }
03119 RBIGNUM_SET_SIGN(x, RBIGNUM_SIGN(x)?1:0);
03120 RBIGNUM_SET_SIGN(y, RBIGNUM_SIGN(y)?1:0);
03121 z = bignew(l2, !(RBIGNUM_SIGN(x) ^ RBIGNUM_SIGN(y)));
03122 zds = BDIGITS(z);
03123
03124 for (i=0; i<l1; i++) {
03125 zds[i] = ds1[i] ^ ds2[i];
03126 }
03127 for (; i<l2; i++) {
03128 zds[i] = sign?ds2[i]:~ds2[i];
03129 }
03130 if (!RBIGNUM_SIGN(z)) get2comp(z);
03131
03132 return bignorm(z);
03133 }
03134
03135 static VALUE
03136 check_shiftdown(VALUE y, VALUE x)
03137 {
03138 if (!RBIGNUM_LEN(x)) return INT2FIX(0);
03139 if (RBIGNUM_LEN(y) > SIZEOF_LONG / SIZEOF_BDIGITS) {
03140 return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(-1);
03141 }
03142 return Qnil;
03143 }
03144
03145
03146
03147
03148
03149
03150
03151
03152 VALUE
03153 rb_big_lshift(VALUE x, VALUE y)
03154 {
03155 long shift;
03156 int neg = 0;
03157
03158 for (;;) {
03159 if (FIXNUM_P(y)) {
03160 shift = FIX2LONG(y);
03161 if (shift < 0) {
03162 neg = 1;
03163 shift = -shift;
03164 }
03165 break;
03166 }
03167 else if (TYPE(y) == T_BIGNUM) {
03168 if (!RBIGNUM_SIGN(y)) {
03169 VALUE t = check_shiftdown(y, x);
03170 if (!NIL_P(t)) return t;
03171 neg = 1;
03172 }
03173 shift = big2ulong(y, "long", TRUE);
03174 break;
03175 }
03176 y = rb_to_int(y);
03177 }
03178
03179 x = neg ? big_rshift(x, shift) : big_lshift(x, shift);
03180 return bignorm(x);
03181 }
03182
03183 static VALUE
03184 big_lshift(VALUE x, unsigned long shift)
03185 {
03186 BDIGIT *xds, *zds;
03187 long s1 = shift/BITSPERDIG;
03188 int s2 = (int)(shift%BITSPERDIG);
03189 VALUE z;
03190 BDIGIT_DBL num = 0;
03191 long len, i;
03192
03193 len = RBIGNUM_LEN(x);
03194 z = bignew(len+s1+1, RBIGNUM_SIGN(x));
03195 zds = BDIGITS(z);
03196 for (i=0; i<s1; i++) {
03197 *zds++ = 0;
03198 }
03199 xds = BDIGITS(x);
03200 for (i=0; i<len; i++) {
03201 num = num | (BDIGIT_DBL)*xds++<<s2;
03202 *zds++ = BIGLO(num);
03203 num = BIGDN(num);
03204 }
03205 *zds = BIGLO(num);
03206 return z;
03207 }
03208
03209
03210
03211
03212
03213
03214
03215
03216 VALUE
03217 rb_big_rshift(VALUE x, VALUE y)
03218 {
03219 long shift;
03220 int neg = 0;
03221
03222 for (;;) {
03223 if (FIXNUM_P(y)) {
03224 shift = FIX2LONG(y);
03225 if (shift < 0) {
03226 neg = 1;
03227 shift = -shift;
03228 }
03229 break;
03230 }
03231 else if (TYPE(y) == T_BIGNUM) {
03232 if (RBIGNUM_SIGN(y)) {
03233 VALUE t = check_shiftdown(y, x);
03234 if (!NIL_P(t)) return t;
03235 }
03236 else {
03237 neg = 1;
03238 }
03239 shift = big2ulong(y, "long", TRUE);
03240 break;
03241 }
03242 y = rb_to_int(y);
03243 }
03244
03245 x = neg ? big_lshift(x, shift) : big_rshift(x, shift);
03246 return bignorm(x);
03247 }
03248
03249 static VALUE
03250 big_rshift(VALUE x, unsigned long shift)
03251 {
03252 BDIGIT *xds, *zds;
03253 long s1 = shift/BITSPERDIG;
03254 int s2 = (int)(shift%BITSPERDIG);
03255 VALUE z;
03256 BDIGIT_DBL num = 0;
03257 long i, j;
03258 volatile VALUE save_x;
03259
03260 if (s1 > RBIGNUM_LEN(x)) {
03261 if (RBIGNUM_SIGN(x))
03262 return INT2FIX(0);
03263 else
03264 return INT2FIX(-1);
03265 }
03266 if (!RBIGNUM_SIGN(x)) {
03267 save_x = x = rb_big_clone(x);
03268 get2comp(x);
03269 }
03270 xds = BDIGITS(x);
03271 i = RBIGNUM_LEN(x); j = i - s1;
03272 if (j == 0) {
03273 if (RBIGNUM_SIGN(x)) return INT2FIX(0);
03274 else return INT2FIX(-1);
03275 }
03276 z = bignew(j, RBIGNUM_SIGN(x));
03277 if (!RBIGNUM_SIGN(x)) {
03278 num = ((BDIGIT_DBL)~0) << BITSPERDIG;
03279 }
03280 zds = BDIGITS(z);
03281 while (i--, j--) {
03282 num = (num | xds[i]) >> s2;
03283 zds[j] = BIGLO(num);
03284 num = BIGUP(xds[i]);
03285 }
03286 if (!RBIGNUM_SIGN(x)) {
03287 get2comp(z);
03288 }
03289 return z;
03290 }
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311 static VALUE
03312 rb_big_aref(VALUE x, VALUE y)
03313 {
03314 BDIGIT *xds;
03315 BDIGIT_DBL num;
03316 VALUE shift;
03317 long i, s1, s2;
03318
03319 if (TYPE(y) == T_BIGNUM) {
03320 if (!RBIGNUM_SIGN(y))
03321 return INT2FIX(0);
03322 bigtrunc(y);
03323 if (RBIGNUM_LEN(y) > DIGSPERLONG) {
03324 out_of_range:
03325 return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
03326 }
03327 shift = big2ulong(y, "long", FALSE);
03328 }
03329 else {
03330 i = NUM2LONG(y);
03331 if (i < 0) return INT2FIX(0);
03332 shift = (VALUE)i;
03333 }
03334 s1 = shift/BITSPERDIG;
03335 s2 = shift%BITSPERDIG;
03336
03337 if (s1 >= RBIGNUM_LEN(x)) goto out_of_range;
03338 if (!RBIGNUM_SIGN(x)) {
03339 xds = BDIGITS(x);
03340 i = 0; num = 1;
03341 while (num += ~xds[i], ++i <= s1) {
03342 num = BIGDN(num);
03343 }
03344 }
03345 else {
03346 num = BDIGITS(x)[s1];
03347 }
03348 if (num & ((BDIGIT_DBL)1<<s2))
03349 return INT2FIX(1);
03350 return INT2FIX(0);
03351 }
03352
03353
03354
03355
03356
03357
03358
03359
03360 static VALUE
03361 rb_big_hash(VALUE x)
03362 {
03363 st_index_t hash;
03364
03365 hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM_LEN(x)) ^ RBIGNUM_SIGN(x);
03366 return INT2FIX(hash);
03367 }
03368
03369
03370
03371
03372
03373 static VALUE
03374 rb_big_coerce(VALUE x, VALUE y)
03375 {
03376 if (FIXNUM_P(y)) {
03377 return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
03378 }
03379 else if (TYPE(y) == T_BIGNUM) {
03380 return rb_assoc_new(y, x);
03381 }
03382 else {
03383 rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
03384 rb_obj_classname(y));
03385 }
03386
03387 return Qnil;
03388 }
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399 static VALUE
03400 rb_big_abs(VALUE x)
03401 {
03402 if (!RBIGNUM_SIGN(x)) {
03403 x = rb_big_clone(x);
03404 RBIGNUM_SET_SIGN(x, 1);
03405 }
03406 return x;
03407 }
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421 static VALUE
03422 rb_big_size(VALUE big)
03423 {
03424 return LONG2FIX(RBIGNUM_LEN(big)*SIZEOF_BDIGITS);
03425 }
03426
03427
03428
03429
03430
03431
03432
03433
03434 static VALUE
03435 rb_big_odd_p(VALUE num)
03436 {
03437 if (BDIGITS(num)[0] & 1) {
03438 return Qtrue;
03439 }
03440 return Qfalse;
03441 }
03442
03443
03444
03445
03446
03447
03448
03449
03450 static VALUE
03451 rb_big_even_p(VALUE num)
03452 {
03453 if (BDIGITS(num)[0] & 1) {
03454 return Qfalse;
03455 }
03456 return Qtrue;
03457 }
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477 void
03478 Init_Bignum(void)
03479 {
03480 rb_cBignum = rb_define_class("Bignum", rb_cInteger);
03481
03482 rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
03483 rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
03484 rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
03485 rb_define_method(rb_cBignum, "+", rb_big_plus, 1);
03486 rb_define_method(rb_cBignum, "-", rb_big_minus, 1);
03487 rb_define_method(rb_cBignum, "*", rb_big_mul, 1);
03488 rb_define_method(rb_cBignum, "/", rb_big_div, 1);
03489 rb_define_method(rb_cBignum, "%", rb_big_modulo, 1);
03490 rb_define_method(rb_cBignum, "div", rb_big_idiv, 1);
03491 rb_define_method(rb_cBignum, "divmod", rb_big_divmod, 1);
03492 rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
03493 rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
03494 rb_define_method(rb_cBignum, "fdiv", rb_big_fdiv, 1);
03495 rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
03496 rb_define_method(rb_cBignum, "&", rb_big_and, 1);
03497 rb_define_method(rb_cBignum, "|", rb_big_or, 1);
03498 rb_define_method(rb_cBignum, "^", rb_big_xor, 1);
03499 rb_define_method(rb_cBignum, "~", rb_big_neg, 0);
03500 rb_define_method(rb_cBignum, "<<", rb_big_lshift, 1);
03501 rb_define_method(rb_cBignum, ">>", rb_big_rshift, 1);
03502 rb_define_method(rb_cBignum, "[]", rb_big_aref, 1);
03503
03504 rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
03505 rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
03506 rb_define_method(rb_cBignum, ">", big_gt, 1);
03507 rb_define_method(rb_cBignum, ">=", big_ge, 1);
03508 rb_define_method(rb_cBignum, "<", big_lt, 1);
03509 rb_define_method(rb_cBignum, "<=", big_le, 1);
03510 rb_define_method(rb_cBignum, "===", rb_big_eq, 1);
03511 rb_define_method(rb_cBignum, "eql?", rb_big_eql, 1);
03512 rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
03513 rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
03514 rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
03515 rb_define_method(rb_cBignum, "magnitude", rb_big_abs, 0);
03516 rb_define_method(rb_cBignum, "size", rb_big_size, 0);
03517 rb_define_method(rb_cBignum, "odd?", rb_big_odd_p, 0);
03518 rb_define_method(rb_cBignum, "even?", rb_big_even_p, 0);
03519
03520 power_cache_init();
03521 }
03522