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