Gav Wood
11 years ago
3 changed files with 441 additions and 3 deletions
@ -0,0 +1,379 @@ |
|||
var bigInt = (function () { |
|||
var base = 10000000, logBase = 7; |
|||
var sign = { |
|||
positive: false, |
|||
negative: true |
|||
}; |
|||
|
|||
var normalize = function (first, second) { |
|||
var a = first.value, b = second.value; |
|||
var length = a.length > b.length ? a.length : b.length; |
|||
for (var i = 0; i < length; i++) { |
|||
a[i] = a[i] || 0; |
|||
b[i] = b[i] || 0; |
|||
} |
|||
for (var i = length - 1; i >= 0; i--) { |
|||
if (a[i] === 0 && b[i] === 0) { |
|||
a.pop(); |
|||
b.pop(); |
|||
} else break; |
|||
} |
|||
if (!a.length) a = [0], b = [0]; |
|||
first.value = a; |
|||
second.value = b; |
|||
}; |
|||
|
|||
var parse = function (text, first) { |
|||
if (typeof text === "object") return text; |
|||
text += ""; |
|||
var s = sign.positive, value = []; |
|||
if (text[0] === "-") { |
|||
s = sign.negative; |
|||
text = text.slice(1); |
|||
} |
|||
var base = 10; |
|||
if (text.slice(0, 2) == "0x") { |
|||
base = 16; |
|||
text = text.slice(2); |
|||
} |
|||
else { |
|||
var texts = text.split("e"); |
|||
if (texts.length > 2) throw new Error("Invalid integer"); |
|||
if (texts[1]) { |
|||
var exp = texts[1]; |
|||
if (exp[0] === "+") exp = exp.slice(1); |
|||
exp = parse(exp); |
|||
if (exp.lesser(0)) throw new Error("Cannot include negative exponent part for integers"); |
|||
while (exp.notEquals(0)) { |
|||
texts[0] += "0"; |
|||
exp = exp.prev(); |
|||
} |
|||
} |
|||
text = texts[0]; |
|||
} |
|||
if (text === "-0") text = "0"; |
|||
text = text.toUpperCase(); |
|||
var isValid = (base == 16 ? /^[0-9A-F]+$/ : /^[0-9]+$/).test(text); |
|||
if (!isValid) throw new Error("Invalid integer"); |
|||
if (base == 16) { |
|||
var val = bigInt(0); |
|||
while (text.length) { |
|||
v = text.charCodeAt(0) - 48; |
|||
if (v > 9) |
|||
v -= 7; |
|||
text = text.slice(1); |
|||
val = val.times(16).plus(v); |
|||
} |
|||
return val; |
|||
} |
|||
else { |
|||
while (text.length) { |
|||
var divider = text.length > logBase ? text.length - logBase : 0; |
|||
value.push(+text.slice(divider)); |
|||
text = text.slice(0, divider); |
|||
} |
|||
var val = bigInt(value, s); |
|||
if (first) normalize(first, val); |
|||
return val; |
|||
} |
|||
}; |
|||
|
|||
var goesInto = function (a, b) { |
|||
var a = bigInt(a, sign.positive), b = bigInt(b, sign.positive); |
|||
if (a.equals(0)) throw new Error("Cannot divide by 0"); |
|||
var n = 0; |
|||
do { |
|||
var inc = 1; |
|||
var c = bigInt(a.value, sign.positive), t = c.times(10); |
|||
while (t.lesser(b)) { |
|||
c = t; |
|||
inc *= 10; |
|||
t = t.times(10); |
|||
} |
|||
while (c.lesserOrEquals(b)) { |
|||
b = b.minus(c); |
|||
n += inc; |
|||
} |
|||
} while (a.lesserOrEquals(b)); |
|||
|
|||
return { |
|||
remainder: b.value, |
|||
result: n |
|||
}; |
|||
}; |
|||
|
|||
var bigInt = function (value, s) { |
|||
var self = { |
|||
value: value, |
|||
sign: s |
|||
}; |
|||
var o = { |
|||
value: value, |
|||
sign: s, |
|||
negate: function (m) { |
|||
var first = m || self; |
|||
return bigInt(first.value, !first.sign); |
|||
}, |
|||
abs: function (m) { |
|||
var first = m || self; |
|||
return bigInt(first.value, sign.positive); |
|||
}, |
|||
add: function (n, m) { |
|||
var s, first = self, second; |
|||
if (m) (first = parse(n)) && (second = parse(m)); |
|||
else second = parse(n, first); |
|||
s = first.sign; |
|||
if (first.sign !== second.sign) { |
|||
first = bigInt(first.value, sign.positive); |
|||
second = bigInt(second.value, sign.positive); |
|||
return s === sign.positive ? |
|||
o.subtract(first, second) : |
|||
o.subtract(second, first); |
|||
} |
|||
normalize(first, second); |
|||
var a = first.value, b = second.value; |
|||
var result = [], |
|||
carry = 0; |
|||
for (var i = 0; i < a.length || carry > 0; i++) { |
|||
var sum = (a[i] || 0) + (b[i] || 0) + carry; |
|||
carry = sum >= base ? 1 : 0; |
|||
sum -= carry * base; |
|||
result.push(sum); |
|||
} |
|||
return bigInt(result, s); |
|||
}, |
|||
plus: function (n, m) { |
|||
return o.add(n, m); |
|||
}, |
|||
subtract: function (n, m) { |
|||
var first = self, second; |
|||
if (m) (first = parse(n)) && (second = parse(m)); |
|||
else second = parse(n, first); |
|||
if (first.sign !== second.sign) return o.add(first, o.negate(second)); |
|||
if (first.sign === sign.negative) return o.subtract(o.negate(second), o.negate(first)); |
|||
if (o.compare(first, second) === -1) return o.negate(o.subtract(second, first)); |
|||
var a = first.value, b = second.value; |
|||
var result = [], |
|||
borrow = 0; |
|||
for (var i = 0; i < a.length; i++) { |
|||
var tmp = a[i] - borrow; |
|||
borrow = tmp < b[i] ? 1 : 0; |
|||
var minuend = (borrow * base) + tmp - b[i]; |
|||
result.push(minuend); |
|||
} |
|||
return bigInt(result, sign.positive); |
|||
}, |
|||
minus: function (n, m) { |
|||
return o.subtract(n, m); |
|||
}, |
|||
multiply: function (n, m) { |
|||
var s, first = self, second; |
|||
if (m) (first = parse(n)) && (second = parse(m)); |
|||
else second = parse(n, first); |
|||
s = first.sign !== second.sign; |
|||
var a = first.value, b = second.value; |
|||
var resultSum = []; |
|||
for (var i = 0; i < a.length; i++) { |
|||
resultSum[i] = []; |
|||
var j = i; |
|||
while (j--) { |
|||
resultSum[i].push(0); |
|||
} |
|||
} |
|||
var carry = 0; |
|||
for (var i = 0; i < a.length; i++) { |
|||
var x = a[i]; |
|||
for (var j = 0; j < b.length || carry > 0; j++) { |
|||
var y = b[j]; |
|||
var product = y ? (x * y) + carry : carry; |
|||
carry = product > base ? Math.floor(product / base) : 0; |
|||
product -= carry * base; |
|||
resultSum[i].push(product); |
|||
} |
|||
} |
|||
var max = -1; |
|||
for (var i = 0; i < resultSum.length; i++) { |
|||
var len = resultSum[i].length; |
|||
if (len > max) max = len; |
|||
} |
|||
var result = [], carry = 0; |
|||
for (var i = 0; i < max || carry > 0; i++) { |
|||
var sum = carry; |
|||
for (var j = 0; j < resultSum.length; j++) { |
|||
sum += resultSum[j][i] || 0; |
|||
} |
|||
carry = sum > base ? Math.floor(sum / base) : 0; |
|||
sum -= carry * base; |
|||
result.push(sum); |
|||
} |
|||
return bigInt(result, s); |
|||
}, |
|||
times: function (n, m) { |
|||
return o.multiply(n, m); |
|||
}, |
|||
divmod: function (n, m) { |
|||
var s, first = self, second; |
|||
if (m) (first = parse(n)) && (second = parse(m)); |
|||
else second = parse(n, first); |
|||
s = first.sign !== second.sign; |
|||
if (bigInt(first.value, first.sign).equals(0)) return { |
|||
quotient: bigInt([0], sign.positive), |
|||
remainder: bigInt([0], sign.positive) |
|||
}; |
|||
if (second.equals(0)) throw new Error("Cannot divide by zero"); |
|||
var a = first.value, b = second.value; |
|||
var result = [], remainder = []; |
|||
for (var i = a.length - 1; i >= 0; i--) { |
|||
var n = [a[i]].concat(remainder); |
|||
var quotient = goesInto(b, n); |
|||
result.push(quotient.result); |
|||
remainder = quotient.remainder; |
|||
} |
|||
result.reverse(); |
|||
return { |
|||
quotient: bigInt(result, s), |
|||
remainder: bigInt(remainder, first.sign) |
|||
}; |
|||
}, |
|||
divide: function (n, m) { |
|||
return o.divmod(n, m).quotient; |
|||
}, |
|||
over: function (n, m) { |
|||
return o.divide(n, m); |
|||
}, |
|||
mod: function (n, m) { |
|||
return o.divmod(n, m).remainder; |
|||
}, |
|||
pow: function (n, m) { |
|||
var first = self, second; |
|||
if (m) (first = parse(n)) && (second = parse(m)); |
|||
else second = parse(n, first); |
|||
var a = first, b = second; |
|||
if (b.lesser(0)) return ZERO; |
|||
if (b.equals(0)) return ONE; |
|||
var result = bigInt(a.value, a.sign); |
|||
|
|||
if (b.mod(2).equals(0)) { |
|||
var c = result.pow(b.over(2)); |
|||
return c.times(c); |
|||
} else { |
|||
return result.times(result.pow(b.minus(1))); |
|||
} |
|||
}, |
|||
next: function (m) { |
|||
var first = m || self; |
|||
return o.add(first, 1); |
|||
}, |
|||
prev: function (m) { |
|||
var first = m || self; |
|||
return o.subtract(first, 1); |
|||
}, |
|||
compare: function (n, m) { |
|||
var first = self, second; |
|||
if (m) (first = parse(n)) && (second = parse(m, first)); |
|||
else second = parse(n, first); |
|||
normalize(first, second); |
|||
if (first.value.length === 1 && second.value.length === 1 && first.value[0] === 0 && second.value[0] === 0) return 0; |
|||
if (second.sign !== first.sign) return first.sign === sign.positive ? 1 : -1; |
|||
var multiplier = first.sign === sign.positive ? 1 : -1; |
|||
var a = first.value, b = second.value; |
|||
for (var i = a.length - 1; i >= 0; i--) { |
|||
if (a[i] > b[i]) return 1 * multiplier; |
|||
if (b[i] > a[i]) return -1 * multiplier; |
|||
} |
|||
return 0; |
|||
}, |
|||
compareAbs: function (n, m) { |
|||
var first = self, second; |
|||
if (m) (first = parse(n)) && (second = parse(m, first)); |
|||
else second = parse(n, first); |
|||
first.sign = second.sign = sign.positive; |
|||
return o.compare(first, second); |
|||
}, |
|||
equals: function (n, m) { |
|||
return o.compare(n, m) === 0; |
|||
}, |
|||
notEquals: function (n, m) { |
|||
return !o.equals(n, m); |
|||
}, |
|||
lesser: function (n, m) { |
|||
return o.compare(n, m) < 0; |
|||
}, |
|||
greater: function (n, m) { |
|||
return o.compare(n, m) > 0; |
|||
}, |
|||
greaterOrEquals: function (n, m) { |
|||
return o.compare(n, m) >= 0; |
|||
}, |
|||
lesserOrEquals: function (n, m) { |
|||
return o.compare(n, m) <= 0; |
|||
}, |
|||
isPositive: function (m) { |
|||
var first = m || self; |
|||
return first.sign === sign.positive; |
|||
}, |
|||
isNegative: function (m) { |
|||
var first = m || self; |
|||
return first.sign === sign.negative; |
|||
}, |
|||
isEven: function (m) { |
|||
var first = m || self; |
|||
return first.value[0] % 2 === 0; |
|||
}, |
|||
isOdd: function (m) { |
|||
var first = m || self; |
|||
return first.value[0] % 2 === 1; |
|||
}, |
|||
toString: function (m) { |
|||
var first = m || self; |
|||
var str = "", len = first.value.length; |
|||
while (len--) { |
|||
if (first.value[len].toString().length === 8) str += first.value[len]; |
|||
else str += (base.toString() + first.value[len]).slice(-logBase); |
|||
} |
|||
while (str[0] === "0") { |
|||
str = str.slice(1); |
|||
} |
|||
if (!str.length) str = "0"; |
|||
var s = first.sign === sign.positive ? "" : "-"; |
|||
return s + str; |
|||
}, |
|||
toHex: function (m) { |
|||
var first = m || self; |
|||
var str = ""; |
|||
var l = this.abs(); |
|||
while (l > 0) { |
|||
var qr = l.divmod(256); |
|||
var b = qr.remainder.toJSNumber(); |
|||
str = (b >> 4).toString(16) + (b & 15).toString(16) + str; |
|||
l = qr.quotient; |
|||
} |
|||
return (this.isNegative() ? "-" : "") + "0x" + str; |
|||
}, |
|||
toJSNumber: function (m) { |
|||
return +o.toString(m); |
|||
}, |
|||
valueOf: function (m) { |
|||
return o.toJSNumber(m); |
|||
} |
|||
}; |
|||
return o; |
|||
}; |
|||
|
|||
var ZERO = bigInt([0], sign.positive); |
|||
var ONE = bigInt([1], sign.positive); |
|||
var MINUS_ONE = bigInt([1], sign.negative); |
|||
|
|||
var fnReturn = function (a) { |
|||
if (typeof a === "undefined") return ZERO; |
|||
return parse(a); |
|||
}; |
|||
fnReturn.zero = ZERO; |
|||
fnReturn.one = ONE; |
|||
fnReturn.minusOne = MINUS_ONE; |
|||
return fnReturn; |
|||
})(); |
|||
|
|||
if (typeof module !== "undefined") { |
|||
module.exports = bigInt; |
|||
} |
@ -0,0 +1,54 @@ |
|||
if (typeof(require) !== "undefined") |
|||
require( ['BigInteger'], function() {} ) |
|||
else if (typeof(bigInt) === "undefined") |
|||
alert("You need to have included BigInteger.js for eth to work.") |
|||
|
|||
String.prototype.pad = function(l, r) { |
|||
if (r === null) { |
|||
r = l |
|||
if (!(this.substr(0, 2) == "0x" || /^\d+$/.test(this))) |
|||
l = 0 |
|||
} |
|||
var ret = this.bin(); |
|||
while (ret.length < l) |
|||
ret = "\0" + ret |
|||
while (ret.length < r) |
|||
ret = ret + "\0" |
|||
return ret; |
|||
} |
|||
|
|||
String.prototype.unpad = function() { |
|||
var i = this.length; |
|||
while (i && this[i - 1] == "\0") |
|||
--i |
|||
return this.substr(0, i) |
|||
} |
|||
|
|||
String.prototype.bin = function() { |
|||
if (this.substr(0, 2) == "0x") { |
|||
bytes = [] |
|||
var i = 2; |
|||
// Check if it's odd - pad with a zero if so.
|
|||
if (s.length % 2) |
|||
bytes.push(parseInt(this.substr(i++, 1), 16)) |
|||
for (; i < s.length - 1; i += 2) |
|||
bytes.push(parseInt(this.substr(i, 2), 16)); |
|||
return String.fromCharCode.apply(String, bytes); |
|||
} else if (/^\d+$/.test(this)) |
|||
return bigInt(this).toHex().bin() |
|||
|
|||
// Otherwise we'll return the "String" object instead of an actual string
|
|||
return this.substr(0, this.length) |
|||
} |
|||
|
|||
String.prototype.unbin = function() { |
|||
var i, l, o = ''; |
|||
for(i = 0, l = this.length; i < l; i++) { |
|||
var n = this.charCodeAt(i).toString(16); |
|||
o += n.length < 2 ? '0' + n : n; |
|||
} |
|||
|
|||
return "0x" + o; |
|||
} |
|||
|
|||
|
Loading…
Reference in new issue