Advertisement
rg443

javascript bigint

Jan 19th, 2013
415
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // BigInt.js - Arbitrary size integer math package for JavaScript
  2. // http://www.onicos.com/staff/iz/amuse/javascript/expert/BigInt.txt
  3. // Version: 1.0.1
  4. // Licence: GPL
  5. //
  6. // This program is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 2 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. //
  17. // Interfaces:
  18. // x = new BigInt("1234567890123456789012345678901234567890");
  19. // y = new BigInt("0x123456789abcdef0123456789abcdef0");
  20. // z = x.clone();
  21. // z = bigint_uminus(x);
  22. // z = bigint_plus(x, y);
  23. // z = bigint_minus(x, y);
  24. // z = bigint_mul(x, y);
  25. // z = bigint_div(x, y);
  26. // z = bigint_mod(x, y);
  27. // cmp = bigint_cmp(x, y);  /* return -1, 0, or 1 */
  28. // num = bigint_number(x);  /* convert normal number (may be floating) */
  29. //
  30.  
  31. function _BigInt_toString()
  32. {
  33.     return this.toStringBase(10);
  34. }
  35. function _BigInt_toStringBase(base)
  36. {
  37.     var i, j, hbase;
  38.     var t;
  39.     var ds;
  40.     var c;
  41.  
  42.     i = this.len;
  43.     if(i == 0)
  44.       return "0";
  45.     if(i == 1 && !this.digits[0])
  46.       return "0";
  47.  
  48.     switch(base) {
  49.       default:
  50.       case 10:
  51.       j = Math.floor((2*8*i*241)/800)+2;
  52.       hbase = 10000;
  53.       break;
  54.  
  55.       case 16:
  56.       j = Math.floor((2*8*i)/4)+2;
  57.       hbase = 0x10000;
  58.       break;
  59.  
  60.       case 8:
  61.       j = (2*8*i)+2;
  62.       hbase = 010000;
  63.       break;
  64.  
  65.       case 2:
  66.       j = (2*8*i)+2;
  67.       hbase = 020;
  68.       break;
  69.     }
  70.  
  71.     t = this.clone();
  72.     ds = t.digits;
  73.     s = "";
  74.  
  75.     while (i && j) {
  76.       var k = i;
  77.       var num = 0;
  78.  
  79.       while (k--) {
  80.     num = (num<<16) + ds[k];
  81.     if(num < 0) num += 4294967296;
  82.     ds[k] = Math.floor(num / hbase);
  83.     num %= hbase;
  84.       }
  85.  
  86.       if (ds[i-1] == 0)
  87.         i--;
  88.       k = 4;
  89.       while (k--) {
  90.     c = (num % base);
  91.     s = "0123456789abcdef".charAt(c) + s;
  92.     --j;
  93.     num = Math.floor(num / base);
  94.     if (i == 0 && num == 0) {
  95.       break;
  96.     }
  97.       }
  98.     }
  99.  
  100.     i = 0;
  101.     while(i < s.length && s.charAt(i) == "0")
  102.       i++;
  103.     if(i)
  104.       s = s.substring(i, s.length);
  105.     if(!this.sign)
  106.       s = "-" + s;
  107.     return s;
  108. }
  109. function _BigInt_clone()
  110. {
  111.   var x, i;
  112.  
  113.   x = new BigInt(this.len, this.sign);
  114.   for(i = 0; i < this.len; i++)
  115.     x.digits[i] = this.digits[i];
  116.   return x;
  117. }
  118.  
  119. function BigInt(len, sign)
  120. {
  121.   var i, x, need_init;
  122.  
  123.   // Setup member functions.
  124.   // Note: There is G.C. bug of function() in Netscape!
  125.   //       Don't use anonymous function.
  126.   this.toString = _BigInt_toString;
  127.   this.toStringBase = _BigInt_toStringBase;
  128.   this.clone = _BigInt_clone;
  129.  
  130.   if(BigInt.arguments.length == 0) {
  131.     this.sign = true;
  132.     this.len = len = 1;
  133.     this.digits = new Array(1);
  134.     need_init = true;
  135.   } else if(BigInt.arguments.length == 1) {
  136.     x = bigint_from_any(BigInt.arguments[0]);
  137.     if(x == BigInt.arguments[0])
  138.       x = x.clone();
  139.     this.sign = x.sign;
  140.     this.len = x.len;
  141.     this.digits = x.digits;
  142.     need_init = false;
  143.   } else {
  144.     this.sign = (sign ? true : false);
  145.     this.len = len;
  146.     this.digits = new Array(len);
  147.     need_init = true;
  148.   }
  149.  
  150.   if(need_init) {
  151.     for(i = 0; i < len; i++)
  152.       this.digits[i] = 0;
  153.   }
  154. }
  155.  
  156. function bigint_norm(x)
  157. {
  158.   var len = x.len;
  159.   var ds = x.digits;
  160.  
  161.   while(len-- && !ds[len])
  162.     ;
  163.   x.len = ++len;
  164.   return x;
  165. }
  166.  
  167. function bigint_from_int(n)
  168. {
  169.   var sign, big, i;
  170.  
  171.   if(n < 0) {
  172.     n = -n;
  173.     sign = false;
  174.   } else
  175.     sign = true;
  176.   n &= 0x7fffffff;
  177.  
  178.   if(n <= 0xffff) {
  179.     big = new BigInt(1, 1);
  180.     big.digits[0] = n;
  181.   } else {
  182.     big = new BigInt(2, 1);
  183.     big.digits[0] = (n & 0xffff);
  184.     big.digits[1] = ((n>>16) & 0xffff);
  185.   }
  186.   return big;
  187. }
  188.  
  189. function bigint_from_string(str, base)
  190. {
  191.   var str_i;
  192.   var sign = true;
  193.   var c;
  194.   var len;
  195.   var z;
  196.   var zds;
  197.   var num;
  198.   var i;
  199.   var blen = 1;
  200.  
  201.   str += "@";   // Terminator;
  202.  
  203.   str_i = 0;
  204.   // TODO: skip white spaces
  205.  
  206.   if(str.charAt(str_i) == "+") {
  207.     str_i++;
  208.   }
  209.   else if (str.charAt(str_i) == "-") {
  210.     str_i++;
  211.     sign = false;
  212.   }
  213.  
  214.   if (str.charAt(str_i) == "@")
  215.     return null;
  216.  
  217.   if (!base) {
  218.     if (str.charAt(str_i) == "0") {
  219.       c = str.charAt(str_i + 1);
  220.       if (c == "x" || c == "X") {
  221.     base = 16;
  222.       }
  223.       else if (c == "b" || c == "B") {
  224.     base = 2;
  225.       }
  226.       else {
  227.     base = 8;
  228.       }
  229.     }
  230.     else {
  231.       base = 10;
  232.     }
  233.   }
  234.  
  235.   if (base == 8) {
  236.     while (str.charAt(str_i) == "0")
  237.       str_i++;
  238.     len = 3 * (str.length - str_i);
  239.   }
  240.   else {            // base == 10, 2 or 16
  241.     if (base == 16 && str.charAt(str_i) == '0' && (str.charAt(str_i+1) == "x" || str.charAt(str_i+1) == "X")) {
  242.       str_i += 2;
  243.     }
  244.     if (base == 2 && str.charAt(str_i) == '0' && (str.charAt(str_i+1) == "b"||str.charAt(str_i+1) == "B")) {
  245.       str_i += 2;
  246.     }
  247.     while (str.charAt(str_i) == "0")
  248.       str_i++;
  249.     if (str.charAt(str_i) == "@") str_i--;
  250.     len = 4 * (str.length - str_i);
  251.   }
  252.  
  253.   len = (len>>4)+1;
  254.   z = new BigInt(len, sign);
  255.   zds = z.digits;
  256.  
  257.   while(true) {
  258.     c = str.charAt(str_i++);
  259.     if(c == "@")
  260.       break;
  261.     switch (c) {
  262.     case '0': c = 0; break;
  263.     case '1': c = 1; break;
  264.     case '2': c = 2; break;
  265.     case '3': c = 3; break;
  266.     case '4': c = 4; break;
  267.     case '5': c = 5; break;
  268.     case '6': c = 6; break;
  269.     case '7': c = 7; break;
  270.     case '8': c = 8; break;
  271.     case '9': c = 9; break;
  272.     case 'a': case 'A': c = 10; break;
  273.     case 'b': case 'B': c = 11; break;
  274.     case 'c': case 'C': c = 12; break;
  275.     case 'd': case 'D': c = 13; break;
  276.     case 'e': case 'E': c = 14; break;
  277.     case 'f': case 'F': c = 15; break;
  278.     default:
  279.       c = base;
  280.       break;
  281.     }
  282.     if (c >= base)
  283.       break;
  284.  
  285.     i = 0;
  286.     num = c;
  287.     while(true) {
  288.       while (i<blen) {
  289.     num += zds[i]*base;
  290.     zds[i++] = (num & 0xffff);
  291.     num >>>= 16;
  292.       }
  293.       if (num) {
  294.     blen++;
  295.     continue;
  296.       }
  297.       break;
  298.     }
  299.   }
  300.   return bigint_norm(z);
  301. }
  302.  
  303. function bigint_from_any(x)
  304. {
  305.   if(typeof(x) == "object") {
  306.     if(x.constructor == BigInt)
  307.       return x;
  308.     return BigInt(1, 1);
  309.   }
  310.  
  311.   if(typeof(x) == "string") {
  312.     return bigint_from_string(x);
  313.   }
  314.  
  315.   if(typeof(x) == "number") {
  316.     var i, x1, x2, fpt, np;
  317.  
  318.     if(-2147483647 <= x && x <= 2147483647) {
  319.       return bigint_from_int(x);
  320.     }
  321.     x = x + "";
  322.     i = x.indexOf("e", 0);
  323.     if(i == -1)
  324.       return bigint_from_string(x);
  325.     x1 = x.substr(0, i);
  326.     x2 = x.substr(i+2, x.length - (i+2));
  327.  
  328.     fpt = x1.indexOf(".", 0);
  329.     if(fpt != -1) {
  330.       np = x1.length - (fpt+1);
  331.       x1 = x1.substr(0, fpt) + x1.substr(fpt+1, np);
  332.       x2 = parseInt(x2) - np;
  333.     } else {
  334.       x2 = parseInt(x2);
  335.     }
  336.     while(x2-- > 0) {
  337.       x1 += "0";
  338.     }
  339.     return bigint_from_string(x1);
  340.   }
  341.   return BigInt(1, 1);
  342. }
  343.  
  344. function bigint_uminus(x)
  345. {
  346.   var z = x.clone();
  347.   z.sign = !z.sign;
  348.   return bigint_norm(z);
  349. }
  350.  
  351. function bigint_add_internal(x, y, sign)
  352. {
  353.   var z;
  354.   var num;
  355.   var i, len;
  356.  
  357.   sign = (sign == y.sign);
  358.   if (x.sign != sign) {
  359.     if (sign)
  360.       return bigint_sub_internal(y, x);
  361.     return bigint_sub_internal(x, y);
  362.   }
  363.  
  364.   if (x.len > y.len) {
  365.     len = x.len + 1;
  366.     z = x; x = y; y = z;
  367.   } else {
  368.     len = y.len + 1;
  369.   }
  370.   z = new BigInt(len, sign);
  371.  
  372.   len = x.len;
  373.   for (i = 0, num = 0; i < len; i++) {
  374.     num += x.digits[i] + y.digits[i];
  375.     z.digits[i] = (num & 0xffff);
  376.     num >>>= 16;
  377.   }
  378.   len = y.len;
  379.   while (num && i < len) {
  380.     num += y.digits[i];
  381.     z.digits[i++] = (num & 0xffff);
  382.     num >>>= 16;
  383.   }
  384.   while (i < len) {
  385.     z.digits[i] = y.digits[i];
  386.     i++;
  387.   }
  388.   z.digits[i] = (num & 0xffff);
  389.   return bigint_norm(z);
  390.   //  return z;
  391. }
  392.  
  393. function bigint_sub_internal(x, y)
  394. {
  395.   var z = 0;
  396.   var zds;
  397.   var num;
  398.   var i;
  399.  
  400.   i = x.len;
  401.   // if x is larger than y, swap
  402.   if (x.len < y.len) {
  403.     z = x; x = y; y = z;    // swap x y
  404.   }
  405.   else if (x.len == y.len) {
  406.     while (i > 0) {
  407.       i--;
  408.       if (x.digits[i] > y.digits[i]) {
  409.     break;
  410.       }
  411.       if (x.digits[i] < y.digits[i]) {
  412.     z = x; x = y; y = z;    // swap x y
  413.     break;
  414.       }
  415.     }
  416.   }
  417.  
  418.   z = new BigInt(x.len, (z == 0) ? 1 : 0);
  419.   zds = z.digits;
  420.  
  421.   for (i = 0, num = 0; i < y.len; i++) {
  422.     num += x.digits[i] - y.digits[i];
  423.     zds[i] = (num & 0xffff);
  424.     num >>>= 16;
  425.   }
  426.   while (num && i < x.len) {
  427.     num += x.digits[i];
  428.     zds[i++] = (num & 0xffff);
  429.     num >>>= 16;
  430.   }
  431.   while (i < x.len) {
  432.     zds[i] = x.digits[i];
  433.     i++;
  434.   }
  435.    
  436.   return bigint_norm(z);
  437. }
  438.  
  439. function bigint_plus(x, y)
  440. {
  441.   x = bigint_from_any(x);
  442.   y = bigint_from_any(y);
  443.   return bigint_add_internal(x, y, 1);
  444. }
  445.  
  446. function bigint_minus(x, y)
  447. {
  448.   x = bigint_from_any(x);
  449.   y = bigint_from_any(y);
  450.   return bigint_add_internal(x, y, 0);
  451. }
  452.  
  453. function bigint_mul(x, y)
  454. {
  455.   var i, j;
  456.   var n = 0;
  457.   var z;
  458.   var zds, xds, yds;
  459.   var dd, ee;
  460.   var ylen;
  461.  
  462.   x = bigint_from_any(x);
  463.   y = bigint_from_any(y);
  464.  
  465.   j = x.len + y.len + 1;
  466.   z = new BigInt(j, x.sign == y.sign);
  467.  
  468.   xds = x.digits;
  469.   yds = y.digits;
  470.   zds = z.digits;
  471.   ylen = y.len;
  472.   while (j--)
  473.     zds[j] = 0;
  474.   for (i = 0; i < x.len; i++) {
  475.     dd = xds[i];
  476.     if (dd == 0)
  477.       continue;
  478.     n = 0;
  479.     for (j = 0; j < ylen; j++) {
  480.       ee = n + dd * yds[j];
  481.       n = zds[i + j] + ee;
  482.       if (ee)
  483.     zds[i + j] = (n & 0xffff);
  484.       n >>>= 16;
  485.     }
  486.     if (n) {
  487.       zds[i + j] = n;
  488.     }
  489.   }
  490.  
  491.   return bigint_norm(z);
  492. }
  493.  
  494. function bigint_divmod(x, y, modulo)
  495. {
  496.   var nx = x.len;
  497.   var ny = y.len;
  498.   var i, j;
  499.   var yy, z;
  500.   var xds, yds, zds, tds;
  501.   var t2;
  502.   var num;
  503.   var dd, q;
  504.   var ee;
  505.   var mod, div;
  506.  
  507.   yds = y.digits;
  508.   if (ny == 0 && yds[0] == 0)
  509.     return null;    // Division by zero
  510.  
  511.   if (nx < ny || nx == ny && x.digits[nx - 1] < y.digits[ny - 1]) {
  512.     if (modulo)
  513.       return bigint_norm(x);
  514.     return BigInt(1, 1);
  515.   }
  516.  
  517.   xds = x.digits;
  518.   if (ny == 1) {
  519.     dd = yds[0];
  520.     z = x.clone();
  521.     zds = z.digits;
  522.     t2 = 0;
  523.     i = nx;
  524.     while (i--) {
  525.       t2 = t2 * 65536 + zds[i];
  526.       zds[i] = (t2 / dd) & 0xffff;
  527.       t2 %= dd;
  528.     }
  529.     z.sign = (x.sign == y.sign);
  530.     if (modulo) {
  531.       if (!x.sign)
  532.     t2 = -t2;
  533.       if (x.sign != y.sign) {
  534.     t2 = t2 + yds[0] * (y.sign ? 1 : -1);
  535.       }
  536.       return bigint_from_int(t2);
  537.     }
  538.     return bigint_norm(z);
  539.   }
  540.  
  541.   z = new BigInt(nx == ny ? nx + 2 : nx + 1,
  542.          x.sign == y.sign);
  543.   zds = z.digits;
  544.   if (nx == ny)
  545.     zds[nx + 1] = 0;
  546.   while (!yds[ny - 1])
  547.     ny--;
  548.   if ((dd = ((65536/(yds[ny-1]+1)) & 0xffff)) != 1) {
  549.     yy = y.clone();
  550.     tds = yy.digits;
  551.     j = 0;
  552.     num = 0;
  553.     while (j<ny) {
  554.       num += yds[j]*dd;
  555.       tds[j++] = num & 0xffff;
  556.       num >>= 16;
  557.     }
  558.     yds = tds;
  559.     j = 0;
  560.     num = 0;
  561.     while (j<nx) {
  562.       num += xds[j] * dd;
  563.       zds[j++] = num & 0xffff;
  564.       num >>= 16;
  565.     }
  566.     zds[j] = num & 0xffff;
  567.   }
  568.   else {
  569.     zds[nx] = 0;
  570.     j = nx;
  571.     while (j--) zds[j] = xds[j];
  572.   }
  573.   j = nx==ny?nx+1:nx;
  574.   do {
  575.     if (zds[j] ==  yds[ny-1]) q = 65535;
  576.     else q = ((zds[j]*65536 + zds[j-1])/yds[ny-1]) & 0xffff;
  577.     if (q) {
  578.       i = 0; num = 0; t2 = 0;
  579.       do {          // multiply and subtract
  580.     t2 += yds[i] * q;
  581.     ee = num - (t2 & 0xffff);
  582.     num = zds[j - ny + i] + ee;
  583.     if (ee) zds[j - ny + i] = num & 0xffff;
  584.     num >>= 16;
  585.     t2 >>>= 16;
  586.       } while (++i < ny);
  587.       num += zds[j - ny + i] - t2; // borrow from high digit; don't update
  588.       while (num) {     // "add back" required
  589.     i = 0; num = 0; q--;
  590.     do {
  591.       ee = num + yds[i];
  592.       num = zds[j - ny + i] + ee;
  593.       if (ee) zds[j - ny + i] = num & 0xffff;
  594.       num >>= 16;
  595.     } while (++i < ny);
  596.     num--;
  597.       }
  598.     }
  599.     zds[j] = q;
  600.   } while (--j >= ny);
  601.  
  602.   if (modulo) {         // just normalize remainder
  603.     mod = z.clone();
  604.     if (dd) {
  605.       zds = mod.digits;
  606.       t2 = 0; i = ny;
  607.       while (i--) {
  608.     t2 = (t2*65536) + zds[i];
  609.     zds[i] = (t2 / dd) & 0xffff;
  610.     t2 %= dd;
  611.       }
  612.     }
  613.     mod.len = ny;
  614.     mod.sign = x.sign;
  615.     if (x.sign != y.sign) {
  616.       return bigint_add_internal(mod, y, 1);
  617.     }
  618.     return bigint_norm(mod);
  619.   }
  620.  
  621.   div = z.clone();
  622.   zds = div.digits;
  623.   j = (nx==ny ? nx+2 : nx+1) - ny;
  624.   for (i = 0;i < j;i++) zds[i] = zds[i+ny];
  625.   div.len = i;
  626.   return bigint_norm(div);
  627. }
  628.  
  629. function bigint_div(x, y)
  630. {
  631.   x = bigint_from_any(x);
  632.   y = bigint_from_any(y);
  633.   return bigint_divmod(x, y, 0);
  634. }
  635.  
  636. function bigint_mod(x, y)
  637. {
  638.   x = bigint_from_any(x);
  639.   y = bigint_from_any(y);
  640.   return bigint_divmod(x, y, 1);
  641. }
  642.  
  643. function bigint_cmp(x, y)
  644. {
  645.   var xlen;
  646.  
  647.   if(x == y)
  648.     return 0;   // Same object
  649.  
  650.   x = bigint_from_any(x);
  651.   y = bigint_from_any(y);
  652.   xlen = x.len;
  653.  
  654.   if(x.sign != y.sign) {
  655.     if(x.sign)
  656.       return 1;
  657.     return -1;
  658.   }
  659.  
  660.   if (xlen < y.len)
  661.     return (x.sign) ? -1 : 1;
  662.   if (xlen > y.len)
  663.     return (x.sign) ? 1 : -1;
  664.  
  665.   while(xlen-- && (x.digits[xlen] == y.digits[xlen]))
  666.     ;
  667.   if (-1 == xlen)
  668.     return 0;
  669.   return (x.digits[xlen] > y.digits[xlen]) ?
  670.     (x.sign ? 1 : -1) :
  671.     (x.sign ? -1 : 1);
  672. }
  673.  
  674. function bigint_number(x)
  675. {
  676.   var d = 0.0;
  677.   var i = x.len;
  678.   var ds = x.digits;
  679.  
  680.   while (i--) {
  681.     d = ds[i] + 65536.0 * d;
  682.   }
  683.   if (!x.sign) d = -d;
  684.   return d;
  685. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement