/** 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)