Martin@438: // empty line needed here Martin@445: Number.prototype.add32 = function(x) { return (this + x) | 0; }; Martin@445: Number.prototype.sub32 = function(x) { return (this - x) | 0; }; Martin@445: Number.prototype.mul32 = function(x) { Martin@445: return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0; Martin@438: }; Martin@439: Martin@445: Number.prototype.toInt8 = function() { return (this << 24) >> 24; }; Martin@582: Number.prototype.toInt16 = function() { return (this << 16) >> 16; }; Martin@582: Martin@615: var __m32 = 0xFFFFFFFF; Martin@615: Martin@594: Number.prototype.next32 = function(low) { Martin@594: if (this === 0) { Martin@594: return low; Martin@594: } Martin@594: var l = new Number(low); Martin@616: l.hi = this | 0; Martin@594: return l; Martin@582: }; Martin@582: Martin@594: Number.prototype.high32 = function() { Martin@615: return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0; Martin@594: }; Martin@594: Number.prototype.toInt32 = function() { return this | 0; }; Martin@594: Number.prototype.toFP = function() { Martin@615: return this.hi ? this.hi * (__m32+1) + this : this; Martin@594: }; Martin@594: Number.prototype.toLong = function() { Martin@615: var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0; Martin@616: return hi.next32(Math.floor(this % (__m32+1))); Martin@607: }; Martin@607: Martin@607: Number.prototype.toExactString = function() { Martin@607: if (this.hi) { Martin@607: var res = 0; Martin@607: var a = [ 6,9,2,7,6,9,4,9,2,4 ]; Martin@607: var s = ''; Martin@607: var digit; Martin@607: var hi = this.hi; Martin@607: var low = this; Martin@607: for (var i = 0; i < a.length; i++) { Martin@607: res += hi * a[i]; Martin@607: var low_digit = low % 10; Martin@607: digit = (res % 10) + low_digit; Martin@607: Martin@607: low = Math.floor(low / 10); Martin@607: res = Math.floor(res / 10); Martin@607: Martin@607: if (digit >= 10) { Martin@607: digit -= 10; Martin@607: res++; Martin@607: } Martin@607: s = String(digit).concat(s); Martin@607: } Martin@607: return String(res).concat(s); Martin@607: } Martin@607: return String(this); Martin@607: }; Martin@594: Martin@594: Number.prototype.add64 = function(x) { Martin@594: var low = this + x; Martin@594: carry = 0; Martin@615: if (low > __m32) { Martin@594: carry = 1; Martin@615: low -= (__m32+1); Martin@594: } Martin@615: var hi = (this.high32() + x.high32() + carry) | 0; Martin@594: return hi.next32(low); Martin@582: }; Martin@582: Martin@620: Number.prototype.sub64 = function(x) { Martin@620: var low = this - x; Martin@620: carry = 0; Martin@620: if (low < 0) { Martin@620: carry = 1; Martin@620: low += (__m32+1); Martin@620: } Martin@620: var hi = (this.high32() - x.high32() - carry) | 0; Martin@620: return hi.next32(low); Martin@620: }; Martin@620: Martin@657: Number.prototype.mul64 = function(x) { Martin@657: var low = this.mul32(x); Martin@657: low += (low < 0) ? (__m32+1) : 0; Martin@657: // first count upper 32 bits of (this.low * x.low) Martin@657: var hi_hi = 0; Martin@657: var hi_low = 0; Martin@657: var m = 1; Martin@657: for (var i = 0; i < 32; i++) { Martin@657: if (x & m) { Martin@657: hi_hi += this >>> 16; Martin@657: hi_low += this & 0xFFFF Martin@657: } Martin@657: hi_low >>= 1; Martin@657: hi_low += (hi_hi & 1) ? 0x8000 : 0; Martin@657: hi_hi >>= 1; Martin@657: m <<= 1; Martin@657: } Martin@657: var hi = (hi_hi << 16) + hi_low; Martin@657: Martin@657: var m1 = this.high32().mul32(x); Martin@657: var m2 = this.mul32(x.high32()); Martin@657: hi = hi.add32(m1).add32(m2); Martin@657: Martin@657: return hi.next32(low); Martin@657: }; Martin@657: Martin@594: Number.prototype.div64 = function(x) { Martin@594: var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough Martin@615: if (low > __m32) { Martin@615: var hi = Math.floor(low / (__m32+1)) | 0; Martin@615: return hi.next32(low % (__m32+1)); Martin@582: } Martin@594: return low; Martin@582: }; Martin@582: Martin@615: Number.prototype.and64 = function(x) { Martin@615: var low = this & x; Martin@627: low += (low < 0) ? (__m32+1) : 0; Martin@615: if (this.hi && x.hi) { Martin@615: var hi = this.hi & x.hi; Martin@615: return hi.next32(low); Martin@615: }; Martin@615: return low; Martin@615: }; Martin@615: Martin@627: Number.prototype.or64 = function(x) { Martin@627: var low = this | x; Martin@627: low += (low < 0) ? (__m32+1) : 0; Martin@627: if (this.hi || x.hi) { Martin@627: var hi = this.hi | x.hi; Martin@627: return hi.next32(low); Martin@627: }; Martin@627: return low; Martin@627: }; Martin@627: Martin@628: Number.prototype.xor64 = function(x) { Martin@628: var low = this ^ x; Martin@628: low += (low < 0) ? (__m32+1) : 0; Martin@628: if (this.hi || x.hi) { Martin@628: var hi = this.hi ^ x.hi; Martin@628: return hi.next32(low); Martin@628: }; Martin@628: return low; Martin@628: }; Martin@628: Martin@594: Number.prototype.shl64 = function(x) { Martin@616: if (x >= 32) { Martin@629: var hi = this << (x - 32); Martin@594: return hi.next32(0); Martin@594: } else { Martin@629: var hi = this.high32() << x; Martin@615: var low_reminder = this >> (32 - x); Martin@594: hi |= low_reminder; Martin@594: var low = this << x; Martin@616: low += (low < 0) ? (__m32+1) : 0; Martin@594: return hi.next32(low); Martin@594: } Martin@582: }; Martin@582: Martin@615: Number.prototype.shr64 = function(x) { Martin@619: if (x >= 32) { Martin@629: var low = this.high32() >> (x - 32); Martin@619: low += (low < 0) ? (__m32+1) : 0; Martin@615: return low; Martin@615: } else { Martin@629: var low = this >> x; Martin@619: var hi_reminder = this.high32() << (32 - x); Martin@615: low |= hi_reminder; Martin@619: low += (low < 0) ? (__m32+1) : 0; Martin@615: var hi = this.high32() >> x; Martin@615: return hi.next32(low); Martin@615: } Martin@615: }; Martin@615: Martin@629: Number.prototype.ushr64 = function(x) { Martin@629: if (x >= 32) { Martin@629: var low = this.high32() >>> (x - 32); Martin@629: low += (low < 0) ? (__m32+1) : 0; Martin@629: return low; Martin@629: } else { Martin@629: var low = this >>> x; Martin@629: var hi_reminder = this.high32() << (32 - x); Martin@629: low |= hi_reminder; Martin@629: low += (low < 0) ? (__m32+1) : 0; Martin@629: var hi = this.high32() >>> x; Martin@629: return hi.next32(low); Martin@629: } Martin@629: }; Martin@629: Martin@594: Number.prototype.compare64 = function(x) { Martin@582: if (this.hi == x.hi) { Martin@594: return (this == x) ? 0 : ((this < x) ? -1 : 1); Martin@582: } Martin@582: return (this.hi < x.hi) ? -1 : 1; Martin@582: }; Martin@630: Martin@630: Number.prototype.neg64 = function() { Martin@630: var hi = this.high32(); Martin@630: var low = this; Martin@630: if ((hi === 0) && (low < 0)) { return -low; } Martin@630: hi = ~hi; Martin@630: low = ~low; Martin@630: low += (low < 0) ? (__m32+1) : 0; Martin@669: var ret = hi.next32(low); Martin@669: return ret.add64(1); Martin@630: };