Guest User

Untitled

a guest
May 25th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 47.41 KB | None | 0 0
  1. /**********************************************************************
  2.  
  3. bignum.c -
  4.  
  5. $Author: shyouhei $
  6. $Date: 2008-08-04 14:05:38 +0900 (Mon, 04 Aug 2008) $
  7. created at: Fri Jun 10 00:48:55 JST 1994
  8.  
  9. Copyright (C) 1993-2003 Yukihiro Matsumoto
  10.  
  11. **********************************************************************/
  12.  
  13. #include "ruby.h"
  14. #include "rubysig.h"
  15.  
  16. #include <math.h>
  17. #include <float.h>
  18. #include <ctype.h>
  19. #ifdef HAVE_IEEEFP_H
  20. #include <ieeefp.h>
  21. #endif
  22.  
  23. VALUE rb_cBignum;
  24.  
  25. #if defined __MINGW32__
  26. #define USHORT _USHORT
  27. #endif
  28.  
  29. #define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
  30. #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
  31. #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
  32. #define DIGSPERLONG ((unsigned int)(SIZEOF_LONG/SIZEOF_BDIGITS))
  33. #if HAVE_LONG_LONG
  34. # define DIGSPERLL ((unsigned int)(SIZEOF_LONG_LONG/SIZEOF_BDIGITS))
  35. #endif
  36. #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
  37. #define BIGDN(x) RSHIFT(x,BITSPERDIG)
  38. #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
  39. #define BDIGMAX ((BDIGIT)-1)
  40.  
  41. #define BIGZEROP(x) (RBIGNUM(x)->len == 0 || \
  42. (BDIGITS(x)[0] == 0 && \
  43. (RBIGNUM(x)->len == 1 || bigzero_p(x))))
  44.  
  45. static int bigzero_p(VALUE);
  46. static int
  47. bigzero_p(x)
  48. VALUE x;
  49. {
  50. long i;
  51. for (i = 0; i < RBIGNUM(x)->len; ++i) {
  52. if (BDIGITS(x)[i]) return 0;
  53. }
  54. return 1;
  55. }
  56.  
  57. static VALUE
  58. bignew_1(klass, len, sign)
  59. VALUE klass;
  60. long len;
  61. int sign;
  62. {
  63. NEWOBJ(big, struct RBignum);
  64. OBJSETUP(big, klass, T_BIGNUM);
  65. big->sign = sign?1:0;
  66. big->len = len;
  67. big->digits = ALLOC_N(BDIGIT, len);
  68.  
  69. return (VALUE)big;
  70. }
  71.  
  72. #define bignew(len,sign) bignew_1(rb_cBignum,len,sign)
  73.  
  74. VALUE
  75. rb_big_clone(x)
  76. VALUE x;
  77. {
  78. VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign);
  79.  
  80. MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM(x)->len);
  81. return z;
  82. }
  83.  
  84. /* modify a bignum by 2's complement */
  85. static void
  86. get2comp(x)
  87. VALUE x;
  88. {
  89. long i = RBIGNUM(x)->len;
  90. BDIGIT *ds = BDIGITS(x);
  91. BDIGIT_DBL num;
  92.  
  93. if (!i) return;
  94. while (i--) ds[i] = ~ds[i];
  95. i = 0; num = 1;
  96. do {
  97. num += ds[i];
  98. ds[i++] = BIGLO(num);
  99. num = BIGDN(num);
  100. } while (i < RBIGNUM(x)->len);
  101. if (num != 0) {
  102. REALLOC_N(RBIGNUM(x)->digits, BDIGIT, ++RBIGNUM(x)->len);
  103. ds = BDIGITS(x);
  104. ds[RBIGNUM(x)->len-1] = RBIGNUM(x)->sign ? ~0 : 1;
  105. }
  106. }
  107.  
  108. void
  109. rb_big_2comp(x) /* get 2's complement */
  110. VALUE x;
  111. {
  112. get2comp(x);
  113. }
  114.  
  115. static VALUE
  116. bigtrunc(x)
  117. VALUE x;
  118. {
  119. long len = RBIGNUM(x)->len;
  120. BDIGIT *ds = BDIGITS(x);
  121.  
  122. if (len == 0) return x;
  123. while (--len && !ds[len]);
  124. RBIGNUM(x)->len = ++len;
  125. return x;
  126. }
  127.  
  128. static VALUE
  129. bigfixize(x)
  130. VALUE x;
  131. {
  132. long len = RBIGNUM(x)->len;
  133. BDIGIT *ds = BDIGITS(x);
  134.  
  135. if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
  136. long num = 0;
  137. while (len--) {
  138. num = BIGUP(num) + ds[len];
  139. }
  140. if (num >= 0) {
  141. if (RBIGNUM(x)->sign) {
  142. if (POSFIXABLE(num)) return LONG2FIX(num);
  143. }
  144. else {
  145. if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
  146. }
  147. }
  148. }
  149. return x;
  150. }
  151.  
  152. static VALUE
  153. bignorm(x)
  154. VALUE x;
  155. {
  156. if (!FIXNUM_P(x) && TYPE(x) == T_BIGNUM) {
  157. x = bigfixize(bigtrunc(x));
  158. }
  159. return x;
  160. }
  161.  
  162. VALUE
  163. rb_big_norm(x)
  164. VALUE x;
  165. {
  166. return bignorm(x);
  167. }
  168.  
  169. VALUE
  170. rb_uint2big(n)
  171. unsigned long n;
  172. {
  173. BDIGIT_DBL num = n;
  174. long i = 0;
  175. BDIGIT *digits;
  176. VALUE big;
  177.  
  178. big = bignew(DIGSPERLONG, 1);
  179. digits = BDIGITS(big);
  180. while (i < DIGSPERLONG) {
  181. digits[i++] = BIGLO(num);
  182. num = BIGDN(num);
  183. }
  184.  
  185. i = DIGSPERLONG;
  186. while (--i && !digits[i]) ;
  187. RBIGNUM(big)->len = i+1;
  188. return big;
  189. }
  190.  
  191. VALUE
  192. rb_int2big(n)
  193. long n;
  194. {
  195. long neg = 0;
  196. VALUE big;
  197.  
  198. if (n < 0) {
  199. n = -n;
  200. neg = 1;
  201. }
  202. big = rb_uint2big(n);
  203. if (neg) {
  204. RBIGNUM(big)->sign = 0;
  205. }
  206. return big;
  207. }
  208.  
  209. VALUE
  210. rb_uint2inum(n)
  211. unsigned long n;
  212. {
  213. if (POSFIXABLE(n)) return LONG2FIX(n);
  214. return rb_uint2big(n);
  215. }
  216.  
  217. VALUE
  218. rb_int2inum(n)
  219. long n;
  220. {
  221. if (FIXABLE(n)) return LONG2FIX(n);
  222. return rb_int2big(n);
  223. }
  224.  
  225. #ifdef HAVE_LONG_LONG
  226.  
  227. void
  228. rb_quad_pack(buf, val)
  229. char *buf;
  230. VALUE val;
  231. {
  232. LONG_LONG q;
  233.  
  234. val = rb_to_int(val);
  235. if (FIXNUM_P(val)) {
  236. q = FIX2LONG(val);
  237. }
  238. else {
  239. long len = RBIGNUM(val)->len;
  240. BDIGIT *ds;
  241.  
  242. if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS)
  243. rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
  244. ds = BDIGITS(val);
  245. q = 0;
  246. while (len--) {
  247. q = BIGUP(q);
  248. q += ds[len];
  249. }
  250. if (!RBIGNUM(val)->sign) q = -q;
  251. }
  252. memcpy(buf, (char*)&q, SIZEOF_LONG_LONG);
  253. }
  254.  
  255. VALUE
  256. rb_quad_unpack(buf, sign)
  257. const char *buf;
  258. int sign;
  259. {
  260. unsigned LONG_LONG q;
  261. long neg = 0;
  262. long i;
  263. BDIGIT *digits;
  264. VALUE big;
  265.  
  266. memcpy(&q, buf, SIZEOF_LONG_LONG);
  267. if (sign) {
  268. if (FIXABLE((LONG_LONG)q)) return LONG2FIX((LONG_LONG)q);
  269. if ((LONG_LONG)q < 0) {
  270. q = -(LONG_LONG)q;
  271. neg = 1;
  272. }
  273. }
  274. else {
  275. if (POSFIXABLE(q)) return LONG2FIX(q);
  276. }
  277.  
  278. i = 0;
  279. big = bignew(DIGSPERLL, 1);
  280. digits = BDIGITS(big);
  281. while (i < DIGSPERLL) {
  282. digits[i++] = BIGLO(q);
  283. q = BIGDN(q);
  284. }
  285.  
  286. i = DIGSPERLL;
  287. while (i-- && !digits[i]) ;
  288. RBIGNUM(big)->len = i+1;
  289.  
  290. if (neg) {
  291. RBIGNUM(big)->sign = 0;
  292. }
  293. return bignorm(big);
  294. }
  295.  
  296. #else
  297.  
  298. #define QUAD_SIZE 8
  299.  
  300. void
  301. rb_quad_pack(buf, val)
  302. char *buf;
  303. VALUE val;
  304. {
  305. long len;
  306.  
  307. memset(buf, 0, QUAD_SIZE);
  308. val = rb_to_int(val);
  309. if (FIXNUM_P(val)) {
  310. val = rb_int2big(FIX2LONG(val));
  311. }
  312. len = RBIGNUM(val)->len * SIZEOF_BDIGITS;
  313. if (len > QUAD_SIZE) {
  314. rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
  315. }
  316. memcpy(buf, (char*)BDIGITS(val), len);
  317. if (!RBIGNUM(val)->sign) {
  318. len = QUAD_SIZE;
  319. while (len--) {
  320. *buf = ~*buf;
  321. buf++;
  322. }
  323. }
  324. }
  325.  
  326. #define BNEG(b) (RSHIFT(((BDIGIT*)b)[QUAD_SIZE/SIZEOF_BDIGITS-1],BITSPERDIG-1) != 0)
  327.  
  328. VALUE
  329. rb_quad_unpack(buf, sign)
  330. const char *buf;
  331. int sign;
  332. {
  333. VALUE big = bignew(QUAD_SIZE/SIZEOF_BDIGITS, 1);
  334.  
  335. memcpy((char*)BDIGITS(big), buf, QUAD_SIZE);
  336. if (sign && BNEG(buf)) {
  337. long len = QUAD_SIZE;
  338. char *tmp = (char*)BDIGITS(big);
  339.  
  340. RBIGNUM(big)->sign = 0;
  341. while (len--) {
  342. *tmp = ~*tmp;
  343. tmp++;
  344. }
  345. }
  346.  
  347. return bignorm(big);
  348. }
  349.  
  350. #endif
  351.  
  352. VALUE
  353. rb_cstr_to_inum(str, base, badcheck)
  354. const char *str;
  355. int base;
  356. int badcheck;
  357. {
  358. const char *s = str;
  359. char *end;
  360. char sign = 1, nondigit = 0;
  361. int c;
  362. BDIGIT_DBL num;
  363. long len, blen = 1;
  364. long i;
  365. VALUE z;
  366. BDIGIT *zds;
  367.  
  368. #define conv_digit(c) \
  369. (!ISASCII(c) ? -1 : \
  370. isdigit(c) ? ((c) - '0') : \
  371. islower(c) ? ((c) - 'a' + 10) : \
  372. isupper(c) ? ((c) - 'A' + 10) : \
  373. -1)
  374.  
  375. if (!str) {
  376. if (badcheck) goto bad;
  377. return INT2FIX(0);
  378. }
  379. if (badcheck) {
  380. while (ISSPACE(*str)) str++;
  381. }
  382. else {
  383. while (ISSPACE(*str) || *str == '_') str++;
  384. }
  385.  
  386. if (str[0] == '+') {
  387. str++;
  388. }
  389. else if (str[0] == '-') {
  390. str++;
  391. sign = 0;
  392. }
  393. if (str[0] == '+' || str[0] == '-') {
  394. if (badcheck) goto bad;
  395. return INT2FIX(0);
  396. }
  397. if (base <= 0) {
  398. if (str[0] == '0') {
  399. switch (str[1]) {
  400. case 'x': case 'X':
  401. base = 16;
  402. break;
  403. case 'b': case 'B':
  404. base = 2;
  405. break;
  406. case 'o': case 'O':
  407. base = 8;
  408. break;
  409. case 'd': case 'D':
  410. base = 10;
  411. break;
  412. default:
  413. base = 8;
  414. }
  415. }
  416. else if (base < -1) {
  417. base = -base;
  418. }
  419. else {
  420. base = 10;
  421. }
  422. }
  423. switch (base) {
  424. case 2:
  425. len = 1;
  426. if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
  427. str += 2;
  428. }
  429. break;
  430. case 3:
  431. len = 2;
  432. break;
  433. case 8:
  434. if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
  435. str += 2;
  436. }
  437. case 4: case 5: case 6: case 7:
  438. len = 3;
  439. break;
  440. case 10:
  441. if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
  442. str += 2;
  443. }
  444. case 9: case 11: case 12: case 13: case 14: case 15:
  445. len = 4;
  446. break;
  447. case 16:
  448. len = 4;
  449. if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
  450. str += 2;
  451. }
  452. break;
  453. default:
  454. if (base < 2 || 36 < base) {
  455. rb_raise(rb_eArgError, "illegal radix %d", base);
  456. }
  457. if (base <= 32) {
  458. len = 5;
  459. }
  460. else {
  461. len = 6;
  462. }
  463. break;
  464. }
  465. if (*str == '0') { /* squeeze preceeding 0s */
  466. int us = 0;
  467. while ((c = *++str) == '0' || c == '_') {
  468. if (c == '_') {
  469. if (++us >= 2)
  470. break;
  471. } else
  472. us = 0;
  473. }
  474. if (!(c = *str) || ISSPACE(c)) --str;
  475. }
  476. c = *str;
  477. c = conv_digit(c);
  478. if (c < 0 || c >= base) {
  479. if (badcheck) goto bad;
  480. return INT2FIX(0);
  481. }
  482. len *= strlen(str)*sizeof(char);
  483.  
  484. if (len <= (sizeof(VALUE)*CHAR_BIT)) {
  485. unsigned long val = strtoul((char*)str, &end, base);
  486.  
  487. if (*end == '_') goto bigparse;
  488. if (badcheck) {
  489. if (end == str) goto bad; /* no number */
  490. while (*end && ISSPACE(*end)) end++;
  491. if (*end) goto bad; /* trailing garbage */
  492. }
  493.  
  494. if (POSFIXABLE(val)) {
  495. if (sign) return LONG2FIX(val);
  496. else {
  497. long result = -(long)val;
  498. return LONG2FIX(result);
  499. }
  500. }
  501. else {
  502. VALUE big = rb_uint2big(val);
  503. RBIGNUM(big)->sign = sign;
  504. return bignorm(big);
  505. }
  506. }
  507. bigparse:
  508. len = (len/BITSPERDIG)+1;
  509. if (badcheck && *str == '_') goto bad;
  510.  
  511. z = bignew(len, sign);
  512. zds = BDIGITS(z);
  513. for (i=len;i--;) zds[i]=0;
  514. while ((c = *str++) != 0) {
  515. if (c == '_') {
  516. if (nondigit) {
  517. if (badcheck) goto bad;
  518. break;
  519. }
  520. nondigit = c;
  521. continue;
  522. }
  523. else if ((c = conv_digit(c)) < 0) {
  524. break;
  525. }
  526. if (c >= base) break;
  527. nondigit = 0;
  528. i = 0;
  529. num = c;
  530. for (;;) {
  531. while (i<blen) {
  532. num += (BDIGIT_DBL)zds[i]*base;
  533. zds[i++] = BIGLO(num);
  534. num = BIGDN(num);
  535. }
  536. if (num) {
  537. blen++;
  538. continue;
  539. }
  540. break;
  541. }
  542. }
  543. if (badcheck) {
  544. str--;
  545. if (s+1 < str && str[-1] == '_') goto bad;
  546. while (*str && ISSPACE(*str)) str++;
  547. if (*str) {
  548. bad:
  549. rb_invalid_str(s, "Integer");
  550. }
  551. }
  552.  
  553. return bignorm(z);
  554. }
  555.  
  556. VALUE
  557. rb_str_to_inum(str, base, badcheck)
  558. VALUE str;
  559. int base;
  560. int badcheck;
  561. {
  562. char *s;
  563. long len;
  564.  
  565. StringValue(str);
  566. if (badcheck) {
  567. s = StringValueCStr(str);
  568. }
  569. else {
  570. s = RSTRING(str)->ptr;
  571. }
  572. if (s) {
  573. len = RSTRING(str)->len;
  574. if (s[len]) { /* no sentinel somehow */
  575. char *p = ALLOCA_N(char, len+1);
  576.  
  577. MEMCPY(p, s, char, len);
  578. p[len] = '\0';
  579. s = p;
  580. }
  581. }
  582. return rb_cstr_to_inum(s, base, badcheck);
  583. }
  584.  
  585. #if HAVE_LONG_LONG
  586.  
  587. VALUE
  588. rb_ull2big(n)
  589. unsigned LONG_LONG n;
  590. {
  591. BDIGIT_DBL num = n;
  592. long i = 0;
  593. BDIGIT *digits;
  594. VALUE big;
  595.  
  596. big = bignew(DIGSPERLL, 1);
  597. digits = BDIGITS(big);
  598. while (i < DIGSPERLL) {
  599. digits[i++] = BIGLO(num);
  600. num = BIGDN(num);
  601. }
  602.  
  603. i = DIGSPERLL;
  604. while (i-- && !digits[i]) ;
  605. RBIGNUM(big)->len = i+1;
  606. return big;
  607. }
  608.  
  609. VALUE
  610. rb_ll2big(n)
  611. LONG_LONG n;
  612. {
  613. long neg = 0;
  614. VALUE big;
  615.  
  616. if (n < 0) {
  617. n = -n;
  618. neg = 1;
  619. }
  620. big = rb_ull2big(n);
  621. if (neg) {
  622. RBIGNUM(big)->sign = 0;
  623. }
  624. return big;
  625. }
  626.  
  627. VALUE
  628. rb_ull2inum(n)
  629. unsigned LONG_LONG n;
  630. {
  631. if (POSFIXABLE(n)) return LONG2FIX(n);
  632. return rb_ull2big(n);
  633. }
  634.  
  635. VALUE
  636. rb_ll2inum(n)
  637. LONG_LONG n;
  638. {
  639. if (FIXABLE(n)) return LONG2FIX(n);
  640. return rb_ll2big(n);
  641. }
  642.  
  643. #endif /* HAVE_LONG_LONG */
  644.  
  645. VALUE
  646. rb_cstr2inum(str, base)
  647. const char *str;
  648. int base;
  649. {
  650. return rb_cstr_to_inum(str, base, base==0);
  651. }
  652.  
  653. VALUE
  654. rb_str2inum(str, base)
  655. VALUE str;
  656. int base;
  657. {
  658. return rb_str_to_inum(str, base, base==0);
  659. }
  660.  
  661. const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  662. VALUE
  663. rb_big2str0(x, base, trim)
  664. VALUE x;
  665. int base;
  666. int trim;
  667. {
  668. volatile VALUE t;
  669. BDIGIT *ds;
  670. long i, j, hbase;
  671. VALUE ss;
  672. char *s;
  673.  
  674. if (FIXNUM_P(x)) {
  675. return rb_fix2str(x, base);
  676. }
  677. i = RBIGNUM(x)->len;
  678. if (BIGZEROP(x)) {
  679. return rb_str_new2("0");
  680. }
  681. if (i >= LONG_MAX/SIZEOF_BDIGITS/CHAR_BIT) {
  682. rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
  683. }
  684. j = SIZEOF_BDIGITS*CHAR_BIT*i;
  685. switch (base) {
  686. case 2: break;
  687. case 3:
  688. j = j * 53L / 84 + 1;
  689. break;
  690. case 4: case 5: case 6: case 7:
  691. j = (j + 1) / 2;
  692. break;
  693. case 8: case 9:
  694. j = (j + 2) / 3;
  695. break;
  696. case 10: case 11: case 12: case 13: case 14: case 15:
  697. j = j * 28L / 93 + 1;
  698. break;
  699. case 16: case 17: case 18: case 19: case 20: case 21:
  700. case 22: case 23: case 24: case 25: case 26: case 27:
  701. case 28: case 29: case 30: case 31:
  702. j = (j + 3) / 4;
  703. break;
  704. case 32: case 33: case 34: case 35: case 36:
  705. j = (j + 4) / 5;
  706. break;
  707. default:
  708. rb_raise(rb_eArgError, "illegal radix %d", base);
  709. break;
  710. }
  711. j++; /* space for sign */
  712.  
  713. hbase = base * base;
  714. #if SIZEOF_BDIGITS > 2
  715. hbase *= hbase;
  716. #endif
  717.  
  718. t = rb_big_clone(x);
  719. ds = BDIGITS(t);
  720. ss = rb_str_new(0, j+1);
  721. s = RSTRING(ss)->ptr;
  722.  
  723. s[0] = RBIGNUM(x)->sign ? '+' : '-';
  724. TRAP_BEG;
  725. while (i && j > 1) {
  726. long k = i;
  727. BDIGIT_DBL num = 0;
  728.  
  729. while (k--) {
  730. num = BIGUP(num) + ds[k];
  731. ds[k] = (BDIGIT)(num / hbase);
  732. num %= hbase;
  733. }
  734. if (trim && ds[i-1] == 0) i--;
  735. k = SIZEOF_BDIGITS;
  736. while (k--) {
  737. s[--j] = ruby_digitmap[num % base];
  738. num /= base;
  739. if (!trim && j <= 1) break;
  740. if (trim && i == 0 && num == 0) break;
  741. }
  742. }
  743. if (trim) {while (s[j] == '0') j++;}
  744. i = RSTRING(ss)->len - j;
  745. if (RBIGNUM(x)->sign) {
  746. memmove(s, s+j, i);
  747. RSTRING(ss)->len = i-1;
  748. }
  749. else {
  750. memmove(s+1, s+j, i);
  751. RSTRING(ss)->len = i;
  752. }
  753. s[RSTRING(ss)->len] = '\0';
  754. TRAP_END;
  755.  
  756. return ss;
  757. }
  758.  
  759. VALUE
  760. rb_big2str(VALUE x, int base)
  761. {
  762. return rb_big2str0(x, base, Qtrue);
  763. }
  764.  
  765. /*
  766. * call-seq:
  767. * big.to_s(base=10) => string
  768. *
  769. * Returns a string containing the representation of <i>big</i> radix
  770. * <i>base</i> (2 through 36).
  771. *
  772. * 12345654321.to_s #=> "12345654321"
  773. * 12345654321.to_s(2) #=> "1011011111110110111011110000110001"
  774. * 12345654321.to_s(8) #=> "133766736061"
  775. * 12345654321.to_s(16) #=> "2dfdbbc31"
  776. * 78546939656932.to_s(36) #=> "rubyrules"
  777. */
  778.  
  779. static VALUE
  780. rb_big_to_s(argc, argv, x)
  781. int argc;
  782. VALUE *argv;
  783. VALUE x;
  784. {
  785. VALUE b;
  786. int base;
  787.  
  788. rb_scan_args(argc, argv, "01", &b);
  789. if (argc == 0) base = 10;
  790. else base = NUM2INT(b);
  791. return rb_big2str(x, base);
  792. }
  793.  
  794. static unsigned long
  795. big2ulong(x, type)
  796. VALUE x;
  797. char *type;
  798. {
  799. long len = RBIGNUM(x)->len;
  800. BDIGIT_DBL num;
  801. BDIGIT *ds;
  802.  
  803. if (len > SIZEOF_LONG/SIZEOF_BDIGITS)
  804. rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
  805. ds = BDIGITS(x);
  806. num = 0;
  807. while (len--) {
  808. num = BIGUP(num);
  809. num += ds[len];
  810. }
  811. return num;
  812. }
  813.  
  814. unsigned long
  815. rb_big2ulong_pack(x)
  816. VALUE x;
  817. {
  818. unsigned long num = big2ulong(x, "unsigned long");
  819. if (!RBIGNUM(x)->sign) {
  820. return -num;
  821. }
  822. return num;
  823. }
  824.  
  825. unsigned long
  826. rb_big2ulong(x)
  827. VALUE x;
  828. {
  829. unsigned long num = big2ulong(x, "unsigned long");
  830.  
  831. if (!RBIGNUM(x)->sign) {
  832. if ((long)num < 0) {
  833. rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
  834. }
  835. return -num;
  836. }
  837. return num;
  838. }
  839.  
  840. long
  841. rb_big2long(x)
  842. VALUE x;
  843. {
  844. unsigned long num = big2ulong(x, "long");
  845.  
  846. if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) {
  847. rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
  848. }
  849. if (!RBIGNUM(x)->sign) return -(long)num;
  850. return num;
  851. }
  852.  
  853. #if HAVE_LONG_LONG
  854.  
  855. static unsigned LONG_LONG
  856. big2ull(x, type)
  857. VALUE x;
  858. char *type;
  859. {
  860. long len = RBIGNUM(x)->len;
  861. BDIGIT_DBL num;
  862. BDIGIT *ds;
  863.  
  864. if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS)
  865. rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
  866. ds = BDIGITS(x);
  867. num = 0;
  868. while (len--) {
  869. num = BIGUP(num);
  870. num += ds[len];
  871. }
  872. return num;
  873. }
  874.  
  875. unsigned LONG_LONG
  876. rb_big2ull(x)
  877. VALUE x;
  878. {
  879. unsigned LONG_LONG num = big2ull(x, "unsigned long long");
  880.  
  881. if (!RBIGNUM(x)->sign) return -num;
  882. return num;
  883. }
  884.  
  885. LONG_LONG
  886. rb_big2ll(x)
  887. VALUE x;
  888. {
  889. unsigned LONG_LONG num = big2ull(x, "long long");
  890.  
  891. if ((LONG_LONG)num < 0 && (RBIGNUM(x)->sign
  892. || (LONG_LONG)num != LLONG_MIN)) {
  893. rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
  894. }
  895. if (!RBIGNUM(x)->sign) return -(LONG_LONG)num;
  896. return num;
  897. }
  898.  
  899. #endif /* HAVE_LONG_LONG */
  900.  
  901. static VALUE
  902. dbl2big(d)
  903. double d;
  904. {
  905. long i = 0;
  906. BDIGIT c;
  907. BDIGIT *digits;
  908. VALUE z;
  909. double u = (d < 0)?-d:d;
  910.  
  911. if (isinf(d)) {
  912. rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
  913. }
  914. if (isnan(d)) {
  915. rb_raise(rb_eFloatDomainError, "NaN");
  916. }
  917.  
  918. while (!POSFIXABLE(u) || 0 != (long)u) {
  919. u /= (double)(BIGRAD);
  920. i++;
  921. }
  922. z = bignew(i, d>=0);
  923. digits = BDIGITS(z);
  924. while (i--) {
  925. u *= BIGRAD;
  926. c = (BDIGIT)u;
  927. u -= c;
  928. digits[i] = c;
  929. }
  930.  
  931. return z;
  932. }
  933.  
  934. VALUE
  935. rb_dbl2big(d)
  936. double d;
  937. {
  938. return bignorm(dbl2big(d));
  939. }
  940.  
  941. static double
  942. big2dbl(x)
  943. VALUE x;
  944. {
  945. double d = 0.0;
  946. long i = RBIGNUM(x)->len;
  947. BDIGIT *ds = BDIGITS(x);
  948.  
  949. while (i--) {
  950. d = ds[i] + BIGRAD*d;
  951. }
  952. if (!RBIGNUM(x)->sign) d = -d;
  953. return d;
  954. }
  955.  
  956. double
  957. rb_big2dbl(x)
  958. VALUE x;
  959. {
  960. double d = big2dbl(x);
  961.  
  962. if (isinf(d)) {
  963. rb_warn("Bignum out of Float range");
  964. d = HUGE_VAL;
  965. }
  966. return d;
  967. }
  968.  
  969. /*
  970. * call-seq:
  971. * big.to_f -> float
  972. *
  973. * Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't
  974. * fit in a <code>Float</code>, the result is infinity.
  975. *
  976. */
  977.  
  978. static VALUE
  979. rb_big_to_f(x)
  980. VALUE x;
  981. {
  982. return rb_float_new(rb_big2dbl(x));
  983. }
  984.  
  985. /*
  986. * call-seq:
  987. * big <=> numeric => -1, 0, +1
  988. *
  989. * Comparison---Returns -1, 0, or +1 depending on whether <i>big</i> is
  990. * less than, equal to, or greater than <i>numeric</i>. This is the
  991. * basis for the tests in <code>Comparable</code>.
  992. *
  993. */
  994.  
  995. static VALUE
  996. rb_big_cmp(x, y)
  997. VALUE x, y;
  998. {
  999. long xlen = RBIGNUM(x)->len;
  1000.  
  1001. switch (TYPE(y)) {
  1002. case T_FIXNUM:
  1003. y = rb_int2big(FIX2LONG(y));
  1004. break;
  1005.  
  1006. case T_BIGNUM:
  1007. break;
  1008.  
  1009. case T_FLOAT:
  1010. return rb_dbl_cmp(rb_big2dbl(x), RFLOAT(y)->value);
  1011.  
  1012. default:
  1013. return rb_num_coerce_cmp(x, y);
  1014. }
  1015.  
  1016. if (RBIGNUM(x)->sign > RBIGNUM(y)->sign) return INT2FIX(1);
  1017. if (RBIGNUM(x)->sign < RBIGNUM(y)->sign) return INT2FIX(-1);
  1018. if (xlen < RBIGNUM(y)->len)
  1019. return (RBIGNUM(x)->sign) ? INT2FIX(-1) : INT2FIX(1);
  1020. if (xlen > RBIGNUM(y)->len)
  1021. return (RBIGNUM(x)->sign) ? INT2FIX(1) : INT2FIX(-1);
  1022.  
  1023. while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen]));
  1024. if (-1 == xlen) return INT2FIX(0);
  1025. return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ?
  1026. (RBIGNUM(x)->sign ? INT2FIX(1) : INT2FIX(-1)) :
  1027. (RBIGNUM(x)->sign ? INT2FIX(-1) : INT2FIX(1));
  1028. }
  1029.  
  1030. /*
  1031. * call-seq:
  1032. * big == obj => true or false
  1033. *
  1034. * Returns <code>true</code> only if <i>obj</i> has the same value
  1035. * as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
  1036. * requires <i>obj</i> to be a <code>Bignum</code>.
  1037. *
  1038. * 68719476736 == 68719476736.0 #=> true
  1039. */
  1040.  
  1041. static VALUE
  1042. rb_big_eq(x, y)
  1043. VALUE x, y;
  1044. {
  1045. switch (TYPE(y)) {
  1046. case T_FIXNUM:
  1047. y = rb_int2big(FIX2LONG(y));
  1048. break;
  1049. case T_BIGNUM:
  1050. break;
  1051. case T_FLOAT:
  1052. {
  1053. volatile double a, b;
  1054.  
  1055. a = RFLOAT(y)->value;
  1056. if (isnan(a)) return Qfalse;
  1057. b = rb_big2dbl(x);
  1058. return (a == b)?Qtrue:Qfalse;
  1059. }
  1060. default:
  1061. return rb_equal(y, x);
  1062. }
  1063. if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
  1064. if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
  1065. if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
  1066. return Qtrue;
  1067. }
  1068.  
  1069. /*
  1070. * call-seq:
  1071. * big.eql?(obj) => true or false
  1072. *
  1073. * Returns <code>true</code> only if <i>obj</i> is a
  1074. * <code>Bignum</code> with the same value as <i>big</i>. Contrast this
  1075. * with <code>Bignum#==</code>, which performs type conversions.
  1076. *
  1077. * 68719476736.eql?(68719476736.0) #=> false
  1078. */
  1079.  
  1080. static VALUE
  1081. rb_big_eql(x, y)
  1082. VALUE x, y;
  1083. {
  1084. if (TYPE(y) != T_BIGNUM) return Qfalse;
  1085. if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
  1086. if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
  1087. if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
  1088. return Qtrue;
  1089. }
  1090.  
  1091. /*
  1092. * call-seq:
  1093. * -big => other_big
  1094. *
  1095. * Unary minus (returns a new Bignum whose value is 0-big)
  1096. */
  1097.  
  1098. static VALUE
  1099. rb_big_uminus(x)
  1100. VALUE x;
  1101. {
  1102. VALUE z = rb_big_clone(x);
  1103.  
  1104. RBIGNUM(z)->sign = !RBIGNUM(x)->sign;
  1105.  
  1106. return bignorm(z);
  1107. }
  1108.  
  1109. /*
  1110. * call-seq:
  1111. * ~big => integer
  1112. *
  1113. * Inverts the bits in big. As Bignums are conceptually infinite
  1114. * length, the result acts as if it had an infinite number of one
  1115. * bits to the left. In hex representations, this is displayed
  1116. * as two periods to the left of the digits.
  1117. *
  1118. * sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA"
  1119. */
  1120.  
  1121. static VALUE
  1122. rb_big_neg(x)
  1123. VALUE x;
  1124. {
  1125. VALUE z = rb_big_clone(x);
  1126. long i;
  1127. BDIGIT *ds;
  1128.  
  1129. if (!RBIGNUM(x)->sign) get2comp(z);
  1130. ds = BDIGITS(z);
  1131. i = RBIGNUM(x)->len;
  1132. if (!i) return INT2FIX(~0);
  1133. while (i--) ds[i] = ~ds[i];
  1134. RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
  1135. if (RBIGNUM(x)->sign) get2comp(z);
  1136.  
  1137. return bignorm(z);
  1138. }
  1139.  
  1140. static VALUE
  1141. bigsub(x, y)
  1142. VALUE x, y;
  1143. {
  1144. VALUE z = 0;
  1145. BDIGIT *zds;
  1146. BDIGIT_DBL_SIGNED num;
  1147. long i = RBIGNUM(x)->len;
  1148.  
  1149. /* if x is larger than y, swap */
  1150. if (RBIGNUM(x)->len < RBIGNUM(y)->len) {
  1151. z = x; x = y; y = z; /* swap x y */
  1152. }
  1153. else if (RBIGNUM(x)->len == RBIGNUM(y)->len) {
  1154. while (i > 0) {
  1155. i--;
  1156. if (BDIGITS(x)[i] > BDIGITS(y)[i]) {
  1157. break;
  1158. }
  1159. if (BDIGITS(x)[i] < BDIGITS(y)[i]) {
  1160. z = x; x = y; y = z; /* swap x y */
  1161. break;
  1162. }
  1163. }
  1164. }
  1165.  
  1166. z = bignew(RBIGNUM(x)->len, z==0);
  1167. zds = BDIGITS(z);
  1168.  
  1169. for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
  1170. num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i];
  1171. zds[i] = BIGLO(num);
  1172. num = BIGDN(num);
  1173. }
  1174. while (num && i < RBIGNUM(x)->len) {
  1175. num += BDIGITS(x)[i];
  1176. zds[i++] = BIGLO(num);
  1177. num = BIGDN(num);
  1178. }
  1179. while (i < RBIGNUM(x)->len) {
  1180. zds[i] = BDIGITS(x)[i];
  1181. i++;
  1182. }
  1183.  
  1184. return z;
  1185. }
  1186.  
  1187. static VALUE
  1188. bigadd(x, y, sign)
  1189. VALUE x, y;
  1190. int sign;
  1191. {
  1192. VALUE z;
  1193. BDIGIT_DBL num;
  1194. long i, len;
  1195.  
  1196. sign = (sign == RBIGNUM(y)->sign);
  1197. if (RBIGNUM(x)->sign != sign) {
  1198. if (sign) return bigsub(y, x);
  1199. return bigsub(x, y);
  1200. }
  1201.  
  1202. if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
  1203. len = RBIGNUM(x)->len + 1;
  1204. z = x; x = y; y = z;
  1205. }
  1206. else {
  1207. len = RBIGNUM(y)->len + 1;
  1208. }
  1209. z = bignew(len, sign);
  1210.  
  1211. len = RBIGNUM(x)->len;
  1212. for (i = 0, num = 0; i < len; i++) {
  1213. num += (BDIGIT_DBL)BDIGITS(x)[i] + BDIGITS(y)[i];
  1214. BDIGITS(z)[i] = BIGLO(num);
  1215. num = BIGDN(num);
  1216. }
  1217. len = RBIGNUM(y)->len;
  1218. while (num && i < len) {
  1219. num += BDIGITS(y)[i];
  1220. BDIGITS(z)[i++] = BIGLO(num);
  1221. num = BIGDN(num);
  1222. }
  1223. while (i < len) {
  1224. BDIGITS(z)[i] = BDIGITS(y)[i];
  1225. i++;
  1226. }
  1227. BDIGITS(z)[i] = (BDIGIT)num;
  1228.  
  1229. return z;
  1230. }
  1231.  
  1232. /*
  1233. * call-seq:
  1234. * big + other => Numeric
  1235. *
  1236. * Adds big and other, returning the result.
  1237. */
  1238.  
  1239. VALUE
  1240. rb_big_plus(x, y)
  1241. VALUE x, y;
  1242. {
  1243. switch (TYPE(y)) {
  1244. case T_FIXNUM:
  1245. y = rb_int2big(FIX2LONG(y));
  1246. /* fall through */
  1247. case T_BIGNUM:
  1248. return bignorm(bigadd(x, y, 1));
  1249.  
  1250. case T_FLOAT:
  1251. return rb_float_new(rb_big2dbl(x) + RFLOAT(y)->value);
  1252.  
  1253. default:
  1254. return rb_num_coerce_bin(x, y);
  1255. }
  1256. }
  1257.  
  1258. /*
  1259. * call-seq:
  1260. * big - other => Numeric
  1261. *
  1262. * Subtracts other from big, returning the result.
  1263. */
  1264.  
  1265. VALUE
  1266. rb_big_minus(x, y)
  1267. VALUE x, y;
  1268. {
  1269. switch (TYPE(y)) {
  1270. case T_FIXNUM:
  1271. y = rb_int2big(FIX2LONG(y));
  1272. /* fall through */
  1273. case T_BIGNUM:
  1274. return bignorm(bigadd(x, y, 0));
  1275.  
  1276. case T_FLOAT:
  1277. return rb_float_new(rb_big2dbl(x) - RFLOAT(y)->value);
  1278.  
  1279. default:
  1280. return rb_num_coerce_bin(x, y);
  1281. }
  1282. }
  1283.  
  1284. VALUE
  1285. rb_big_mul0(x, y)
  1286. VALUE x, y;
  1287. {
  1288. long i, j;
  1289. BDIGIT_DBL n = 0;
  1290. VALUE z;
  1291. BDIGIT *zds;
  1292.  
  1293. if (FIXNUM_P(x)) x = rb_int2big(FIX2LONG(x));
  1294. switch (TYPE(y)) {
  1295. case T_FIXNUM:
  1296. y = rb_int2big(FIX2LONG(y));
  1297. break;
  1298.  
  1299. case T_BIGNUM:
  1300. break;
  1301.  
  1302. case T_FLOAT:
  1303. return rb_float_new(rb_big2dbl(x) * RFLOAT(y)->value);
  1304.  
  1305. default:
  1306. return rb_num_coerce_bin(x, y);
  1307. }
  1308.  
  1309. j = RBIGNUM(x)->len + RBIGNUM(y)->len + 1;
  1310. z = bignew(j, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
  1311. zds = BDIGITS(z);
  1312. while (j--) zds[j] = 0;
  1313. for (i = 0; i < RBIGNUM(x)->len; i++) {
  1314. BDIGIT_DBL dd = BDIGITS(x)[i];
  1315. if (dd == 0) continue;
  1316. n = 0;
  1317. for (j = 0; j < RBIGNUM(y)->len; j++) {
  1318. BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * BDIGITS(y)[j];
  1319. n = zds[i + j] + ee;
  1320. if (ee) zds[i + j] = BIGLO(n);
  1321. n = BIGDN(n);
  1322. }
  1323. if (n) {
  1324. zds[i + j] = n;
  1325. }
  1326. }
  1327.  
  1328. return z;
  1329. }
  1330.  
  1331. /*
  1332. * call-seq:
  1333. * big * other => Numeric
  1334. *
  1335. * Multiplies big and other, returning the result.
  1336. */
  1337.  
  1338. VALUE
  1339. rb_big_mul(x, y)
  1340. VALUE x, y;
  1341. {
  1342. return bignorm(rb_big_mul0(x, y));
  1343. }
  1344.  
  1345. static void
  1346. bigdivrem(x, y, divp, modp)
  1347. VALUE x, y;
  1348. VALUE *divp, *modp;
  1349. {
  1350. long nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
  1351. long i, j;
  1352. VALUE yy, z;
  1353. BDIGIT *xds, *yds, *zds, *tds;
  1354. BDIGIT_DBL t2;
  1355. BDIGIT_DBL_SIGNED num;
  1356. BDIGIT dd, q;
  1357.  
  1358. if (BIGZEROP(y)) rb_num_zerodiv();
  1359. yds = BDIGITS(y);
  1360. if (nx < ny || (nx == ny && BDIGITS(x)[nx - 1] < BDIGITS(y)[ny - 1])) {
  1361. if (divp) *divp = rb_int2big(0);
  1362. if (modp) *modp = x;
  1363. return;
  1364. }
  1365. xds = BDIGITS(x);
  1366. if (ny == 1) {
  1367. dd = yds[0];
  1368. z = rb_big_clone(x);
  1369. zds = BDIGITS(z);
  1370. t2 = 0; i = nx;
  1371. while (i--) {
  1372. t2 = BIGUP(t2) + zds[i];
  1373. zds[i] = (BDIGIT)(t2 / dd);
  1374. t2 %= dd;
  1375. }
  1376. RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign;
  1377. if (modp) {
  1378. *modp = rb_uint2big((unsigned long)t2);
  1379. RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
  1380. }
  1381. if (divp) *divp = z;
  1382. return;
  1383. }
  1384. z = bignew(nx==ny?nx+2:nx+1, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
  1385. zds = BDIGITS(z);
  1386. if (nx==ny) zds[nx+1] = 0;
  1387. while (!yds[ny-1]) ny--;
  1388.  
  1389. dd = 0;
  1390. q = yds[ny-1];
  1391. while ((q & (1U<<(BITSPERDIG-1))) == 0) {
  1392. q <<= 1;
  1393. dd++;
  1394. }
  1395. if (dd) {
  1396. yy = rb_big_clone(y);
  1397. tds = BDIGITS(yy);
  1398. j = 0;
  1399. t2 = 0;
  1400. while (j<ny) {
  1401. t2 += (BDIGIT_DBL)yds[j]<<dd;
  1402. tds[j++] = BIGLO(t2);
  1403. t2 = BIGDN(t2);
  1404. }
  1405. yds = tds;
  1406. j = 0;
  1407. t2 = 0;
  1408. while (j<nx) {
  1409. t2 += (BDIGIT_DBL)xds[j]<<dd;
  1410. zds[j++] = BIGLO(t2);
  1411. t2 = BIGDN(t2);
  1412. }
  1413. zds[j] = (BDIGIT)t2;
  1414. }
  1415. else {
  1416. zds[nx] = 0;
  1417. j = nx;
  1418. while (j--) zds[j] = xds[j];
  1419. }
  1420.  
  1421. j = nx==ny?nx+1:nx;
  1422. do {
  1423. if (zds[j] == yds[ny-1]) q = BIGRAD-1;
  1424. else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
  1425. if (q) {
  1426. i = 0; num = 0; t2 = 0;
  1427. do { /* multiply and subtract */
  1428. BDIGIT_DBL ee;
  1429. t2 += (BDIGIT_DBL)yds[i] * q;
  1430. ee = num - BIGLO(t2);
  1431. num = (BDIGIT_DBL)zds[j - ny + i] + ee;
  1432. if (ee) zds[j - ny + i] = BIGLO(num);
  1433. num = BIGDN(num);
  1434. t2 = BIGDN(t2);
  1435. } while (++i < ny);
  1436. num += zds[j - ny + i] - t2;/* borrow from high digit; don't update */
  1437. while (num) { /* "add back" required */
  1438. i = 0; num = 0; q--;
  1439. do {
  1440. BDIGIT_DBL ee = num + yds[i];
  1441. num = (BDIGIT_DBL)zds[j - ny + i] + ee;
  1442. if (ee) zds[j - ny + i] = BIGLO(num);
  1443. num = BIGDN(num);
  1444. } while (++i < ny);
  1445. num--;
  1446. }
  1447. }
  1448. zds[j] = q;
  1449. } while (--j >= ny);
  1450. if (divp) { /* move quotient down in z */
  1451. *divp = rb_big_clone(z);
  1452. zds = BDIGITS(*divp);
  1453. j = (nx==ny ? nx+2 : nx+1) - ny;
  1454. for (i = 0;i < j;i++) zds[i] = zds[i+ny];
  1455. RBIGNUM(*divp)->len = i;
  1456. }
  1457. if (modp) { /* normalize remainder */
  1458. *modp = rb_big_clone(z);
  1459. zds = BDIGITS(*modp);
  1460. while (--ny && !zds[ny]); ++ny;
  1461. if (dd) {
  1462. t2 = 0; i = ny;
  1463. while(i--) {
  1464. t2 = (t2 | zds[i]) >> dd;
  1465. q = zds[i];
  1466. zds[i] = BIGLO(t2);
  1467. t2 = BIGUP(q);
  1468. }
  1469. }
  1470. RBIGNUM(*modp)->len = ny;
  1471. RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
  1472. }
  1473. }
  1474.  
  1475. static void
  1476. bigdivmod(x, y, divp, modp)
  1477. VALUE x, y;
  1478. VALUE *divp, *modp;
  1479. {
  1480. VALUE mod;
  1481.  
  1482. bigdivrem(x, y, divp, &mod);
  1483. if (RBIGNUM(x)->sign != RBIGNUM(y)->sign && !BIGZEROP(mod)) {
  1484. if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
  1485. if (modp) *modp = bigadd(mod, y, 1);
  1486. }
  1487. else {
  1488. if (divp) *divp = *divp;
  1489. if (modp) *modp = mod;
  1490. }
  1491. }
  1492.  
  1493. /*
  1494. * call-seq:
  1495. * big / other => Numeric
  1496. * big.div(other) => Numeric
  1497. *
  1498. * Divides big by other, returning the result.
  1499. */
  1500.  
  1501. static VALUE
  1502. rb_big_div(x, y)
  1503. VALUE x, y;
  1504. {
  1505. VALUE z;
  1506.  
  1507. switch (TYPE(y)) {
  1508. case T_FIXNUM:
  1509. y = rb_int2big(FIX2LONG(y));
  1510. break;
  1511.  
  1512. case T_BIGNUM:
  1513. break;
  1514.  
  1515. default:
  1516. return rb_num_coerce_bin(x, y);
  1517. }
  1518. bigdivmod(x, y, &z, 0);
  1519.  
  1520. return bignorm(z);
  1521. }
  1522.  
  1523. /*
  1524. * call-seq:
  1525. * big % other => Numeric
  1526. * big.modulo(other) => Numeric
  1527. *
  1528. * Returns big modulo other. See Numeric.divmod for more
  1529. * information.
  1530. */
  1531.  
  1532. static VALUE
  1533. rb_big_modulo(x, y)
  1534. VALUE x, y;
  1535. {
  1536. VALUE z;
  1537.  
  1538. switch (TYPE(y)) {
  1539. case T_FIXNUM:
  1540. y = rb_int2big(FIX2LONG(y));
  1541. break;
  1542.  
  1543. case T_BIGNUM:
  1544. break;
  1545.  
  1546. default:
  1547. return rb_num_coerce_bin(x, y);
  1548. }
  1549. bigdivmod(x, y, 0, &z);
  1550.  
  1551. return bignorm(z);
  1552. }
  1553.  
  1554. /*
  1555. * call-seq:
  1556. * big.remainder(numeric) => number
  1557. *
  1558. * Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
  1559. *
  1560. * -1234567890987654321.remainder(13731) #=> -6966
  1561. * -1234567890987654321.remainder(13731.24) #=> -9906.22531493148
  1562. */
  1563. static VALUE
  1564. rb_big_remainder(x, y)
  1565. VALUE x, y;
  1566. {
  1567. VALUE z;
  1568.  
  1569. switch (TYPE(y)) {
  1570. case T_FIXNUM:
  1571. y = rb_int2big(FIX2LONG(y));
  1572. break;
  1573.  
  1574. case T_BIGNUM:
  1575. break;
  1576.  
  1577. default:
  1578. return rb_num_coerce_bin(x, y);
  1579. }
  1580. bigdivrem(x, y, 0, &z);
  1581.  
  1582. return bignorm(z);
  1583. }
  1584.  
  1585. static int
  1586. bdigbitsize(BDIGIT x)
  1587. {
  1588. int size = 1;
  1589. int nb = BITSPERDIG / 2;
  1590. BDIGIT bits = (~0 << nb);
  1591.  
  1592. if (!x) return 0;
  1593. while (x > 1) {
  1594. if (x & bits) {
  1595. size += nb;
  1596. x >>= nb;
  1597. }
  1598. x &= ~bits;
  1599. nb /= 2;
  1600. bits >>= nb;
  1601. }
  1602.  
  1603. return size;
  1604. }
  1605.  
  1606. static VALUE big_lshift _((VALUE, unsigned long));
  1607. static VALUE big_rshift _((VALUE, unsigned long));
  1608.  
  1609. static VALUE big_shift(x, n)
  1610. VALUE x;
  1611. int n;
  1612. {
  1613. if (n < 0)
  1614. return big_lshift(x, (unsigned int)n);
  1615. else if (n > 0)
  1616. return big_rshift(x, (unsigned int)n);
  1617. return x;
  1618. }
  1619.  
  1620. /*
  1621. * call-seq:
  1622. * big.divmod(numeric) => array
  1623. *
  1624. * See <code>Numeric#divmod</code>.
  1625. *
  1626. */
  1627. VALUE
  1628. rb_big_divmod(x, y)
  1629. VALUE x, y;
  1630. {
  1631. VALUE div, mod;
  1632.  
  1633. switch (TYPE(y)) {
  1634. case T_FIXNUM:
  1635. y = rb_int2big(FIX2LONG(y));
  1636. break;
  1637.  
  1638. case T_BIGNUM:
  1639. break;
  1640.  
  1641. default:
  1642. return rb_num_coerce_bin(x, y);
  1643. }
  1644. bigdivmod(x, y, &div, &mod);
  1645.  
  1646. return rb_assoc_new(bignorm(div), bignorm(mod));
  1647. }
  1648.  
  1649. /*
  1650. * call-seq:
  1651. * big.quo(numeric) -> float
  1652. * big.fdiv(numeric) -> float
  1653. *
  1654. * Returns the floating point result of dividing <i>big</i> by
  1655. * <i>numeric</i>.
  1656. *
  1657. * -1234567890987654321.quo(13731) #=> -89910996357705.5
  1658. * -1234567890987654321.quo(13731.24) #=> -89909424858035.7
  1659. *
  1660. */
  1661.  
  1662. static VALUE
  1663. rb_big_quo(x, y)
  1664. VALUE x, y;
  1665. {
  1666. double dx = big2dbl(x);
  1667. double dy;
  1668.  
  1669. if (isinf(dx)) {
  1670. #define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)
  1671. VALUE z;
  1672. int ex, ey;
  1673.  
  1674. ex = (RBIGNUM(bigtrunc(x))->len - 1) * BITSPERDIG;
  1675. ex += bdigbitsize(BDIGITS(x)[RBIGNUM(x)->len - 1]);
  1676. ex -= 2 * DBL_BIGDIG * BITSPERDIG;
  1677. if (ex) x = big_shift(x, ex);
  1678.  
  1679. switch (TYPE(y)) {
  1680. case T_FIXNUM:
  1681. y = rb_int2big(FIX2LONG(y));
  1682. case T_BIGNUM: {
  1683. ey = (RBIGNUM(bigtrunc(y))->len - 1) * BITSPERDIG;
  1684. ey += bdigbitsize(BDIGITS(y)[RBIGNUM(y)->len - 1]);
  1685. ey -= DBL_BIGDIG * BITSPERDIG;
  1686. if (ey) y = big_shift(y, ey);
  1687. bignum:
  1688. bigdivrem(x, y, &z, 0);
  1689. return rb_float_new(ldexp(big2dbl(z), ex - ey));
  1690. }
  1691. case T_FLOAT:
  1692. y = dbl2big(ldexp(frexp(RFLOAT(y)->value, &ey), DBL_MANT_DIG));
  1693. ey -= DBL_MANT_DIG;
  1694. goto bignum;
  1695. }
  1696. }
  1697. switch (TYPE(y)) {
  1698. case T_FIXNUM:
  1699. dy = (double)FIX2LONG(y);
  1700. break;
  1701.  
  1702. case T_BIGNUM:
  1703. dy = rb_big2dbl(y);
  1704. break;
  1705.  
  1706. case T_FLOAT:
  1707. dy = RFLOAT(y)->value;
  1708. break;
  1709.  
  1710. default:
  1711. return rb_num_coerce_bin(x, y);
  1712. }
  1713. return rb_float_new(dx / dy);
  1714. }
  1715.  
  1716. static VALUE
  1717. bigsqr(x)
  1718. VALUE x;
  1719. {
  1720. long len = RBIGNUM(x)->len, k = len / 2, i;
  1721. VALUE a, b, a2, z;
  1722. BDIGIT_DBL num;
  1723.  
  1724. if (len < 4000 / BITSPERDIG) {
  1725. return rb_big_mul0(x, x);
  1726. }
  1727.  
  1728. a = bignew(len - k, 1);
  1729. MEMCPY(BDIGITS(a), BDIGITS(x) + k, BDIGIT, len - k);
  1730. b = bignew(k, 1);
  1731. MEMCPY(BDIGITS(b), BDIGITS(x), BDIGIT, k);
  1732.  
  1733. a2 = bigtrunc(bigsqr(a));
  1734. z = bigsqr(b);
  1735. REALLOC_N(RBIGNUM(z)->digits, BDIGIT, (len = 2 * k + RBIGNUM(a2)->len) + 1);
  1736. while (RBIGNUM(z)->len < 2 * k) BDIGITS(z)[RBIGNUM(z)->len++] = 0;
  1737. MEMCPY(BDIGITS(z) + 2 * k, BDIGITS(a2), BDIGIT, RBIGNUM(a2)->len);
  1738. RBIGNUM(z)->len = len;
  1739. a2 = bigtrunc(rb_big_mul0(a, b));
  1740. len = RBIGNUM(a2)->len;
  1741. TRAP_BEG;
  1742. for (i = 0, num = 0; i < len; i++) {
  1743. num += (BDIGIT_DBL)BDIGITS(z)[i + k] + ((BDIGIT_DBL)BDIGITS(a2)[i] << 1);
  1744. BDIGITS(z)[i + k] = BIGLO(num);
  1745. num = BIGDN(num);
  1746. }
  1747. TRAP_END;
  1748. if (num) {
  1749. len = RBIGNUM(z)->len;
  1750. for (i += k; i < len && num; ++i) {
  1751. num += (BDIGIT_DBL)BDIGITS(z)[i];
  1752. BDIGITS(z)[i] = BIGLO(num);
  1753. num = BIGDN(num);
  1754. }
  1755. if (num) {
  1756. BDIGITS(z)[RBIGNUM(z)->len++] = BIGLO(num);
  1757. }
  1758. }
  1759. return bigtrunc(z);
  1760. }
  1761.  
  1762. /*
  1763. * call-seq:
  1764. * big ** exponent #=> numeric
  1765. *
  1766. * Raises _big_ to the _exponent_ power (which may be an integer, float,
  1767. * or anything that will coerce to a number). The result may be
  1768. * a Fixnum, Bignum, or Float
  1769. *
  1770. * 123456789 ** 2 #=> 15241578750190521
  1771. * 123456789 ** 1.2 #=> 5126464716.09932
  1772. * 123456789 ** -2 #=> 6.5610001194102e-17
  1773. */
  1774.  
  1775. VALUE
  1776. rb_big_pow(x, y)
  1777. VALUE x, y;
  1778. {
  1779. double d;
  1780. long yy;
  1781.  
  1782. if (y == INT2FIX(0)) return INT2FIX(1);
  1783. switch (TYPE(y)) {
  1784. case T_FLOAT:
  1785. d = RFLOAT(y)->value;
  1786. break;
  1787.  
  1788. case T_BIGNUM:
  1789. rb_warn("in a**b, b may be too big");
  1790. d = rb_big2dbl(y);
  1791. break;
  1792.  
  1793. case T_FIXNUM:
  1794. yy = FIX2LONG(y);
  1795. if (yy > 0) {
  1796. VALUE z = 0;
  1797. long mask;
  1798. const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
  1799.  
  1800. if ((RBIGNUM(x)->len > BIGLEN_LIMIT) ||
  1801. (RBIGNUM(x)->len > BIGLEN_LIMIT / yy)) {
  1802. rb_warn("in a**b, b may be too big");
  1803. d = (double)yy;
  1804. break;
  1805. }
  1806. for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
  1807. if (z) z = bigtrunc(bigsqr(z));
  1808. if (yy & mask) {
  1809. z = z ? bigtrunc(rb_big_mul0(z, x)) : x;
  1810. }
  1811. }
  1812. return bignorm(z);
  1813. }
  1814. d = (double)yy;
  1815. break;
  1816.  
  1817. default:
  1818. return rb_num_coerce_bin(x, y);
  1819. }
  1820. return rb_float_new(pow(rb_big2dbl(x), d));
  1821. }
  1822.  
  1823. /*
  1824. * call-seq:
  1825. * big & numeric => integer
  1826. *
  1827. * Performs bitwise +and+ between _big_ and _numeric_.
  1828. */
  1829.  
  1830. VALUE
  1831. rb_big_and(xx, yy)
  1832. VALUE xx, yy;
  1833. {
  1834. volatile VALUE x, y, z;
  1835. BDIGIT *ds1, *ds2, *zds;
  1836. long i, l1, l2;
  1837. char sign;
  1838.  
  1839. x = xx;
  1840. y = rb_to_int(yy);
  1841. if (FIXNUM_P(y)) {
  1842. y = rb_int2big(FIX2LONG(y));
  1843. }
  1844. if (!RBIGNUM(y)->sign) {
  1845. y = rb_big_clone(y);
  1846. get2comp(y);
  1847. }
  1848. if (!RBIGNUM(x)->sign) {
  1849. x = rb_big_clone(x);
  1850. get2comp(x);
  1851. }
  1852. if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
  1853. l1 = RBIGNUM(y)->len;
  1854. l2 = RBIGNUM(x)->len;
  1855. ds1 = BDIGITS(y);
  1856. ds2 = BDIGITS(x);
  1857. sign = RBIGNUM(y)->sign;
  1858. }
  1859. else {
  1860. l1 = RBIGNUM(x)->len;
  1861. l2 = RBIGNUM(y)->len;
  1862. ds1 = BDIGITS(x);
  1863. ds2 = BDIGITS(y);
  1864. sign = RBIGNUM(x)->sign;
  1865. }
  1866. z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign);
  1867. zds = BDIGITS(z);
  1868.  
  1869. for (i=0; i<l1; i++) {
  1870. zds[i] = ds1[i] & ds2[i];
  1871. }
  1872. for (; i<l2; i++) {
  1873. zds[i] = sign?0:ds2[i];
  1874. }
  1875. if (!RBIGNUM(z)->sign) get2comp(z);
  1876. return bignorm(z);
  1877. }
  1878.  
  1879. /*
  1880. * call-seq:
  1881. * big | numeric => integer
  1882. *
  1883. * Performs bitwise +or+ between _big_ and _numeric_.
  1884. */
  1885.  
  1886. VALUE
  1887. rb_big_or(xx, yy)
  1888. VALUE xx, yy;
  1889. {
  1890. volatile VALUE x, y, z;
  1891. BDIGIT *ds1, *ds2, *zds;
  1892. long i, l1, l2;
  1893. char sign;
  1894.  
  1895. x = xx;
  1896. y = rb_to_int(yy);
  1897. if (FIXNUM_P(y)) {
  1898. y = rb_int2big(FIX2LONG(y));
  1899. }
  1900. if (!RBIGNUM(y)->sign) {
  1901. y = rb_big_clone(y);
  1902. get2comp(y);
  1903. }
  1904. if (!RBIGNUM(x)->sign) {
  1905. x = rb_big_clone(x);
  1906. get2comp(x);
  1907. }
  1908. if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
  1909. l1 = RBIGNUM(y)->len;
  1910. l2 = RBIGNUM(x)->len;
  1911. ds1 = BDIGITS(y);
  1912. ds2 = BDIGITS(x);
  1913. sign = RBIGNUM(y)->sign;
  1914. }
  1915. else {
  1916. l1 = RBIGNUM(x)->len;
  1917. l2 = RBIGNUM(y)->len;
  1918. ds1 = BDIGITS(x);
  1919. ds2 = BDIGITS(y);
  1920. sign = RBIGNUM(x)->sign;
  1921. }
  1922. z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
  1923. zds = BDIGITS(z);
  1924.  
  1925. for (i=0; i<l1; i++) {
  1926. zds[i] = ds1[i] | ds2[i];
  1927. }
  1928. for (; i<l2; i++) {
  1929. zds[i] = sign?ds2[i]:(BIGRAD-1);
  1930. }
  1931. if (!RBIGNUM(z)->sign) get2comp(z);
  1932.  
  1933. return bignorm(z);
  1934. }
  1935.  
  1936. /*
  1937. * call-seq:
  1938. * big ^ numeric => integer
  1939. *
  1940. * Performs bitwise +exclusive or+ between _big_ and _numeric_.
  1941. */
  1942.  
  1943. VALUE
  1944. rb_big_xor(xx, yy)
  1945. VALUE xx, yy;
  1946. {
  1947. volatile VALUE x, y;
  1948. VALUE z;
  1949. BDIGIT *ds1, *ds2, *zds;
  1950. long i, l1, l2;
  1951. char sign;
  1952.  
  1953. x = xx;
  1954. y = rb_to_int(yy);
  1955. if (FIXNUM_P(y)) {
  1956. y = rb_int2big(FIX2LONG(y));
  1957. }
  1958. if (!RBIGNUM(y)->sign) {
  1959. y = rb_big_clone(y);
  1960. get2comp(y);
  1961. }
  1962. if (!RBIGNUM(x)->sign) {
  1963. x = rb_big_clone(x);
  1964. get2comp(x);
  1965. }
  1966. if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
  1967. l1 = RBIGNUM(y)->len;
  1968. l2 = RBIGNUM(x)->len;
  1969. ds1 = BDIGITS(y);
  1970. ds2 = BDIGITS(x);
  1971. sign = RBIGNUM(y)->sign;
  1972. }
  1973. else {
  1974. l1 = RBIGNUM(x)->len;
  1975. l2 = RBIGNUM(y)->len;
  1976. ds1 = BDIGITS(x);
  1977. ds2 = BDIGITS(y);
  1978. sign = RBIGNUM(x)->sign;
  1979. }
  1980. RBIGNUM(x)->sign = RBIGNUM(x)->sign?1:0;
  1981. RBIGNUM(y)->sign = RBIGNUM(y)->sign?1:0;
  1982. z = bignew(l2, !(RBIGNUM(x)->sign ^ RBIGNUM(y)->sign));
  1983. zds = BDIGITS(z);
  1984.  
  1985. for (i=0; i<l1; i++) {
  1986. zds[i] = ds1[i] ^ ds2[i];
  1987. }
  1988. for (; i<l2; i++) {
  1989. zds[i] = sign?ds2[i]:~ds2[i];
  1990. }
  1991. if (!RBIGNUM(z)->sign) get2comp(z);
  1992.  
  1993. return bignorm(z);
  1994. }
  1995.  
  1996. static VALUE
  1997. check_shiftdown(VALUE y, VALUE x)
  1998. {
  1999. if (!RBIGNUM(x)->len) return INT2FIX(0);
  2000. if (RBIGNUM(y)->len > SIZEOF_LONG / SIZEOF_BDIGITS) {
  2001. return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(-1);
  2002. }
  2003. return Qnil;
  2004. }
  2005.  
  2006. /*
  2007. * call-seq:
  2008. * big << numeric => integer
  2009. *
  2010. * Shifts big left _numeric_ positions (right if _numeric_ is negative).
  2011. */
  2012.  
  2013. VALUE
  2014. rb_big_lshift(x, y)
  2015. VALUE x, y;
  2016. {
  2017. long shift;
  2018. int neg = 0;
  2019.  
  2020. for (;;) {
  2021. if (FIXNUM_P(y)) {
  2022. shift = FIX2LONG(y);
  2023. if (shift < 0) {
  2024. neg = 1;
  2025. shift = -shift;
  2026. }
  2027. break;
  2028. }
  2029. else if (TYPE(y) == T_BIGNUM) {
  2030. if (!RBIGNUM(y)->sign) {
  2031. VALUE t = check_shiftdown(y, x);
  2032. if (!NIL_P(t)) return t;
  2033. neg = 1;
  2034. }
  2035. shift = big2ulong(y, "long");
  2036. break;
  2037. }
  2038. y = rb_to_int(y);
  2039. }
  2040.  
  2041. if (neg) return big_rshift(x, shift);
  2042. return big_lshift(x, shift);
  2043. }
  2044.  
  2045. static VALUE
  2046. big_lshift(x, shift)
  2047. VALUE x;
  2048. unsigned long shift;
  2049. {
  2050. BDIGIT *xds, *zds;
  2051. long s1 = shift/BITSPERDIG;
  2052. int s2 = shift%BITSPERDIG;
  2053. VALUE z;
  2054. BDIGIT_DBL num = 0;
  2055. long len, i;
  2056.  
  2057. len = RBIGNUM(x)->len;
  2058. z = bignew(len+s1+1, RBIGNUM(x)->sign);
  2059. zds = BDIGITS(z);
  2060. for (i=0; i<s1; i++) {
  2061. *zds++ = 0;
  2062. }
  2063. xds = BDIGITS(x);
  2064. for (i=0; i<len; i++) {
  2065. num = num | (BDIGIT_DBL)*xds++<<s2;
  2066. *zds++ = BIGLO(num);
  2067. num = BIGDN(num);
  2068. }
  2069. *zds = BIGLO(num);
  2070. return bignorm(z);
  2071. }
  2072.  
  2073. /*
  2074. * call-seq:
  2075. * big >> numeric => integer
  2076. *
  2077. * Shifts big right _numeric_ positions (left if _numeric_ is negative).
  2078. */
  2079.  
  2080. VALUE
  2081. rb_big_rshift(x, y)
  2082. VALUE x, y;
  2083. {
  2084. long shift;
  2085. int neg = 0;
  2086.  
  2087. for (;;) {
  2088. if (FIXNUM_P(y)) {
  2089. shift = FIX2LONG(y);
  2090. if (shift < 0) {
  2091. neg = 1;
  2092. shift = -shift;
  2093. }
  2094. break;
  2095. }
  2096. else if (TYPE(y) == T_BIGNUM) {
  2097. if (RBIGNUM(y)->sign) {
  2098. VALUE t = check_shiftdown(y, x);
  2099. if (!NIL_P(t)) return t;
  2100. }
  2101. else {
  2102. neg = 1;
  2103. }
  2104. shift = big2ulong(y, "long");
  2105. break;
  2106. }
  2107. y = rb_to_int(y);
  2108. }
  2109.  
  2110. if (neg) return big_lshift(x, shift);
  2111. return big_rshift(x, shift);
  2112. }
  2113.  
  2114. static VALUE
  2115. big_rshift(x, shift)
  2116. VALUE x;
  2117. unsigned long shift;
  2118. {
  2119. BDIGIT *xds, *zds;
  2120. long s1 = shift/BITSPERDIG;
  2121. int s2 = shift%BITSPERDIG;
  2122. VALUE z;
  2123. BDIGIT_DBL num = 0;
  2124. long i, j;
  2125. volatile VALUE save_x;
  2126.  
  2127. if (s1 > RBIGNUM(x)->len) {
  2128. if (RBIGNUM(x)->sign)
  2129. return INT2FIX(0);
  2130. else
  2131. return INT2FIX(-1);
  2132. }
  2133. if (!RBIGNUM(x)->sign) {
  2134. save_x = x = rb_big_clone(x);
  2135. get2comp(x);
  2136. }
  2137. xds = BDIGITS(x);
  2138. i = RBIGNUM(x)->len; j = i - s1;
  2139. if (j == 0) {
  2140. if (RBIGNUM(x)->sign) return INT2FIX(0);
  2141. else return INT2FIX(-1);
  2142. }
  2143. z = bignew(j, RBIGNUM(x)->sign);
  2144. if (!RBIGNUM(x)->sign) {
  2145. num = ((BDIGIT_DBL)~0) << BITSPERDIG;
  2146. }
  2147. zds = BDIGITS(z);
  2148. while (i--, j--) {
  2149. num = (num | xds[i]) >> s2;
  2150. zds[j] = BIGLO(num);
  2151. num = BIGUP(xds[i]);
  2152. }
  2153. if (!RBIGNUM(x)->sign) {
  2154. get2comp(z);
  2155. }
  2156. return bignorm(z);
  2157. }
  2158.  
  2159. /*
  2160. * call-seq:
  2161. * big[n] -> 0, 1
  2162. *
  2163. * Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
  2164. * representation of <i>big</i>, where <i>big</i>[0] is the least
  2165. * significant bit.
  2166. *
  2167. * a = 9**15
  2168. * 50.downto(0) do |n|
  2169. * print a[n]
  2170. * end
  2171. *
  2172. * <em>produces:</em>
  2173. *
  2174. * 000101110110100000111000011110010100111100010111001
  2175. *
  2176. */
  2177.  
  2178. static VALUE
  2179. rb_big_aref(x, y)
  2180. VALUE x, y;
  2181. {
  2182. BDIGIT *xds;
  2183. BDIGIT_DBL num;
  2184. unsigned long shift;
  2185. long i, s1, s2;
  2186.  
  2187. if (TYPE(y) == T_BIGNUM) {
  2188. if (!RBIGNUM(y)->sign)
  2189. return INT2FIX(0);
  2190. if (RBIGNUM(bigtrunc(y))->len > SIZEOF_LONG/SIZEOF_BDIGITS) {
  2191. out_of_range:
  2192. return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1);
  2193. }
  2194. shift = big2ulong(y, "long");
  2195. }
  2196. else {
  2197. i = NUM2LONG(y);
  2198. if (i < 0) return INT2FIX(0);
  2199. shift = (VALUE)i;
  2200. }
  2201. s1 = shift/BITSPERDIG;
  2202. s2 = shift%BITSPERDIG;
  2203.  
  2204. if (s1 >= RBIGNUM(x)->len) goto out_of_range;
  2205. if (!RBIGNUM(x)->sign) {
  2206. xds = BDIGITS(x);
  2207. i = 0; num = 1;
  2208. while (num += ~xds[i], ++i <= s1) {
  2209. num = BIGDN(num);
  2210. }
  2211. }
  2212. else {
  2213. num = BDIGITS(x)[s1];
  2214. }
  2215. if (num & ((BDIGIT_DBL)1<<s2))
  2216. return INT2FIX(1);
  2217. return INT2FIX(0);
  2218. }
  2219.  
  2220. /*
  2221. * call-seq:
  2222. * big.hash => fixnum
  2223. *
  2224. * Compute a hash based on the value of _big_.
  2225. */
  2226.  
  2227. static VALUE
  2228. rb_big_hash(x)
  2229. VALUE x;
  2230. {
  2231. long i, len, key;
  2232. BDIGIT *digits;
  2233.  
  2234. key = 0; digits = BDIGITS(x); len = RBIGNUM(x)->len;
  2235. for (i=0; i<len; i++) {
  2236. key ^= *digits++;
  2237. }
  2238. return LONG2FIX(key);
  2239. }
  2240.  
  2241. /*
  2242. * MISSING: documentation
  2243. */
  2244.  
  2245. static VALUE
  2246. rb_big_coerce(x, y)
  2247. VALUE x, y;
  2248. {
  2249. if (FIXNUM_P(y)) {
  2250. return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
  2251. }
  2252. else if (TYPE(y) == T_BIGNUM) {
  2253. return rb_assoc_new(y, x);
  2254. }
  2255. else {
  2256. rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
  2257. rb_obj_classname(y));
  2258. }
  2259. /* not reached */
  2260. return Qnil;
  2261. }
  2262.  
  2263. /*
  2264. * call-seq:
  2265. * big.abs -> aBignum
  2266. *
  2267. * Returns the absolute value of <i>big</i>.
  2268. *
  2269. * -1234567890987654321.abs #=> 1234567890987654321
  2270. */
  2271.  
  2272. static VALUE
  2273. rb_big_abs(x)
  2274. VALUE x;
  2275. {
  2276. if (!RBIGNUM(x)->sign) {
  2277. x = rb_big_clone(x);
  2278. RBIGNUM(x)->sign = 1;
  2279. }
  2280. return x;
  2281. }
  2282.  
  2283. VALUE
  2284. rb_big_rand(max, rand_buf)
  2285. VALUE max;
  2286. double *rand_buf;
  2287. {
  2288. VALUE v;
  2289. long len = RBIGNUM(max)->len;
  2290.  
  2291. if (BIGZEROP(max)) {
  2292. return rb_float_new(rand_buf[0]);
  2293. }
  2294. v = bignew(len,1);
  2295. len--;
  2296. BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
  2297. while (len--) {
  2298. BDIGITS(v)[len] = ((BDIGIT)~0) * rand_buf[len];
  2299. }
  2300.  
  2301. return v;
  2302. }
  2303.  
  2304. /*
  2305. * call-seq:
  2306. * big.size -> integer
  2307. *
  2308. * Returns the number of bytes in the machine representation of
  2309. * <i>big</i>.
  2310. *
  2311. * (256**10 - 1).size #=> 12
  2312. * (256**20 - 1).size #=> 20
  2313. * (256**40 - 1).size #=> 40
  2314. */
  2315.  
  2316. static VALUE
  2317. rb_big_size(big)
  2318. VALUE big;
  2319. {
  2320. return LONG2FIX(RBIGNUM(big)->len*SIZEOF_BDIGITS);
  2321. }
  2322.  
  2323. /*
  2324. * Bignum objects hold integers outside the range of
  2325. * Fixnum. Bignum objects are created
  2326. * automatically when integer calculations would otherwise overflow a
  2327. * Fixnum. When a calculation involving
  2328. * Bignum objects returns a result that will fit in a
  2329. * Fixnum, the result is automatically converted.
  2330. *
  2331. * For the purposes of the bitwise operations and <code>[]</code>, a
  2332. * Bignum is treated as if it were an infinite-length
  2333. * bitstring with 2's complement representation.
  2334. *
  2335. * While Fixnum values are immediate, Bignum
  2336. * objects are not---assignment and parameter passing work with
  2337. * references to objects, not the objects themselves.
  2338. *
  2339. */
  2340.  
  2341. void
  2342. Init_Bignum()
  2343. {
  2344. rb_cBignum = rb_define_class("Bignum", rb_cInteger);
  2345.  
  2346. rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
  2347. rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
  2348. rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
  2349. rb_define_method(rb_cBignum, "+", rb_big_plus, 1);
  2350. rb_define_method(rb_cBignum, "-", rb_big_minus, 1);
  2351. rb_define_method(rb_cBignum, "*", rb_big_mul, 1);
  2352. rb_define_method(rb_cBignum, "/", rb_big_div, 1);
  2353. rb_define_method(rb_cBignum, "%", rb_big_modulo, 1);
  2354. rb_define_method(rb_cBignum, "div", rb_big_div, 1);
  2355. rb_define_method(rb_cBignum, "divmod", rb_big_divmod, 1);
  2356. rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
  2357. rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
  2358. rb_define_method(rb_cBignum, "quo", rb_big_quo, 1);
  2359. rb_define_method(rb_cBignum, "fdiv", rb_big_quo, 1);
  2360. rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
  2361. rb_define_method(rb_cBignum, "&", rb_big_and, 1);
  2362. rb_define_method(rb_cBignum, "|", rb_big_or, 1);
  2363. rb_define_method(rb_cBignum, "^", rb_big_xor, 1);
  2364. rb_define_method(rb_cBignum, "~", rb_big_neg, 0);
  2365. rb_define_method(rb_cBignum, "<<", rb_big_lshift, 1);
  2366. rb_define_method(rb_cBignum, ">>", rb_big_rshift, 1);
  2367. rb_define_method(rb_cBignum, "[]", rb_big_aref, 1);
  2368.  
  2369. rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
  2370. rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
  2371. rb_define_method(rb_cBignum, "eql?", rb_big_eql, 1);
  2372. rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
  2373. rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
  2374. rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
  2375. rb_define_method(rb_cBignum, "size", rb_big_size, 0);
  2376. }
Add Comment
Please, Sign In to add comment