UNPKG

eligendiexercitationem

Version:

Yet another class for arbitrary-precision integers in pure JavaScript. Small. Well tested.

991 lines (969 loc) 47.5 kB
var wrapper = function () { "use strict"; var supportsBase = function (I, base) { var result = false; try { var x = I.parseInt("10", base); result = I.toString(x, 10) === base.toString(10); } catch (e) { console.log(e); } return result; }; var supportsBaseToString = function (I, base) { var result = false; try { var s = base.toString(10); var x = I.parseInt(s, 10); result = I.toString(x, base) === "10"; } catch (e) { console.log(e); } return result; }; (function () { var input10 = undefined; var input16 = undefined; var a = undefined; var b = undefined; var as = undefined; var supportsHex = undefined; var ok = undefined; var create10IsOk = undefined; var create16IsOk = undefined; var addIsOk = undefined; var multiplyIsOk = undefined; var divideIsOk = undefined; var remainderIsOk = undefined; var initialize = function () { var input10 = "012345678901234567890123456789012345678901234567890"; var input16 = "01234567890abcdef01234567890abcdef01234567890abcdef"; var a = I.parseInt(input10, 10); var b = I.parseInt("213509123601923760129376102397651203958123402314875", 10); var aa = I.multiply(a, a); var t = I.parseInt("3735928559", 10); var as = I.add(aa, t); var supportsHex = false; try { var x = I.parseInt("10", 16); supportsHex = I.toString(x, 10) === (16).toString(10); } catch (e) { console.log(e); } var x0 = I.parseInt(input10, 10); var ok = "0" + I.toString(x0, 10) === input10; var create10IsOk = ok; var tmp0 = I.parseInt(input16, 16); var create16IsOk = supportsHex && "0" + I.toString(tmp0, 16).toLowerCase() === input16; var tmp1 = I.add(a, b); var addIsOk = ok && I.toString(tmp1, 10) === "225854802503158328019499559186663549637024636882765"; var tmp2 = I.multiply(a, b); var multiplyIsOk = ok && I.toString(tmp2, 10) === "2635915082473353673085235184843445396749745111229911595609669061939318527195756503500792996344363750"; var tmp3 = I.divide(as, b); var divideIsOk = ok && I.toString(tmp3, 10) === "713860770730150993024342853794918979066195767402"; var tmp4 = I.remainder(as, b); var remainderIsOk = ok && I.toString(tmp4, 10) === "149922972578668446272207027928631904526544890275909"; }; benchmarkSuite.add("create-10", function () { if (!create10IsOk) { throw new Error(); } return I.parseInt(input10, 10); }, { setup: initialize }); benchmarkSuite.add("create-hex", function () { if (!create16IsOk) { throw new Error(); } return I.parseInt(input16, 16); }, { setup: initialize }); benchmarkSuite.add("toString-10", function () { if (!create10IsOk) { throw new Error(); } return I.toString(a, 10); }, { setup: initialize }); benchmarkSuite.add("toString-hex", function () { if (!create16IsOk) { throw new Error(); } return I.toString(a, 16); }, { setup: initialize }); benchmarkSuite.add("add", function () { if (!addIsOk) { throw new Error(); } return I.add(a, b); }, { setup: initialize }); benchmarkSuite.add("mul", function () { if (!multiplyIsOk) { throw new Error(); } return I.multiply(a, b); }, { setup: initialize }); benchmarkSuite.add("div", function () { if (!divideIsOk) { throw new Error(); } return I.divide(as, b); }, { setup: initialize }); benchmarkSuite.add("mod", function () { if (!remainderIsOk) { throw new Error(); } return I.remainder(as, b); }, { setup: initialize }); benchmarkSuite.add("bitwise-shift-operators", function () { var x = I.shiftLeft(a, 1); var y = I.shiftRight(b, 1); return I.compareTo(x, y) < 0; }, { setup: initialize }); benchmarkSuite.add("bitwise-logical-operators", function () { var x = I.and(a, b); var y = I.or(a, b); var z = I.xor(a, b); return I.compareTo(x, y) < 0 && I.compareTo(x, z) < 0; }, { setup: initialize }); }()); (function () { var a = undefined; var b = undefined; var initialize = function () { var a = I.parseInt("134217727", 10); var b = I.parseInt("134217729", 10); var c = I.multiply(a, b); if (I.toString(c, 10) !== "18014398509481983") { a = undefined; b = undefined; } }; benchmarkSuite.add("27*27==54", function () { return I.multiply(a, b); }, { setup: initialize }); }()); (function () { var a = undefined; var b = undefined; var initialize = function () { var a = I.parseInt("1023", 10); var b = I.parseInt("1025", 10); var c = I.multiply(a, b); if (I.toString(c, 10) !== "1048575") { a = undefined; b = undefined; } }; benchmarkSuite.add("10*10==20", function () { return I.multiply(a, b); }, { setup: initialize }); }()); benchmarkSuite.add("joseprio", function () { //var params = ["1", "100000000", "7070"]; var params = [ "1", "100000000000000", "7071067" ]; var start = Date.now(); var iterations = 0; var ZERO = I.parseInt("0", 10); var ONE = I.parseInt("1", 10); var TWO = I.parseInt("2", 10); var currentPaint = I.parseInt(params[1], 10); var currentRadius = I.parseInt(params[0], 10); currentRadius = I.add(currentRadius, ONE); var numberCircles = 0; while (I.compareTo(currentPaint, ZERO) >= 0) { numberCircles += 1; var t = I.multiply(currentRadius, TWO); currentPaint = I.subtract(currentPaint, t); currentPaint = I.add(currentPaint, ONE); currentRadius = I.add(currentRadius, TWO); iterations += 1; if (iterations === 1000) { if (Date.now() - start > 4000) { throw new Error("timeout"); } iterations = 0; } } numberCircles -= 1; if (numberCircles !== Number.parseInt(params[2])) { throw new Error(numberCircles); } }, { minSamples: 1 }); function assertEquals(x, y, t) { if (x !== y) { throw new RangeError(t + " : " + x + " !== " + y); } } testSuite.add("parseInt", function (I) { var s = ""; var a = undefined; var b = undefined; for (var i = 2; i < 37 + 1; i += 1) { var z = i === 37 ? false : supportsBase(I, i); if (!z) { if (b != undefined) { s += (s === "" ? "" : ",") + (a === b ? a.toString() : a.toString() + "-" + b.toString()); a = undefined; b = undefined; } } else { if (a == undefined) { a = i; } b = i; } } throw new RangeError(s); }); testSuite.add("toString", function (I) { var s = ""; var a = undefined; var b = undefined; for (var i = 2; i < 37 + 1; i += 1) { var z = i === 37 ? false : supportsBaseToString(I, i); if (!z) { if (b != undefined) { s += (s === "" ? "" : ",") + (a === b ? a.toString() : a.toString() + "-" + b.toString()); a = undefined; b = undefined; } } else { if (a == undefined) { a = i; } b = i; } } throw new RangeError(s); }); var testDivide = function () { var THREE = I.parseInt("3", 10); var MINUS_THREE = I.parseInt("-3", 10); var FOUR = I.parseInt("4", 10); var MINUS_FOUR = I.parseInt("-4", 10); var a = I.divide(FOUR, THREE); var b = I.divide(FOUR, MINUS_THREE); var c = I.divide(MINUS_FOUR, THREE); var d = I.divide(MINUS_FOUR, MINUS_THREE); var s = a + ", " + b + ", " + c + ", " + d; if (s === "1, -1, -1, 1") { return "truncated division"; } if (s === "1, -2, -2, 1") { return "floored division"; } if (s === "1, -1, -2, 2") { return "Euclidean division"; } return "?"; }; var testRemainder = function () { var THREE = I.parseInt("3", 10); var MINUS_THREE = I.parseInt("-3", 10); var FOUR = I.parseInt("4", 10); var MINUS_FOUR = I.parseInt("-4", 10); var a = I.remainder(FOUR, THREE); var b = I.remainder(FOUR, MINUS_THREE); var c = I.remainder(MINUS_FOUR, THREE); var d = I.remainder(MINUS_FOUR, MINUS_THREE); var s = a + ", " + b + ", " + c + ", " + d; if (s === "1, 1, -1, -1") { return "truncated division"; } if (s === "1, -2, 2, -1") { return "floored division"; } if (s === "1, 1, 2, 2") { return "Euclidean division"; } return "?"; }; var test0 = function (operator) { var property = ""; var f = function (x, y) { return 0; }; var f0 = function (x, y) { return undefined; }; if (operator === "%") { f = function (x, y) { return 0 + x % y; }; f0 = function (x, y) { return I.remainder(x, y); }; } if (operator === "/") { f = function (x, y) { return 0 + Math.sign(x) * Math.sign(y) * Math.floor(Math.abs(x) / Math.abs(y)); }; f0 = function (x, y) { return I.divide(x, y); }; } if (operator === "&") { f = function (x, y) { return x & y; }; f0 = function (x, y) { return I.and(x, y); }; } if (operator === "|") { f = function (x, y) { return x | y; }; f0 = function (x, y) { return I.or(x, y); }; } if (operator === "^") { f = function (x, y) { return x ^ y; }; f0 = function (x, y) { return I.xor(x, y); }; } var THREE = I.parseInt("3", 10); var MINUS_THREE = I.parseInt("-3", 10); var FOUR = I.parseInt("4", 10); var MINUS_FOUR = I.parseInt("-4", 10); var f1 = function (a, b) { var c = f0(a, b); return I.toString(c, 10); }; var a = f1(FOUR, THREE); var b = f1(FOUR, MINUS_THREE); var c = f1(MINUS_FOUR, THREE); var d = f1(MINUS_FOUR, MINUS_THREE); var s = a + ", " + b + ", " + c + ", " + d; if (operator === "/") { if (s === "1, -1, -1, 1") { throw new RangeError("truncated division"); } if (s === "1, -2, -2, 1") { throw new RangeError("floored division"); } if (s === "1, -1, -2, 2") { throw new RangeError("Euclidean division"); } } if (operator === "%") { if (s === "1, 1, -1, -1") { throw new RangeError("truncated division"); } if (s === "1, -2, 2, -1") { throw new RangeError("floored division"); } if (s === "1, 1, 2, 2") { throw new RangeError("Euclidean division"); } } assertEquals(a, f(4, 3).toString(), "4 " + operator + " 3"); assertEquals(b, f(4, -3).toString(), "4 " + operator + " -3"); assertEquals(c, f(-4, 3).toString(), "-4 " + operator + " 3"); assertEquals(d, f(-4, -3).toString(), "-4 " + operator + " -3"); if (operator === "&" || operator === "|" || operator === "^") { var fx = function (s1, s2) { var a = I.parseInt(s1, 10); var b = I.parseInt(s2, 10); return f1(a, b); }; var ff = function (a, b) { var s1 = a.toString(); var s2 = b.toString(); assertEquals(fx(s1, s2).toString(), f(a, b).toString(), "-3 " + operator + " -2"); }; ff(4, 1); ff(4, -1); ff(-4, 1); ff(-4, -1); ff(3, 1); ff(3, -1); ff(-3, 1); ff(-3, -1); ff(4, 2); ff(4, -2); ff(-4, 2); ff(-4, -2); ff(3, 2); ff(3, -2); ff(-3, 2); ff(-3, -2); } }; testSuite.add("%", function (I) { test0("%"); }); testSuite.add("/", function (I) { test0("/"); }); testSuite.add("&", function (I) { test0("&"); }); testSuite.add("|", function (I) { test0("|"); }); testSuite.add("^", function (I) { test0("^"); }); testSuite.add("~", function (I) { var x = I.parseInt("3", 10); var tmp1 = I.not(x); var s = I.toString(tmp1, 10); assertEquals(s, (~3).toString(), "~3"); var x = I.parseInt("-3", 10); var tmp1 = I.not(x); var s = I.toString(tmp1, 10); assertEquals(s, (~-3).toString(), "~-3"); }); testSuite.add("<<", function (I) { var a = I.parseInt("3", 10); var b = I.shiftLeft(a, 8); var s = I.toString(b, 10); assertEquals(s, (3 << 8).toString(), "3 << 8"); var a = I.parseInt("-3", 10); var b = I.shiftLeft(a, 8); var s = I.toString(b, 10); assertEquals(s, (-3 << 8).toString(), "-3 << 8"); }); testSuite.add(">>", function (I) { var a = I.parseInt("3", 10); var b = I.shiftRight(a, 8); var s = I.toString(b, 10); assertEquals(s, (3 >> 8).toString(), "-3 >> 8"); var a = I.parseInt("-3", 10); var b = I.shiftRight(a, 8); var s = I.toString(b, 10); assertEquals(s, (-3 >> 8).toString(), "-3 >> 8"); }); testSuite.add("<< -n", function (I) { var a = I.parseInt("3", 10); var b = I.shiftLeft(a, -1); var s = I.toString(b, 10); assertEquals(s, "1", "3 << -1"); // OR Throw an error (?) }); testSuite.add(">> -n", function (I) { var a = I.parseInt("3", 10); var b = I.shiftRight(a, -1); var s = I.toString(b, 10); assertEquals(s, "6", "3 >> -1"); // OR Throw an error (?) }); testSuite.add("<< 32", function (I) { var a = I.parseInt("3", 10); var b = I.shiftLeft(a, 32); var s = I.toString(b, 10); assertEquals(s, "12884901888", "3 << 32"); // OR Throw an error (?) }); testSuite.add(">> 32", function (I) { var a = I.parseInt("12884901888", 10); var b = I.shiftRight(a, 32); var s = I.toString(b, 10); assertEquals(s, "3", "12884901888 >> 32"); // OR Throw an error (?) }); testSuite.add("-1024 >> 9007199254740991", function (I) { var a = I.parseInt("-1024", 10); var b = I.shiftRight(a, 9007199254740991); var s = I.toString(b, 10); assertEquals(s, "-1"); }); //testSuite.add("1024 >> 9007199254740991", function (I) { // var a = I.parseInt("1024", 10); // var b = I.shiftRight(a, 9007199254740991); // var s = I.toString(b, 10); // assertEquals(s, "0"); //}); //testSuite.add("0 << 9007199254740991", function (I) { // var a = I.parseInt("0", 10); // var b = I.shiftLeft(a, 9007199254740991); // var s = I.toString(b, 10); // assertEquals(s, "0"); //}); testSuite.add("bitLength", function (I) { // ceil(log2(this < 0 ? 0 - this : this + 1)) var a = I.parseInt("4294967295", 10); var b = I.bitLength(a); console.log(b, typeof b); var s = typeof b === "number" ? b.toString(10) : "-"; // I.toString(b, 10); assertEquals(s, "32", "bitLength(4294967295)"); for (var i = 0; i < 4; i += 1) { var tmp0 = i.toString(); var tmp1 = I.parseInt(tmp0, 10); var tmp2 = I.bitLength(tmp1); var s = typeof tmp2 === "number" ? tmp2.toString(10) : "-";//I.toString(tmp2, 10); assertEquals(s, (i === 0 ? 0 : 1 + Math.floor(Math.log(i + 0.5) * Math.LOG2E)).toString(), "bitLength(" + i.toString() + ")"); } }); var testPow = function (sa, sb) { var ssa = sa.toString(); var a = I.parseInt(ssa, 10); var b = null; try { b = I.pow(a, sb); } catch (error) { if (sb < 0) { console.log(error); } else { throw error; } } var c = b == null ? null : I.toString(b, 10); assertEquals(c, sb < 0 ? null : Math.pow(sa, sb).toString(), sa + " ** " + sb); }; testSuite.add("x ** y", function (I) { for (var a = +2; a >= -2; a -= 1) { for (var b = +2; b >= -2; b -= 1) { testPow(a, b); } } }); // jsbn's bug testSuite.add("0 ** (0xffffffff + 1)", function (I) { testPow(0, 0xffffffff + 1); }); testSuite.add("fromNumber", function (I) { var i = I.fromNumber(42); var s = I.toString(i, 10); assertEquals(s, "42"); var i = I.fromNumber(9007199254740991); var s = I.toString(i, 10); assertEquals(s, "9007199254740991"); }); testSuite.add("fromNumber-big", function (I) { var i = I.fromNumber(Number.MAX_VALUE); var s = I.toString(i, 10); assertEquals(s, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368"); }); testSuite.add("toNumber", function (I) { var i = I.parseInt("42", 10); var s = I.toNumber(i); assertEquals(s, 42); var i = I.parseInt("9007199254740991", 10); var s = I.toNumber(i); assertEquals(s, 9007199254740991); }); testSuite.add("toNumber-big", function (I) { var i = I.parseInt("100000000000000008192", 10); var s = I.toNumber(i); assertEquals(s, 100000000000000000000); var i = I.parseInt("100000000000000008193", 10); var s = I.toNumber(i); assertEquals(s, 100000000000000016384); // 2**106+(2**53+4) var i = I.parseInt("81129638414606690702988259885060", 10); var s = I.toNumber(i); assertEquals(s, 9007199254740994 * 9007199254740992); }); testSuite.add("mod", function (I) { var testMod = function (I) { var THREE = I.parseInt("3", 10); var MINUS_THREE = I.parseInt("-3", 10); var FOUR = I.parseInt("4", 10); var MINUS_FOUR = I.parseInt("-4", 10); var a = I.mod(FOUR, THREE); var c = I.mod(MINUS_FOUR, THREE); var as = I.toString(a, 10) var cs = I.toString(c, 10); assertEquals(as, "1"); assertEquals(cs, "2"); //try { // var t = I.mod(FOUR, MINUS_THREE); // assertEquals(false, true); //} catch (error) { //} //try { // var t = I.mod(MINUS_FOUR, MINUS_THREE); // assertEquals(false, true); //} catch (error) { //} }; testMod(I); }); testSuite.add("modInverse", function (I) { var a = I.parseInt("7", 10); var b = I.parseInt("20", 10); var x = I.modInverse(a, b); var s = I.toString(x, 10); assertEquals(s, "3"); }); testSuite.add("modPow", function (I) { var a = I.parseInt("10", 10); var b = I.parseInt("3", 10); var c = I.parseInt("30", 10); var x = I.modPow(a, b, c); var s = I.toString(x, 10); assertEquals(s, "10"); }); /* testSuite.add("modPow", function (I) { var t = Date.now(); var a = "-29694681763448712115267303514023904033265211886910761264672576231554464098637402550663040547342726600568933793424522580102024307390684120501123145913181335140054630257537266316462992944143291789428368597319366497044735307450905133722212599357295495795914532499656994934020209866067682479620381834108247731805362251476372300643310863145482504070318221407436590709353870667746678473405580031604287313646969125892734476605404502107124001169091069970155161376239893444309019800637825991490992886756114995636568690097893351815480034167383046629554600914654853770556603406920385489591581795592966209762321826324786588707444458373503608685515834491712886834370824573830770838543360344886700981870"; // var b = "119334647663227291363113405741243413916434827363146166012200067038894142816254113710841716638008805209543910927476491099816542561560345503311330152550056221240122563520612198703057065667637570340647063422988042473190059156975005813463818646696643573820202000369152615667401021816298491297653620614440782978764393137821956464627163145421579373439868081673415678986432326806001408975760610901250649711198896213496068605039486228645916762983047459546900860937537474723612261449751343757826252579432285178556676653805951590208797794400875516522254480074885052650095801006651270614765243081674516367874973021395155320563"; var b = "11933464766322729136311340574124341391643482736314616601220006703889414281625411371084171663"; var c = "21766174458617435773191008891802753781907668374255538511144643224689886235383840957210909013086056401571399717235807266581649606472148410291413364152197364477180887395655483738115072677402235101762521901569820740293149529620419333266262073471054548368736039519702486226506248861060256971802984953561121442680157668000761429988222457090413873973970171927093992114751765168063614761119615476233422096442783117971236371647333871414335895773474667308967050807005509320424799678417036867928316761272274230314067548291133582479583061439577559347101961771406173684378522703483495337037655006751328447510550299250924469288819"; //var e = "72324557783415787424155521118202596834933898242395886137674358852236580794269836377307287786755289962440782013831739423702014967616850758313183751932896777891669089456853771795527757996329325050996269324970201536028633484579111946278204478269805106124073503820660024439715627250378312057531479971103107712537148991421528677788413535635435770715226291273808528964474082509191820953587881465428407150420995055514194080761192776104785866884604229750694117199160680355057545631740521663782384430018469927006099212868328005800482010975321397684122860835203872900466151550540270815104453823592754896203799696226528729895"; var e = "13540802089857741167023542037988805222546440577229559332533075840910935632532209556364267054685794323888640528195606483456493117658256579047999363349321383330093264011066537310121911518868496867167891598543722545495853065340968093012365382813267366017727691685093503665250431900627681102142398694435798038224365707752325308958087778218641883318154142118828465677276422817258682513984877559101140482783383241463776862894614490093886509444848747212475405025421083989216107083936711753381670137437841278736875577642823331640840588001717269730039276342775573437428364758255438364398063059345080931231137408921321659897500"; var tmp0 = I.parseInt(a, 10); var tmp1 = I.parseInt(b, 10); var tmp2 = I.parseInt(c, 10); var x = I.modPow(tmp0, tmp1, tmp2); var s = I.toString(x, 10); t = Date.now() - t; console.log(t, url); assertEquals(s, e, "modPow"); }); */ //!!! (function () { var basicTests = [ "-1000000000000000000000000000000000001+1000000000000000000000000000000000000=-1", "100000000000000000002222222222222222222-100000000000000000001111111111111111111=1111111111111111111", "16**13==4503599627370496", "123456789123456789**10==822526267372365207989468699031914332476569003445489153619518989325083908083922133639704420166045905346960117046949453426283086050487204639652635846010822673782217799736601", "2**63=9223372036854775808", "306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000=306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000", "306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000=0x9822997e35bb99bcf103a64299aa92b8446ab93879fba53349f1626f3c8f78a4ee1d8d9e7562538f8e374fdf64c8eff7481c63cde5ca9821abfb3df6fb3e2489d2f85d34cf347f3e89191a19cc6b6b8072a976a8f1bcf68d20f18a1c0efb023252ba2d0961428a5c282d2645f3f7fa160f7f84aca88e40a74066c4a787bed7d0082f7e45b1ffee532715f56bd5f8168eaf7eaae112ed1316371f047692631e70e6b85b290ef063845b364dad7e10b9deb9fcfb708f83b7c3c6b82ce16eb0034c030b332a58d637a7b547fd0527051d7de9e5004db2ea2bd75f5c5a280a1a9b93c3c83373b6dcf1b65c01197096e97d13076b6613bc2ebf47c91fbe1aefeea966134bfbbf5f850320f0f0c2d88888bd82d118a6aaf8df2b092cf5456eff7e209feb476bf3c01d6d2e7ca0b9f40d83b107b4def92f2927cf0a1bb6190c67a4da91478709262ed1f1ecb77fbaf1197ac238c246a63a697f51e8d539f850e790137e7fce5f764896fdfb4fc3787520608f0400e72aeea5737c36304c6887ec1a174564ecec63a57b1e0946dc311dd3aea7bfae197ff9c7fcbf17c97d9db303d231702ef502dde1b53896196dc2e5d30b2b6ec58fc3744f4de08109eb99aa9f22ffe2f12f3953f516f91d35a8852aff4a19e250410fbd8dbcdae99f92f88e2f94341fc1ecdff32733d194c0541f708a72c5b4c03e5515e1086d0903addca0e172968ff1dee87bbd4fee679e2ee5a52975807ae7212cc2a33e0821e2d9b44eaa7dc29536a94c6597eda41bdd1e5e618e7b388b53d38ef9542523bce888738db46c6706c3ee82cbc3655408071e9e422a44d309e3cfd31ec2135ee0cba32b0c6721c8bee4d076543b71c35a06087a007c14e51d1f0c4d0aa9aa0751dfd3776d2357a010e6b147aca40c7b669291e6defbf5ca77505c960f14b330e6c90dc2539431329ef78a1e9f26b2ead7d28a622e6b586bcee22bd0a495442c6a1235588988252cbd4d36975560fb8e7e5c8cf06f29aeb68659c5cb4cf8d011375b00000000000000000000000000000000000000000000000000000000000000000000000000", "9223372036854775808=0b1000000000000000000000000000000000000000000000000000000000000000", "-1=-1", "-10000000000000000=-10000000000000000", "0x324AFCCC342342333CCD239998881232324AFCCC342342333CCD239998881232=22748133857356174891035811692236022265357659892433333914058690475216129757746", "234345345345=234345345345", "234345345345=0x3690123141", "1230000000=1230000000", "-0x10=-16", "-0=0", "-0000000000000000000000123=-123", "1+0=1", "10+10000000000000000=10000000000000010", "10000000000000000+10=10000000000000010", "10000000000000000+10000000000000000=20000000000000000", "0b1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111+0b1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111=0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110", "10+10=20", "-10000000000000000+0=-10000000000000000", "0+10000000000000000=10000000000000000", "1+0b11111111111111111111111111=67108864", "10-10000000000000000=-9999999999999990", "10000000000000000-10=9999999999999990", "10000000000000000-10000000000000000=0", "10-10=0", "-10000000000000000-0=-10000000000000000", "0-10000000000000000=-10000000000000000", "-1-0b11111111111111111111111111=-67108864", "10*10000000000000000=100000000000000000", "10000000000000000*10=100000000000000000", "10000000000000000*10000000000000000=100000000000000000000000000000000", "10*10=100", "100000000000000000*-1=-100000000000000000", "-1*100000000000000000=-100000000000000000", "0*-100000000000000000=0", "-100000000000000000*0=0", "0*-1=0", "10/10000000000000000=0", "10000000000000000/10=1000000000000000", "10000000000000000/10000000000000000=1", "10/10=1", "-10/10=-1", "10/-10=-1", "-10/-10=1", "-3221225473/3=-1073741824", "-3221225472/2=-1610612736", "00000000000000000000000000000000000000/2=0", "0/-10000000000000000=0", "10000000000000000/-1000000000000000000000000000000000000000000000000=0", "727587048255308587128283949527991017146474/3262705074329558374374751=223001169790014763", "194994622673976706651658530346880329671441/985341126327582219965=197895548520066180152", "10/10=1", "6582018229284824168619876730229320890292528855852623664389292032/730750818665451459101842416358132502628711530497=9007199254740991", "10%10000000000000000=10", "10000000000000000%10=0", "10000000000000000%10000000000000000=0", "10%10=0", "0%-10000000000000000=0", "-3%3=0", "10<=>10000000000000000=-1", "10000000000000000<=>10=1", "10000000000000000<=>10000000000000000=0", "10<=>10=0", "1<=>2=-1", "2<=>1=1", "0<=>10000000000000000=-1", "10000000000000000<=>0=1", "9007199254740991+1=9007199254740992", "-9007199254740991-1=-9007199254740992", "-5325786+0=-5325786", "5325786+0=5325786", "-10/-1=10", "-10/1=-10", "-10*-1=10", "-10*1=-10", "-1*-10=10", "1*-10=-10", "9-10=-1", "-9+10=1", "9720461847429978160121544487215098400/252477884013826224964152=38500250766113", "-9574957903731725597006190931748628130509/38500250766113=-248698585416990960511658890", "0<=>-1=1", "-1<=>-1=0", "0<=>0=0", "1<=>1=0", "1<=>-1=1", "7%4=3", "-1*-1=1", "-1*0=0", "6*5=30", "3532344566*49823554654=175993962540860910164", "306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000*306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000=93671200784116709168212603693264364491482625140650867012458907580850290479914858264565537535310631693272766559003934292711906009200684627249517173304448324734928094279109540960988005032678411543160632864773462725296609470788914777324208956654901916718052447794025580721872592906456183913463092191741342070445684239516003619737023925365750418514776445402451077204908500545814231399834008986998489607202994429669705269992974675929240962547032808582647838847126057197173872616052439789970160446312025948012277132907416345489644872455137593054745212854458919536502094918842320643368201359463330136605206022340820844860783320865546136566072749156961102456117415146305779819245975135392214778387549605996353627520849328240846135361548408069158100232642516618512258711646524053695093681984213935153010000089399908749062684640944173803129898417404797961177294631508660424692823609149766102132719268107342261493147254317799773900921401553815299967676469915320518174445065337121677714632518336731258782009414814334567511810621472393747064687526968680665458697226848388002476327915592106057333872616052439789970160446312025948012277132907416345489644872455137593054745212854458919536502094918842320643368201359463330136605206022340820844860689649664762019856904536553267838091625932521165128952233516227811364487907634747731788089985538696547573368802544473776446194223441831991262741538342075728960165587705104394192021995056721497205902051776170711077833288946615883183853085674853758507974771161355740521410846675200886077579684162126058431830475717314299296347939445989954767755930288891719226637427609836185444550609580805347569022203418477964077359417533994004736217734679815579419828489068466048860160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "11000000000/-11=-1000000000", "0/-1=0", "-2/-1=2", "-2%-1=0", "175993962540860910164/49823554654=3532344566", "49823554654/34566=1441403", "1234+1235=2469", "-5%-3=-2", "100000000000000000000*2=200000000000000000000", "100000000000000000000*0=0", "100000000000000000000/1000000000000000000000=0", "0b11111111111111111111111111=0b11111111111111111111111111", "1000%10=0", "-0=0", "30!=265252859812191058636308480000000", "-2147483649=-0x80000001", "10000000010000000-10000000=10000000000000000", "12345678901234567890123456789012345678901234567890123456789012345678901234567890/1234567890=10000000001000000000100000000010000000001000000000100000000010000000001", // an error if not zero-fill a result array in the division "(0x1000000000000000000000000*0x1000000000000000000000000)/0x1000000000000000000000000=0x1000000000000000000000000", // https://github.com/GoogleChromeLabs/jsbi/issues/13 "2788589391528142331873770897124985830679715361908029740727468171087321981075%170141183460469231731687303715884105727=170141183460469231731687303715884105726" ]; var run = function (input) { //if (testDivide() !== "truncated division" && input.indexOf("/") !== -1) { // console.log("TODO:testDivide"); // return; //} //if (testRemainder() !== "truncated division" && input.indexOf("%") !== -1) { // console.log("TODO:testRemainder"); // return; //} if (input.indexOf("0x") !== -1 && !supportsBase(I, 16)) { return; } if (input.indexOf("0b") !== -1 && !supportsBase(I, 2)) { return; } var ZERO = I.parseInt("0", 10); var ONE = I.parseInt("1", 10); var divideType = testDivide(); var divideInternal = function (a, b) { var q = I.divide(a, b); if (divideType === "truncated division") { return q; } if (divideType === "floored division") { var p = I.multiply(q, b); if (I.compareTo(a, ZERO) * I.compareTo(b, ZERO) < 0 && I.compareTo(p, a) !== 0) { q = I.add(q, ONE); } return q; } if (divideType === "Euclidean division") { var p = I.multiply(q, b); if (I.compareTo(a, ZERO) < 0 && I.compareTo(p, a) !== 0) { q = I.compareTo(b, ZERO) < 0 ? I.subtract(q, ONE) : I.add(q, ONE); } return q; } throw new RangeError(divideType); }; var remainderType = testRemainder(); var remainderInternal = function (a, b) { var r = I.remainder(a, b); if (remainderType === "truncated division") { return r; } if (remainderType === "floored division") { if (I.compareTo(a, ZERO) * I.compareTo(b, ZERO) < 0 && I.compareTo(r, ZERO) !== 0) { r = I.subtract(r, b); } return r; } if (remainderType === "Euclidean division") { if (I.compareTo(a, ZERO) < 0 && I.compareTo(r, ZERO) !== 0) { r = I.compareTo(b, ZERO) < 0 ? I.add(r, b) : I.subtract(r, b); } return r; } throw new RangeError(remainderType); }; var integerRegExp = /^(0b|0x)?([0-9a-fA-F]+)/; var operatorRegExp = /^(?:\*\*|[\+\-\*\/%]|<\=>|\!)/; var pow = function (x, count, accumulator) { if (count < 0) { throw new RangeError(); } return count < 1 ? accumulator : Math.floor(count / 2) * 2 !== count ? pow(x, count - 1, I.multiply(accumulator, x)) : pow(I.multiply(x, x), Math.floor(count / 2), accumulator); }; var factorial = function (n) { var result = I.parseInt("1", 10); var i = 0; while (++i <= n) { var tmp0 = i.toString(10); var tmp1 = I.parseInt(tmp0, 10); result = I.multiply(result, tmp1); } return result; }; var evaluate = function (input, position, p) { var result = undefined; var ok = true; while (position < input.length && ok) { if (result != undefined && input.slice(position, position + 1) === ")") { return [ position, result ]; } if (result == undefined && input.slice(position, position + 1) === "(") { var tmp = evaluate(input, position + 1, 0); position = tmp[0]; result = tmp[1]; if (input.slice(position, position + 1) === ")") { position += 1; } } else { var match = integerRegExp.exec(input.slice(position)); if (match != undefined) { position += match[0].length; var i = I.parseInt(match[2], match[1] === "0b" ? 2 : match[1] === "0x" ? 16 : 10); if (result == undefined) { result = i; } else { result = I.multiply(result, i); } } else if (result != undefined) { match = operatorRegExp.exec(input.slice(position)); if (match != undefined) { var tmp = undefined; if (match[0] === "+" && p < 2) { position += match[0].length; tmp = evaluate(input, position, 2); position = tmp[0]; result = I.add(result, tmp[1]); } else if (match[0] === "-" && p < 2) { position += match[0].length; tmp = evaluate(input, position, 2); position = tmp[0]; result = I.subtract(result, tmp[1]); } else if (match[0] === "*" && p < 3) { position += match[0].length; tmp = evaluate(input, position, 3); position = tmp[0]; result = I.multiply(result, tmp[1]); } else if (match[0] === "/" && p < 3) { position += match[0].length; tmp = evaluate(input, position, 3); position = tmp[0]; result = divideInternal(result, tmp[1]); } else if (match[0] === "%" && p < 3) { position += match[0].length; tmp = evaluate(input, position, 3); position = tmp[0]; result = remainderInternal(result, tmp[1]); } else if (match[0] === "<=>" && p < 1) { position += match[0].length; tmp = evaluate(input, position, 1); position = tmp[0]; result = I.compareTo(result, tmp[1]); } else if (match[0] === "**" && p < 3) { position += match[0].length; tmp = evaluate(input, position, 3); position = tmp[0]; result = pow(result, Number.parseInt(I.toString(tmp[1], 10)), I.parseInt("1", 10)); } else if (match[0] === "!") { position += match[0].length; result = factorial(Number.parseInt(I.toString(result, 10), 10)); } else { ok = false; } } else { ok = false; } } else if (result == undefined) { match = /^\-/.exec(input.slice(position)); if (match != undefined) { position += match[0].length; var tmp = evaluate(input, position, 3); position = tmp[0]; var MINUS_ONE = I.parseInt("-1", 10); result = I.multiply(MINUS_ONE, tmp[1]); } else { ok = false; } } else { ok = false; } } } return [ position, result ]; }; var t = input.split("="); var right = t.slice(-1).join("="); var radix = 10; var prefix = ""; if (right.slice(0, 2) === "0b" || right.slice(0, 3) === "-0b") { radix = 2; prefix = "0b"; } if (right.slice(0, 2) === "0x" || right.slice(0, 3) === "-0x") { radix = 16; prefix = "0x"; } var result = evaluate(t.slice(0, -1).join("="), 0, 0)[1]; if (input.indexOf("<=>") === -1) { var left = I.toString(result, radix).replace(/^(\-)?/, "$1" + prefix); assertEquals(left.toLowerCase(), right.toLowerCase(), input); //!toLowerCase } else { assertEquals(Math.sign(result).toString(), Math.sign(Number(right)).toString(), input); //assertEquals((1 / result).toString(), (1 / Number(right)).toString(), input); } }; var i = -1; var allTests = generatedTests.concat(basicTests); while (++i < allTests.length) { var input = allTests[i]; if (input !== "?") { testSuite.add(input, run.bind(undefined, input)); } } }()); testSuite.add("negate", function () { var a = I.parseInt("0", 10); var b = I.negate(a); var c = I.compareTo(a, b); assertEquals(c, 0, "0<=>-0"); }); testSuite.add("2", function () { for (var d = 2; d < 10 + 8; d += 8) { for (var c = 1; c < Math.pow(2, 53); c *= d) { var tmp0 = c.toString(); var base = I.parseInt(tmp0, 10); var one = I.parseInt("1", 10); var tmp1 = I.subtract(base, one); var tmp2 = I.multiply(tmp1, base); var tmp3 = I.add(tmp2, tmp1); var tmp4 = I.multiply(tmp3, base); var a = I.multiply(tmp4, base); var b = I.add(tmp4, one); var tmp6 = I.divide(a, b); assertEquals(I.toString(tmp6, 10), (c - 1).toString(), "?"); } } }); }; // TODO: https://github.com/peterolson/BigInteger.js/issues/88