123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648 |
- /**
- C-like unsigned 64 bits integers in Javascript
- Copyright (C) 2013, Pierre Curto
- MIT license
- */
- ;(function (root) {
- // Local cache for typical radices
- var radixPowerCache = {
- 16: UINT64( Math.pow(16, 5) )
- , 10: UINT64( Math.pow(10, 5) )
- , 2: UINT64( Math.pow(2, 5) )
- }
- var radixCache = {
- 16: UINT64(16)
- , 10: UINT64(10)
- , 2: UINT64(2)
- }
- /**
- * Represents an unsigned 64 bits integer
- * @constructor
- * @param {Number} first low bits (8)
- * @param {Number} second low bits (8)
- * @param {Number} first high bits (8)
- * @param {Number} second high bits (8)
- * or
- * @param {Number} low bits (32)
- * @param {Number} high bits (32)
- * or
- * @param {String|Number} integer as a string | integer as a number
- * @param {Number|Undefined} radix (optional, default=10)
- * @return
- */
- function UINT64 (a00, a16, a32, a48) {
- if ( !(this instanceof UINT64) )
- return new UINT64(a00, a16, a32, a48)
- this.remainder = null
- if (typeof a00 == 'string')
- return fromString.call(this, a00, a16)
- if (typeof a16 == 'undefined')
- return fromNumber.call(this, a00)
- fromBits.apply(this, arguments)
- }
- /**
- * Set the current _UINT64_ object with its low and high bits
- * @method fromBits
- * @param {Number} first low bits (8)
- * @param {Number} second low bits (8)
- * @param {Number} first high bits (8)
- * @param {Number} second high bits (8)
- * or
- * @param {Number} low bits (32)
- * @param {Number} high bits (32)
- * @return ThisExpression
- */
- function fromBits (a00, a16, a32, a48) {
- if (typeof a32 == 'undefined') {
- this._a00 = a00 & 0xFFFF
- this._a16 = a00 >>> 16
- this._a32 = a16 & 0xFFFF
- this._a48 = a16 >>> 16
- return this
- }
- this._a00 = a00 | 0
- this._a16 = a16 | 0
- this._a32 = a32 | 0
- this._a48 = a48 | 0
- return this
- }
- UINT64.prototype.fromBits = fromBits
- /**
- * Set the current _UINT64_ object from a number
- * @method fromNumber
- * @param {Number} number
- * @return ThisExpression
- */
- function fromNumber (value) {
- this._a00 = value & 0xFFFF
- this._a16 = value >>> 16
- this._a32 = 0
- this._a48 = 0
- return this
- }
- UINT64.prototype.fromNumber = fromNumber
- /**
- * Set the current _UINT64_ object from a string
- * @method fromString
- * @param {String} integer as a string
- * @param {Number} radix (optional, default=10)
- * @return ThisExpression
- */
- function fromString (s, radix) {
- radix = radix || 10
- this._a00 = 0
- this._a16 = 0
- this._a32 = 0
- this._a48 = 0
- /*
- In Javascript, bitwise operators only operate on the first 32 bits
- of a number, even though parseInt() encodes numbers with a 53 bits
- mantissa.
- Therefore UINT64(<Number>) can only work on 32 bits.
- The radix maximum value is 36 (as per ECMA specs) (26 letters + 10 digits)
- maximum input value is m = 32bits as 1 = 2^32 - 1
- So the maximum substring length n is:
- 36^(n+1) - 1 = 2^32 - 1
- 36^(n+1) = 2^32
- (n+1)ln(36) = 32ln(2)
- n = 32ln(2)/ln(36) - 1
- n = 5.189644915687692
- n = 5
- */
- var radixUint = radixPowerCache[radix] || new UINT64( Math.pow(radix, 5) )
- for (var i = 0, len = s.length; i < len; i += 5) {
- var size = Math.min(5, len - i)
- var value = parseInt( s.slice(i, i + size), radix )
- this.multiply(
- size < 5
- ? new UINT64( Math.pow(radix, size) )
- : radixUint
- )
- .add( new UINT64(value) )
- }
- return this
- }
- UINT64.prototype.fromString = fromString
- /**
- * Convert this _UINT64_ to a number (last 32 bits are dropped)
- * @method toNumber
- * @return {Number} the converted UINT64
- */
- UINT64.prototype.toNumber = function () {
- return (this._a16 * 65536) + this._a00
- }
- /**
- * Convert this _UINT64_ to a string
- * @method toString
- * @param {Number} radix (optional, default=10)
- * @return {String} the converted UINT64
- */
- UINT64.prototype.toString = function (radix) {
- radix = radix || 10
- var radixUint = radixCache[radix] || new UINT64(radix)
- if ( !this.gt(radixUint) ) return this.toNumber().toString(radix)
- var self = this.clone()
- var res = new Array(64)
- for (var i = 63; i >= 0; i--) {
- self.div(radixUint)
- res[i] = self.remainder.toNumber().toString(radix)
- if ( !self.gt(radixUint) ) break
- }
- res[i-1] = self.toNumber().toString(radix)
- return res.join('')
- }
- /**
- * Add two _UINT64_. The current _UINT64_ stores the result
- * @method add
- * @param {Object} other UINT64
- * @return ThisExpression
- */
- UINT64.prototype.add = function (other) {
- var a00 = this._a00 + other._a00
- var a16 = a00 >>> 16
- a16 += this._a16 + other._a16
- var a32 = a16 >>> 16
- a32 += this._a32 + other._a32
- var a48 = a32 >>> 16
- a48 += this._a48 + other._a48
- this._a00 = a00 & 0xFFFF
- this._a16 = a16 & 0xFFFF
- this._a32 = a32 & 0xFFFF
- this._a48 = a48 & 0xFFFF
- return this
- }
- /**
- * Subtract two _UINT64_. The current _UINT64_ stores the result
- * @method subtract
- * @param {Object} other UINT64
- * @return ThisExpression
- */
- UINT64.prototype.subtract = function (other) {
- return this.add( other.clone().negate() )
- }
- /**
- * Multiply two _UINT64_. The current _UINT64_ stores the result
- * @method multiply
- * @param {Object} other UINT64
- * @return ThisExpression
- */
- UINT64.prototype.multiply = function (other) {
- /*
- a = a00 + a16 + a32 + a48
- b = b00 + b16 + b32 + b48
- a*b = (a00 + a16 + a32 + a48)(b00 + b16 + b32 + b48)
- = a00b00 + a00b16 + a00b32 + a00b48
- + a16b00 + a16b16 + a16b32 + a16b48
- + a32b00 + a32b16 + a32b32 + a32b48
- + a48b00 + a48b16 + a48b32 + a48b48
- a16b48, a32b32, a48b16, a48b32 and a48b48 overflow the 64 bits
- so it comes down to:
- a*b = a00b00 + a00b16 + a00b32 + a00b48
- + a16b00 + a16b16 + a16b32
- + a32b00 + a32b16
- + a48b00
- = a00b00
- + a00b16 + a16b00
- + a00b32 + a16b16 + a32b00
- + a00b48 + a16b32 + a32b16 + a48b00
- */
- var a00 = this._a00
- var a16 = this._a16
- var a32 = this._a32
- var a48 = this._a48
- var b00 = other._a00
- var b16 = other._a16
- var b32 = other._a32
- var b48 = other._a48
- var c00 = a00 * b00
- var c16 = c00 >>> 16
- c16 += a00 * b16
- var c32 = c16 >>> 16
- c16 &= 0xFFFF
- c16 += a16 * b00
- c32 += c16 >>> 16
- c32 += a00 * b32
- var c48 = c32 >>> 16
- c32 &= 0xFFFF
- c32 += a16 * b16
- c48 += c32 >>> 16
- c32 &= 0xFFFF
- c32 += a32 * b00
- c48 += c32 >>> 16
- c48 += a00 * b48
- c48 &= 0xFFFF
- c48 += a16 * b32
- c48 &= 0xFFFF
- c48 += a32 * b16
- c48 &= 0xFFFF
- c48 += a48 * b00
- this._a00 = c00 & 0xFFFF
- this._a16 = c16 & 0xFFFF
- this._a32 = c32 & 0xFFFF
- this._a48 = c48 & 0xFFFF
- return this
- }
- /**
- * Divide two _UINT64_. The current _UINT64_ stores the result.
- * The remainder is made available as the _remainder_ property on
- * the _UINT64_ object. It can be null, meaning there are no remainder.
- * @method div
- * @param {Object} other UINT64
- * @return ThisExpression
- */
- UINT64.prototype.div = function (other) {
- if ( (other._a16 == 0) && (other._a32 == 0) && (other._a48 == 0) ) {
- if (other._a00 == 0) throw Error('division by zero')
- // other == 1: this
- if (other._a00 == 1) {
- this.remainder = new UINT64(0)
- return this
- }
- }
- // other > this: 0
- if ( other.gt(this) ) {
- this.remainder = this.clone()
- this._a00 = 0
- this._a16 = 0
- this._a32 = 0
- this._a48 = 0
- return this
- }
- // other == this: 1
- if ( this.eq(other) ) {
- this.remainder = new UINT64(0)
- this._a00 = 1
- this._a16 = 0
- this._a32 = 0
- this._a48 = 0
- return this
- }
- // Shift the divisor left until it is higher than the dividend
- var _other = other.clone()
- var i = -1
- while ( !this.lt(_other) ) {
- // High bit can overflow the default 16bits
- // Its ok since we right shift after this loop
- // The overflown bit must be kept though
- _other.shiftLeft(1, true)
- i++
- }
- // Set the remainder
- this.remainder = this.clone()
- // Initialize the current result to 0
- this._a00 = 0
- this._a16 = 0
- this._a32 = 0
- this._a48 = 0
- for (; i >= 0; i--) {
- _other.shiftRight(1)
- // If shifted divisor is smaller than the dividend
- // then subtract it from the dividend
- if ( !this.remainder.lt(_other) ) {
- this.remainder.subtract(_other)
- // Update the current result
- if (i >= 48) {
- this._a48 |= 1 << (i - 48)
- } else if (i >= 32) {
- this._a32 |= 1 << (i - 32)
- } else if (i >= 16) {
- this._a16 |= 1 << (i - 16)
- } else {
- this._a00 |= 1 << i
- }
- }
- }
- return this
- }
- /**
- * Negate the current _UINT64_
- * @method negate
- * @return ThisExpression
- */
- UINT64.prototype.negate = function () {
- var v = ( ~this._a00 & 0xFFFF ) + 1
- this._a00 = v & 0xFFFF
- v = (~this._a16 & 0xFFFF) + (v >>> 16)
- this._a16 = v & 0xFFFF
- v = (~this._a32 & 0xFFFF) + (v >>> 16)
- this._a32 = v & 0xFFFF
- this._a48 = (~this._a48 + (v >>> 16)) & 0xFFFF
- return this
- }
- /**
- * @method eq
- * @param {Object} other UINT64
- * @return {Boolean}
- */
- UINT64.prototype.equals = UINT64.prototype.eq = function (other) {
- return (this._a48 == other._a48) && (this._a00 == other._a00)
- && (this._a32 == other._a32) && (this._a16 == other._a16)
- }
- /**
- * Greater than (strict)
- * @method gt
- * @param {Object} other UINT64
- * @return {Boolean}
- */
- UINT64.prototype.greaterThan = UINT64.prototype.gt = function (other) {
- if (this._a48 > other._a48) return true
- if (this._a48 < other._a48) return false
- if (this._a32 > other._a32) return true
- if (this._a32 < other._a32) return false
- if (this._a16 > other._a16) return true
- if (this._a16 < other._a16) return false
- return this._a00 > other._a00
- }
- /**
- * Less than (strict)
- * @method lt
- * @param {Object} other UINT64
- * @return {Boolean}
- */
- UINT64.prototype.lessThan = UINT64.prototype.lt = function (other) {
- if (this._a48 < other._a48) return true
- if (this._a48 > other._a48) return false
- if (this._a32 < other._a32) return true
- if (this._a32 > other._a32) return false
- if (this._a16 < other._a16) return true
- if (this._a16 > other._a16) return false
- return this._a00 < other._a00
- }
- /**
- * Bitwise OR
- * @method or
- * @param {Object} other UINT64
- * @return ThisExpression
- */
- UINT64.prototype.or = function (other) {
- this._a00 |= other._a00
- this._a16 |= other._a16
- this._a32 |= other._a32
- this._a48 |= other._a48
- return this
- }
- /**
- * Bitwise AND
- * @method and
- * @param {Object} other UINT64
- * @return ThisExpression
- */
- UINT64.prototype.and = function (other) {
- this._a00 &= other._a00
- this._a16 &= other._a16
- this._a32 &= other._a32
- this._a48 &= other._a48
- return this
- }
- /**
- * Bitwise XOR
- * @method xor
- * @param {Object} other UINT64
- * @return ThisExpression
- */
- UINT64.prototype.xor = function (other) {
- this._a00 ^= other._a00
- this._a16 ^= other._a16
- this._a32 ^= other._a32
- this._a48 ^= other._a48
- return this
- }
- /**
- * Bitwise NOT
- * @method not
- * @return ThisExpression
- */
- UINT64.prototype.not = function() {
- this._a00 = ~this._a00 & 0xFFFF
- this._a16 = ~this._a16 & 0xFFFF
- this._a32 = ~this._a32 & 0xFFFF
- this._a48 = ~this._a48 & 0xFFFF
- return this
- }
- /**
- * Bitwise shift right
- * @method shiftRight
- * @param {Number} number of bits to shift
- * @return ThisExpression
- */
- UINT64.prototype.shiftRight = UINT64.prototype.shiftr = function (n) {
- n %= 64
- if (n >= 48) {
- this._a00 = this._a48 >> (n - 48)
- this._a16 = 0
- this._a32 = 0
- this._a48 = 0
- } else if (n >= 32) {
- n -= 32
- this._a00 = ( (this._a32 >> n) | (this._a48 << (16-n)) ) & 0xFFFF
- this._a16 = (this._a48 >> n) & 0xFFFF
- this._a32 = 0
- this._a48 = 0
- } else if (n >= 16) {
- n -= 16
- this._a00 = ( (this._a16 >> n) | (this._a32 << (16-n)) ) & 0xFFFF
- this._a16 = ( (this._a32 >> n) | (this._a48 << (16-n)) ) & 0xFFFF
- this._a32 = (this._a48 >> n) & 0xFFFF
- this._a48 = 0
- } else {
- this._a00 = ( (this._a00 >> n) | (this._a16 << (16-n)) ) & 0xFFFF
- this._a16 = ( (this._a16 >> n) | (this._a32 << (16-n)) ) & 0xFFFF
- this._a32 = ( (this._a32 >> n) | (this._a48 << (16-n)) ) & 0xFFFF
- this._a48 = (this._a48 >> n) & 0xFFFF
- }
- return this
- }
- /**
- * Bitwise shift left
- * @method shiftLeft
- * @param {Number} number of bits to shift
- * @param {Boolean} allow overflow
- * @return ThisExpression
- */
- UINT64.prototype.shiftLeft = UINT64.prototype.shiftl = function (n, allowOverflow) {
- n %= 64
- if (n >= 48) {
- this._a48 = this._a00 << (n - 48)
- this._a32 = 0
- this._a16 = 0
- this._a00 = 0
- } else if (n >= 32) {
- n -= 32
- this._a48 = (this._a16 << n) | (this._a00 >> (16-n))
- this._a32 = (this._a00 << n) & 0xFFFF
- this._a16 = 0
- this._a00 = 0
- } else if (n >= 16) {
- n -= 16
- this._a48 = (this._a32 << n) | (this._a16 >> (16-n))
- this._a32 = ( (this._a16 << n) | (this._a00 >> (16-n)) ) & 0xFFFF
- this._a16 = (this._a00 << n) & 0xFFFF
- this._a00 = 0
- } else {
- this._a48 = (this._a48 << n) | (this._a32 >> (16-n))
- this._a32 = ( (this._a32 << n) | (this._a16 >> (16-n)) ) & 0xFFFF
- this._a16 = ( (this._a16 << n) | (this._a00 >> (16-n)) ) & 0xFFFF
- this._a00 = (this._a00 << n) & 0xFFFF
- }
- if (!allowOverflow) {
- this._a48 &= 0xFFFF
- }
- return this
- }
- /**
- * Bitwise rotate left
- * @method rotl
- * @param {Number} number of bits to rotate
- * @return ThisExpression
- */
- UINT64.prototype.rotateLeft = UINT64.prototype.rotl = function (n) {
- n %= 64
- if (n == 0) return this
- if (n >= 32) {
- // A.B.C.D
- // B.C.D.A rotl(16)
- // C.D.A.B rotl(32)
- var v = this._a00
- this._a00 = this._a32
- this._a32 = v
- v = this._a48
- this._a48 = this._a16
- this._a16 = v
- if (n == 32) return this
- n -= 32
- }
- var high = (this._a48 << 16) | this._a32
- var low = (this._a16 << 16) | this._a00
- var _high = (high << n) | (low >>> (32 - n))
- var _low = (low << n) | (high >>> (32 - n))
- this._a00 = _low & 0xFFFF
- this._a16 = _low >>> 16
- this._a32 = _high & 0xFFFF
- this._a48 = _high >>> 16
- return this
- }
- /**
- * Bitwise rotate right
- * @method rotr
- * @param {Number} number of bits to rotate
- * @return ThisExpression
- */
- UINT64.prototype.rotateRight = UINT64.prototype.rotr = function (n) {
- n %= 64
- if (n == 0) return this
- if (n >= 32) {
- // A.B.C.D
- // D.A.B.C rotr(16)
- // C.D.A.B rotr(32)
- var v = this._a00
- this._a00 = this._a32
- this._a32 = v
- v = this._a48
- this._a48 = this._a16
- this._a16 = v
- if (n == 32) return this
- n -= 32
- }
- var high = (this._a48 << 16) | this._a32
- var low = (this._a16 << 16) | this._a00
- var _high = (high >>> n) | (low << (32 - n))
- var _low = (low >>> n) | (high << (32 - n))
- this._a00 = _low & 0xFFFF
- this._a16 = _low >>> 16
- this._a32 = _high & 0xFFFF
- this._a48 = _high >>> 16
- return this
- }
- /**
- * Clone the current _UINT64_
- * @method clone
- * @return {Object} cloned UINT64
- */
- UINT64.prototype.clone = function () {
- return new UINT64(this._a00, this._a16, this._a32, this._a48)
- }
- if (typeof define != 'undefined' && define.amd) {
- // AMD / RequireJS
- define([], function () {
- return UINT64
- })
- } else if (typeof module != 'undefined' && module.exports) {
- // Node.js
- module.exports = UINT64
- } else {
- // Browser
- root['UINT64'] = UINT64
- }
- })(this)
|