123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- /**
- C-like unsigned 32 bits integers in Javascript
- Copyright (C) 2013, Pierre Curto
- MIT license
- */
- ;(function (root) {
- // Local cache for typical radices
- var radixPowerCache = {
- 36: UINT32( Math.pow(36, 5) )
- , 16: UINT32( Math.pow(16, 7) )
- , 10: UINT32( Math.pow(10, 9) )
- , 2: UINT32( Math.pow(2, 30) )
- }
- var radixCache = {
- 36: UINT32(36)
- , 16: UINT32(16)
- , 10: UINT32(10)
- , 2: UINT32(2)
- }
- /**
- * Represents an unsigned 32 bits integer
- * @constructor
- * @param {Number|String|Number} low bits | integer as a string | integer as a number
- * @param {Number|Number|Undefined} high bits | radix (optional, default=10)
- * @return
- */
- function UINT32 (l, h) {
- if ( !(this instanceof UINT32) )
- return new UINT32(l, h)
- this._low = 0
- this._high = 0
- this.remainder = null
- if (typeof h == 'undefined')
- return fromNumber.call(this, l)
- if (typeof l == 'string')
- return fromString.call(this, l, h)
- fromBits.call(this, l, h)
- }
- /**
- * Set the current _UINT32_ object with its low and high bits
- * @method fromBits
- * @param {Number} low bits
- * @param {Number} high bits
- * @return ThisExpression
- */
- function fromBits (l, h) {
- this._low = l | 0
- this._high = h | 0
- return this
- }
- UINT32.prototype.fromBits = fromBits
- /**
- * Set the current _UINT32_ object from a number
- * @method fromNumber
- * @param {Number} number
- * @return ThisExpression
- */
- function fromNumber (value) {
- this._low = value & 0xFFFF
- this._high = value >>> 16
- return this
- }
- UINT32.prototype.fromNumber = fromNumber
- /**
- * Set the current _UINT32_ object from a string
- * @method fromString
- * @param {String} integer as a string
- * @param {Number} radix (optional, default=10)
- * @return ThisExpression
- */
- function fromString (s, radix) {
- var value = parseInt(s, radix || 10)
- this._low = value & 0xFFFF
- this._high = value >>> 16
- return this
- }
- UINT32.prototype.fromString = fromString
- /**
- * Convert this _UINT32_ to a number
- * @method toNumber
- * @return {Number} the converted UINT32
- */
- UINT32.prototype.toNumber = function () {
- return (this._high * 65536) + this._low
- }
- /**
- * Convert this _UINT32_ to a string
- * @method toString
- * @param {Number} radix (optional, default=10)
- * @return {String} the converted UINT32
- */
- UINT32.prototype.toString = function (radix) {
- return this.toNumber().toString(radix || 10)
- }
- /**
- * Add two _UINT32_. The current _UINT32_ stores the result
- * @method add
- * @param {Object} other UINT32
- * @return ThisExpression
- */
- UINT32.prototype.add = function (other) {
- var a00 = this._low + other._low
- var a16 = a00 >>> 16
- a16 += this._high + other._high
- this._low = a00 & 0xFFFF
- this._high = a16 & 0xFFFF
- return this
- }
- /**
- * Subtract two _UINT32_. The current _UINT32_ stores the result
- * @method subtract
- * @param {Object} other UINT32
- * @return ThisExpression
- */
- UINT32.prototype.subtract = function (other) {
- //TODO inline
- return this.add( other.clone().negate() )
- }
- /**
- * Multiply two _UINT32_. The current _UINT32_ stores the result
- * @method multiply
- * @param {Object} other UINT32
- * @return ThisExpression
- */
- UINT32.prototype.multiply = function (other) {
- /*
- a = a00 + a16
- b = b00 + b16
- a*b = (a00 + a16)(b00 + b16)
- = a00b00 + a00b16 + a16b00 + a16b16
- a16b16 overflows the 32bits
- */
- var a16 = this._high
- var a00 = this._low
- var b16 = other._high
- var b00 = other._low
- /* Removed to increase speed under normal circumstances (i.e. not multiplying by 0 or 1)
- // this == 0 or other == 1: nothing to do
- if ((a00 == 0 && a16 == 0) || (b00 == 1 && b16 == 0)) return this
- // other == 0 or this == 1: this = other
- if ((b00 == 0 && b16 == 0) || (a00 == 1 && a16 == 0)) {
- this._low = other._low
- this._high = other._high
- return this
- }
- */
- var c16, c00
- c00 = a00 * b00
- c16 = c00 >>> 16
- c16 += a16 * b00
- c16 &= 0xFFFF // Not required but improves performance
- c16 += a00 * b16
- this._low = c00 & 0xFFFF
- this._high = c16 & 0xFFFF
- return this
- }
- /**
- * Divide two _UINT32_. The current _UINT32_ stores the result.
- * The remainder is made available as the _remainder_ property on
- * the _UINT32_ object. It can be null, meaning there are no remainder.
- * @method div
- * @param {Object} other UINT32
- * @return ThisExpression
- */
- UINT32.prototype.div = function (other) {
- if ( (other._low == 0) && (other._high == 0) ) throw Error('division by zero')
- // other == 1
- if (other._high == 0 && other._low == 1) {
- this.remainder = new UINT32(0)
- return this
- }
- // other > this: 0
- if ( other.gt(this) ) {
- this.remainder = this.clone()
- this._low = 0
- this._high = 0
- return this
- }
- // other == this: 1
- if ( this.eq(other) ) {
- this.remainder = new UINT32(0)
- this._low = 1
- this._high = 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._low = 0
- this._high = 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 >= 16) {
- this._high |= 1 << (i - 16)
- } else {
- this._low |= 1 << i
- }
- }
- }
- return this
- }
- /**
- * Negate the current _UINT32_
- * @method negate
- * @return ThisExpression
- */
- UINT32.prototype.negate = function () {
- var v = ( ~this._low & 0xFFFF ) + 1
- this._low = v & 0xFFFF
- this._high = (~this._high + (v >>> 16)) & 0xFFFF
- return this
- }
- /**
- * Equals
- * @method eq
- * @param {Object} other UINT32
- * @return {Boolean}
- */
- UINT32.prototype.equals = UINT32.prototype.eq = function (other) {
- return (this._low == other._low) && (this._high == other._high)
- }
- /**
- * Greater than (strict)
- * @method gt
- * @param {Object} other UINT32
- * @return {Boolean}
- */
- UINT32.prototype.greaterThan = UINT32.prototype.gt = function (other) {
- if (this._high > other._high) return true
- if (this._high < other._high) return false
- return this._low > other._low
- }
- /**
- * Less than (strict)
- * @method lt
- * @param {Object} other UINT32
- * @return {Boolean}
- */
- UINT32.prototype.lessThan = UINT32.prototype.lt = function (other) {
- if (this._high < other._high) return true
- if (this._high > other._high) return false
- return this._low < other._low
- }
- /**
- * Bitwise OR
- * @method or
- * @param {Object} other UINT32
- * @return ThisExpression
- */
- UINT32.prototype.or = function (other) {
- this._low |= other._low
- this._high |= other._high
- return this
- }
- /**
- * Bitwise AND
- * @method and
- * @param {Object} other UINT32
- * @return ThisExpression
- */
- UINT32.prototype.and = function (other) {
- this._low &= other._low
- this._high &= other._high
- return this
- }
- /**
- * Bitwise NOT
- * @method not
- * @return ThisExpression
- */
- UINT32.prototype.not = function() {
- this._low = ~this._low & 0xFFFF
- this._high = ~this._high & 0xFFFF
- return this
- }
- /**
- * Bitwise XOR
- * @method xor
- * @param {Object} other UINT32
- * @return ThisExpression
- */
- UINT32.prototype.xor = function (other) {
- this._low ^= other._low
- this._high ^= other._high
- return this
- }
- /**
- * Bitwise shift right
- * @method shiftRight
- * @param {Number} number of bits to shift
- * @return ThisExpression
- */
- UINT32.prototype.shiftRight = UINT32.prototype.shiftr = function (n) {
- if (n > 16) {
- this._low = this._high >> (n - 16)
- this._high = 0
- } else if (n == 16) {
- this._low = this._high
- this._high = 0
- } else {
- this._low = (this._low >> n) | ( (this._high << (16-n)) & 0xFFFF )
- this._high >>= n
- }
- return this
- }
- /**
- * Bitwise shift left
- * @method shiftLeft
- * @param {Number} number of bits to shift
- * @param {Boolean} allow overflow
- * @return ThisExpression
- */
- UINT32.prototype.shiftLeft = UINT32.prototype.shiftl = function (n, allowOverflow) {
- if (n > 16) {
- this._high = this._low << (n - 16)
- this._low = 0
- if (!allowOverflow) {
- this._high &= 0xFFFF
- }
- } else if (n == 16) {
- this._high = this._low
- this._low = 0
- } else {
- this._high = (this._high << n) | (this._low >> (16-n))
- this._low = (this._low << n) & 0xFFFF
- if (!allowOverflow) {
- // Overflow only allowed on the high bits...
- this._high &= 0xFFFF
- }
- }
- return this
- }
- /**
- * Bitwise rotate left
- * @method rotl
- * @param {Number} number of bits to rotate
- * @return ThisExpression
- */
- UINT32.prototype.rotateLeft = UINT32.prototype.rotl = function (n) {
- var v = (this._high << 16) | this._low
- v = (v << n) | (v >>> (32 - n))
- this._low = v & 0xFFFF
- this._high = v >>> 16
- return this
- }
- /**
- * Bitwise rotate right
- * @method rotr
- * @param {Number} number of bits to rotate
- * @return ThisExpression
- */
- UINT32.prototype.rotateRight = UINT32.prototype.rotr = function (n) {
- var v = (this._high << 16) | this._low
- v = (v >>> n) | (v << (32 - n))
- this._low = v & 0xFFFF
- this._high = v >>> 16
- return this
- }
- /**
- * Clone the current _UINT32_
- * @method clone
- * @return {Object} cloned UINT32
- */
- UINT32.prototype.clone = function () {
- return new UINT32(this._low, this._high)
- }
- if (typeof define != 'undefined' && define.amd) {
- // AMD / RequireJS
- define([], function () {
- return UINT32
- })
- } else if (typeof module != 'undefined' && module.exports) {
- // Node.js
- module.exports = UINT32
- } else {
- // Browser
- root['UINT32'] = UINT32
- }
- })(this)
|