author | Martin Soch <Martin.Soch@oracle.com> |
Tue, 05 Feb 2013 16:32:14 +0100 | |
branch | arithmetic |
changeset 675 | 7d3da112e2c1 |
parent 669 | 3754580b6c67 |
child 676 | eecf6077ec4e |
permissions | -rw-r--r-- |
Martin@438 | 1 |
// empty line needed here |
Martin@445 | 2 |
Number.prototype.add32 = function(x) { return (this + x) | 0; }; |
Martin@445 | 3 |
Number.prototype.sub32 = function(x) { return (this - x) | 0; }; |
Martin@445 | 4 |
Number.prototype.mul32 = function(x) { |
Martin@445 | 5 |
return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0; |
Martin@438 | 6 |
}; |
Martin@439 | 7 |
|
Martin@445 | 8 |
Number.prototype.toInt8 = function() { return (this << 24) >> 24; }; |
Martin@582 | 9 |
Number.prototype.toInt16 = function() { return (this << 16) >> 16; }; |
Martin@582 | 10 |
|
Martin@615 | 11 |
var __m32 = 0xFFFFFFFF; |
Martin@615 | 12 |
|
Martin@594 | 13 |
Number.prototype.next32 = function(low) { |
Martin@594 | 14 |
if (this === 0) { |
Martin@594 | 15 |
return low; |
Martin@594 | 16 |
} |
Martin@594 | 17 |
var l = new Number(low); |
Martin@616 | 18 |
l.hi = this | 0; |
Martin@594 | 19 |
return l; |
Martin@582 | 20 |
}; |
Martin@582 | 21 |
|
Martin@594 | 22 |
Number.prototype.high32 = function() { |
Martin@615 | 23 |
return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0; |
Martin@594 | 24 |
}; |
Martin@594 | 25 |
Number.prototype.toInt32 = function() { return this | 0; }; |
Martin@594 | 26 |
Number.prototype.toFP = function() { |
Martin@615 | 27 |
return this.hi ? this.hi * (__m32+1) + this : this; |
Martin@594 | 28 |
}; |
Martin@594 | 29 |
Number.prototype.toLong = function() { |
Martin@615 | 30 |
var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0; |
Martin@616 | 31 |
return hi.next32(Math.floor(this % (__m32+1))); |
Martin@607 | 32 |
}; |
Martin@607 | 33 |
|
Martin@607 | 34 |
Number.prototype.toExactString = function() { |
Martin@607 | 35 |
if (this.hi) { |
Martin@607 | 36 |
var res = 0; |
Martin@607 | 37 |
var a = [ 6,9,2,7,6,9,4,9,2,4 ]; |
Martin@607 | 38 |
var s = ''; |
Martin@607 | 39 |
var digit; |
Martin@675 | 40 |
var neg = this.hi < 0; |
Martin@675 | 41 |
if (neg) { |
Martin@675 | 42 |
var x = this.neg64(); |
Martin@675 | 43 |
var hi = x.hi; |
Martin@675 | 44 |
var low = x; |
Martin@675 | 45 |
} else { |
Martin@675 | 46 |
var hi = this.hi; |
Martin@675 | 47 |
var low = this; |
Martin@675 | 48 |
} |
Martin@607 | 49 |
for (var i = 0; i < a.length; i++) { |
Martin@607 | 50 |
res += hi * a[i]; |
Martin@607 | 51 |
var low_digit = low % 10; |
Martin@607 | 52 |
digit = (res % 10) + low_digit; |
Martin@607 | 53 |
|
Martin@607 | 54 |
low = Math.floor(low / 10); |
Martin@607 | 55 |
res = Math.floor(res / 10); |
Martin@607 | 56 |
|
Martin@607 | 57 |
if (digit >= 10) { |
Martin@607 | 58 |
digit -= 10; |
Martin@607 | 59 |
res++; |
Martin@607 | 60 |
} |
Martin@607 | 61 |
s = String(digit).concat(s); |
Martin@607 | 62 |
} |
Martin@675 | 63 |
return (neg ? '-' : '').concat(res).concat(s); |
Martin@607 | 64 |
} |
Martin@607 | 65 |
return String(this); |
Martin@607 | 66 |
}; |
Martin@594 | 67 |
|
Martin@594 | 68 |
Number.prototype.add64 = function(x) { |
Martin@594 | 69 |
var low = this + x; |
Martin@594 | 70 |
carry = 0; |
Martin@615 | 71 |
if (low > __m32) { |
Martin@594 | 72 |
carry = 1; |
Martin@615 | 73 |
low -= (__m32+1); |
Martin@594 | 74 |
} |
Martin@615 | 75 |
var hi = (this.high32() + x.high32() + carry) | 0; |
Martin@594 | 76 |
return hi.next32(low); |
Martin@582 | 77 |
}; |
Martin@582 | 78 |
|
Martin@620 | 79 |
Number.prototype.sub64 = function(x) { |
Martin@620 | 80 |
var low = this - x; |
Martin@620 | 81 |
carry = 0; |
Martin@620 | 82 |
if (low < 0) { |
Martin@620 | 83 |
carry = 1; |
Martin@620 | 84 |
low += (__m32+1); |
Martin@620 | 85 |
} |
Martin@620 | 86 |
var hi = (this.high32() - x.high32() - carry) | 0; |
Martin@620 | 87 |
return hi.next32(low); |
Martin@620 | 88 |
}; |
Martin@620 | 89 |
|
Martin@657 | 90 |
Number.prototype.mul64 = function(x) { |
Martin@657 | 91 |
var low = this.mul32(x); |
Martin@657 | 92 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@657 | 93 |
// first count upper 32 bits of (this.low * x.low) |
Martin@657 | 94 |
var hi_hi = 0; |
Martin@657 | 95 |
var hi_low = 0; |
Martin@657 | 96 |
var m = 1; |
Martin@657 | 97 |
for (var i = 0; i < 32; i++) { |
Martin@657 | 98 |
if (x & m) { |
Martin@657 | 99 |
hi_hi += this >>> 16; |
Martin@657 | 100 |
hi_low += this & 0xFFFF |
Martin@657 | 101 |
} |
Martin@657 | 102 |
hi_low >>= 1; |
Martin@657 | 103 |
hi_low += (hi_hi & 1) ? 0x8000 : 0; |
Martin@657 | 104 |
hi_hi >>= 1; |
Martin@657 | 105 |
m <<= 1; |
Martin@657 | 106 |
} |
Martin@657 | 107 |
var hi = (hi_hi << 16) + hi_low; |
Martin@657 | 108 |
|
Martin@657 | 109 |
var m1 = this.high32().mul32(x); |
Martin@657 | 110 |
var m2 = this.mul32(x.high32()); |
Martin@657 | 111 |
hi = hi.add32(m1).add32(m2); |
Martin@657 | 112 |
|
Martin@657 | 113 |
return hi.next32(low); |
Martin@657 | 114 |
}; |
Martin@657 | 115 |
|
Martin@594 | 116 |
Number.prototype.div64 = function(x) { |
Martin@594 | 117 |
var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough |
Martin@615 | 118 |
if (low > __m32) { |
Martin@615 | 119 |
var hi = Math.floor(low / (__m32+1)) | 0; |
Martin@615 | 120 |
return hi.next32(low % (__m32+1)); |
Martin@582 | 121 |
} |
Martin@594 | 122 |
return low; |
Martin@582 | 123 |
}; |
Martin@582 | 124 |
|
Martin@615 | 125 |
Number.prototype.and64 = function(x) { |
Martin@615 | 126 |
var low = this & x; |
Martin@627 | 127 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@615 | 128 |
if (this.hi && x.hi) { |
Martin@615 | 129 |
var hi = this.hi & x.hi; |
Martin@615 | 130 |
return hi.next32(low); |
Martin@615 | 131 |
}; |
Martin@615 | 132 |
return low; |
Martin@615 | 133 |
}; |
Martin@615 | 134 |
|
Martin@627 | 135 |
Number.prototype.or64 = function(x) { |
Martin@627 | 136 |
var low = this | x; |
Martin@627 | 137 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@627 | 138 |
if (this.hi || x.hi) { |
Martin@627 | 139 |
var hi = this.hi | x.hi; |
Martin@627 | 140 |
return hi.next32(low); |
Martin@627 | 141 |
}; |
Martin@627 | 142 |
return low; |
Martin@627 | 143 |
}; |
Martin@627 | 144 |
|
Martin@628 | 145 |
Number.prototype.xor64 = function(x) { |
Martin@628 | 146 |
var low = this ^ x; |
Martin@628 | 147 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@628 | 148 |
if (this.hi || x.hi) { |
Martin@628 | 149 |
var hi = this.hi ^ x.hi; |
Martin@628 | 150 |
return hi.next32(low); |
Martin@628 | 151 |
}; |
Martin@628 | 152 |
return low; |
Martin@628 | 153 |
}; |
Martin@628 | 154 |
|
Martin@594 | 155 |
Number.prototype.shl64 = function(x) { |
Martin@616 | 156 |
if (x >= 32) { |
Martin@629 | 157 |
var hi = this << (x - 32); |
Martin@594 | 158 |
return hi.next32(0); |
Martin@594 | 159 |
} else { |
Martin@629 | 160 |
var hi = this.high32() << x; |
Martin@615 | 161 |
var low_reminder = this >> (32 - x); |
Martin@594 | 162 |
hi |= low_reminder; |
Martin@594 | 163 |
var low = this << x; |
Martin@616 | 164 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@594 | 165 |
return hi.next32(low); |
Martin@594 | 166 |
} |
Martin@582 | 167 |
}; |
Martin@582 | 168 |
|
Martin@615 | 169 |
Number.prototype.shr64 = function(x) { |
Martin@619 | 170 |
if (x >= 32) { |
Martin@629 | 171 |
var low = this.high32() >> (x - 32); |
Martin@619 | 172 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@615 | 173 |
return low; |
Martin@615 | 174 |
} else { |
Martin@629 | 175 |
var low = this >> x; |
Martin@619 | 176 |
var hi_reminder = this.high32() << (32 - x); |
Martin@615 | 177 |
low |= hi_reminder; |
Martin@619 | 178 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@615 | 179 |
var hi = this.high32() >> x; |
Martin@615 | 180 |
return hi.next32(low); |
Martin@615 | 181 |
} |
Martin@615 | 182 |
}; |
Martin@615 | 183 |
|
Martin@629 | 184 |
Number.prototype.ushr64 = function(x) { |
Martin@629 | 185 |
if (x >= 32) { |
Martin@629 | 186 |
var low = this.high32() >>> (x - 32); |
Martin@629 | 187 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@629 | 188 |
return low; |
Martin@629 | 189 |
} else { |
Martin@629 | 190 |
var low = this >>> x; |
Martin@629 | 191 |
var hi_reminder = this.high32() << (32 - x); |
Martin@629 | 192 |
low |= hi_reminder; |
Martin@629 | 193 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@629 | 194 |
var hi = this.high32() >>> x; |
Martin@629 | 195 |
return hi.next32(low); |
Martin@629 | 196 |
} |
Martin@629 | 197 |
}; |
Martin@629 | 198 |
|
Martin@594 | 199 |
Number.prototype.compare64 = function(x) { |
Martin@582 | 200 |
if (this.hi == x.hi) { |
Martin@594 | 201 |
return (this == x) ? 0 : ((this < x) ? -1 : 1); |
Martin@582 | 202 |
} |
Martin@582 | 203 |
return (this.hi < x.hi) ? -1 : 1; |
Martin@582 | 204 |
}; |
Martin@630 | 205 |
|
Martin@630 | 206 |
Number.prototype.neg64 = function() { |
Martin@630 | 207 |
var hi = this.high32(); |
Martin@630 | 208 |
var low = this; |
Martin@630 | 209 |
if ((hi === 0) && (low < 0)) { return -low; } |
Martin@630 | 210 |
hi = ~hi; |
Martin@630 | 211 |
low = ~low; |
Martin@630 | 212 |
low += (low < 0) ? (__m32+1) : 0; |
Martin@669 | 213 |
var ret = hi.next32(low); |
Martin@669 | 214 |
return ret.add64(1); |
Martin@630 | 215 |
}; |