eligendiexercitationem
Version:
Yet another class for arbitrary-precision integers in pure JavaScript. Small. Well tested.
122 lines (115 loc) • 3.09 kB
HTML
<script src="libs/http___www_cs_students_stanford_edu__tjw_jsbn_.js"></script>
<script>
function LiteralNode(value) {
this.value = value;
}
LiteralNode.prototype.toString = function () {
return this.value;
};
LiteralNode.prototype.evaluate = function () {
return new BigInteger(this.value, 10);
};
function BinaryOperatorNode(operator, a, b) {
this.operator = operator;
this.a = a;
this.b = b;
}
BinaryOperatorNode.prototype.toString = function () {
function precedence(operator) {
switch (operator) {
case "<=>": return 0;
case "+": return 1;
case "-": return 1;
case "*": return 2;
case "/": return 2;
case "%": return 2;
}
throw new Error();
}
function fence(e, operator, isStart) {
if (isStart) {
return precedence(operator) > (e instanceof LiteralNode ? 42 : precedence(e.operator)) ? "(" + e.toString() + ")" : e.toString();
}
return precedence(operator) >= (e instanceof LiteralNode ? 42 : precedence(e.operator)) ? "(" + e.toString() + ")" : e.toString();
}
return fence(this.a, this.operator, true) + this.operator + fence(this.b, this.operator, false);
};
BinaryOperatorNode.prototype.evaluate = function () {
var operator = this.operator;
var a = this.a.evaluate();
var b = this.b.evaluate();
if (a == null || b == null) {
return null;
}
if (typeof a === "number" || typeof b === "number") {
return null;
}
if (operator === "+") {
return a.add(b);
}
if (operator === "-") {
return a.subtract(b);
}
if (operator === "*") {
return a.multiply(b);
}
if (operator === "/") {
if (b.compareTo(BigInteger.ZERO) === 0) {
return null;
}
return a.divide(b);
}
if (operator === "%") {
if (b.compareTo(BigInteger.ZERO) === 0) {
return null;
}
return a.remainder(b);
}
if (operator === "<=>") {
return Math.min(Math.max(a.compareTo(b), -1), +1);
}
throw new Error();
};
var operators = ["+", "-", "*", "/", "%", "<=>"];
function* generateNode(operatorsCount, possibleOperators, possibleValues) {
if (operatorsCount === 0) {
for (var value of possibleValues) {
yield new LiteralNode(value);
}
} else {
for (var i = 0; i < operatorsCount; i += 1) {
for (var a of generateNode(i, possibleOperators, possibleValues)) {
for (var b of generateNode(operatorsCount - 1 - i, possibleOperators, possibleValues)) {
for (var operator of possibleOperators) {
yield new BinaryOperatorNode(operator, a, b);
}
}
}
}
}
};
function generateSomeTests() {
var values = [
"0",
"1",
"2",
"3",
"9",
"67108864", //2**26
"9007199254740992", //2**53
"65536",
"4294967296",
"18446744073709551616",
"10000000"
];
var result = [];
for (var node of generateNode(2, operators, values)) {
var x = node.evaluate();
if (x != null) {
result.push(node.toString() + "=" + x.toString());
}
}
return result;
}
console.log(JSON.stringify(generateSomeTests(), null, 2));
</script>