fable-compiler
Version:
Fable compiler
1,318 lines • 42 kB
JavaScript
// Adapted from: https://github.com/dcodeIO/long.js/blob/master/src/long.js
// Apache License 2.0: https://github.com/dcodeIO/long.js/blob/master/LICENSE
export default Long;
/**
* wasm optimizations, to do native i64 multiplication and divide
*/
var wasm = null;
try {
wasm = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([
0, 97, 115, 109, 1, 0, 0, 0, 1, 13, 2, 96, 0, 1, 127, 96, 4, 127, 127, 127, 127, 1, 127, 3, 7, 6, 0, 1, 1, 1, 1, 1, 6, 6, 1, 127, 1, 65, 0, 11, 7, 50, 6, 3, 109, 117, 108, 0, 1, 5, 100, 105, 118, 95, 115, 0, 2, 5, 100, 105, 118, 95, 117, 0, 3, 5, 114, 101, 109, 95, 115, 0, 4, 5, 114, 101, 109, 95, 117, 0, 5, 8, 103, 101, 116, 95, 104, 105, 103, 104, 0, 0, 10, 191, 1, 6, 4, 0, 35, 0, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 126, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 127, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 128, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 129, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 130, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11
])), {}).exports;
}
catch (e) {
// no wasm support :(
}
/**
* Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
* See the from* functions below for more convenient ways of constructing Longs.
* @exports Long
* @class A Long class for representing a 64 bit two's-complement integer value.
* @param {number} low The low (signed) 32 bits of the long
* @param {number} high The high (signed) 32 bits of the long
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @constructor
*/
export function Long(low, high, unsigned) {
/**
* The low 32 bits as a signed value.
* @type {number}
*/
this.low = low | 0;
/**
* The high 32 bits as a signed value.
* @type {number}
*/
this.high = high | 0;
/**
* Whether unsigned or not.
* @type {boolean}
*/
this.unsigned = !!unsigned;
}
Long.prototype.GetHashCode = function () {
let h1 = this.unsigned ? 1 : 0;
h1 = ((h1 << 5) + h1) ^ this.high;
h1 = ((h1 << 5) + h1) ^ this.low;
return h1;
};
Long.prototype.Equals = function (x) { return equals(this, x); };
Long.prototype.CompareTo = function (x) { return compare(this, x); };
Long.prototype.toString = function (radix) { return toString(this, radix); };
Long.prototype.toJSON = function () { return toString(this); };
// The internal representation of a long is the two given signed, 32-bit values.
// We use 32-bit pieces because these are the size of integers on which
// Javascript performs bit-operations. For operations like addition and
// multiplication, we split each number into 16 bit pieces, which can easily be
// multiplied within Javascript's floating-point representation without overflow
// or change in sign.
//
// In the algorithms below, we frequently reduce the negative case to the
// positive case by negating the input(s) and then post-processing the result.
// Note that we must ALWAYS check specially whether those values are MIN_VALUE
// (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
// a positive number, it overflows back into a negative). Not handling this
// case would often result in infinite recursion.
//
// Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
// methods on which they depend.
/**
* An indicator used to reliably determine if an object is a Long or not.
* @type {boolean}
* @const
* @private
*/
Long.prototype.__isLong__;
Object.defineProperty(Long.prototype, "__isLong__", { value: true });
/**
* @function
* @param {*} obj Object
* @returns {boolean}
* @inner
*/
export function isLong(obj) {
return (obj && obj["__isLong__"]) === true;
}
/**
* Tests if the specified object is a Long.
* @function
* @param {*} obj Object
* @returns {boolean}
*/
// Long.isLong = isLong;
/**
* A cache of the Long representations of small integer values.
* @type {!Object}
* @inner
*/
var INT_CACHE = {};
/**
* A cache of the Long representations of small unsigned integer values.
* @type {!Object}
* @inner
*/
var UINT_CACHE = {};
/**
* @param {number} value
* @param {boolean=} unsigned
* @returns {!Long}
* @inner
*/
export function fromInt(value, unsigned) {
var obj, cachedObj, cache;
if (unsigned) {
value >>>= 0;
if (cache = (0 <= value && value < 256)) {
cachedObj = UINT_CACHE[value];
if (cachedObj)
return cachedObj;
}
obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
if (cache)
UINT_CACHE[value] = obj;
return obj;
}
else {
value |= 0;
if (cache = (-128 <= value && value < 128)) {
cachedObj = INT_CACHE[value];
if (cachedObj)
return cachedObj;
}
obj = fromBits(value, value < 0 ? -1 : 0, false);
if (cache)
INT_CACHE[value] = obj;
return obj;
}
}
/**
* Returns a Long representing the given 32 bit integer value.
* @function
* @param {number} value The 32 bit integer in question
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @returns {!Long} The corresponding Long value
*/
// Long.fromInt = fromInt;
/**
* @param {number} value
* @param {boolean=} unsigned
* @returns {!Long}
* @inner
*/
export function fromNumber(value, unsigned) {
if (isNaN(value))
return unsigned ? UZERO : ZERO;
if (unsigned) {
if (value < 0)
return UZERO;
if (value >= TWO_PWR_64_DBL)
return MAX_UNSIGNED_VALUE;
}
else {
if (value <= -TWO_PWR_63_DBL)
return MIN_VALUE;
if (value + 1 >= TWO_PWR_63_DBL)
return MAX_VALUE;
}
if (value < 0)
return negate(fromNumber(-value, unsigned));
return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
}
/**
* Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
* @function
* @param {number} value The number in question
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @returns {!Long} The corresponding Long value
*/
// Long.fromNumber = fromNumber;
/**
* @param {number} lowBits
* @param {number} highBits
* @param {boolean=} unsigned
* @returns {!Long}
* @inner
*/
export function fromBits(lowBits, highBits, unsigned) {
return new Long(lowBits, highBits, unsigned);
}
/**
* Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
* assumed to use 32 bits.
* @function
* @param {number} lowBits The low 32 bits
* @param {number} highBits The high 32 bits
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @returns {!Long} The corresponding Long value
*/
// Long.fromBits = fromBits;
/**
* @function
* @param {number} base
* @param {number} exponent
* @returns {number}
* @inner
*/
var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4)
/**
* @param {string} str
* @param {(boolean|number)=} unsigned
* @param {number=} radix
* @returns {!Long}
* @inner
*/
export function fromString(str, unsigned, radix) {
if (str.length === 0)
throw Error('empty string');
if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
return ZERO;
if (typeof unsigned === 'number') {
// For goog.math.long compatibility
radix = unsigned,
unsigned = false;
}
else {
unsigned = !!unsigned;
}
radix = radix || 10;
if (radix < 2 || 36 < radix)
throw RangeError('radix');
var p = str.indexOf('-');
if (p > 0)
throw Error('interior hyphen');
else if (p === 0) {
return negate(fromString(str.substring(1), unsigned, radix));
}
// Do several (8) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = fromNumber(pow_dbl(radix, 8));
var result = ZERO;
for (var i = 0; i < str.length; i += 8) {
var size = Math.min(8, str.length - i), value = parseInt(str.substring(i, i + size), radix);
if (size < 8) {
var power = fromNumber(pow_dbl(radix, size));
result = add(multiply(result, power), fromNumber(value));
}
else {
result = multiply(result, radixToPower);
result = add(result, fromNumber(value));
}
}
result.unsigned = unsigned;
return result;
}
/**
* Returns a Long representation of the given string, written using the specified radix.
* @function
* @param {string} str The textual representation of the Long
* @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to signed
* @param {number=} radix The radix in which the text is written (2-36), defaults to 10
* @returns {!Long} The corresponding Long value
*/
// Long.fromString = fromString;
/**
* @function
* @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val
* @param {boolean=} unsigned
* @returns {!Long}
* @inner
*/
export function fromValue(val, unsigned) {
if (typeof val === 'number')
return fromNumber(val, unsigned);
if (typeof val === 'string')
return fromString(val, unsigned);
// Throws for non-objects, converts non-instanceof Long:
return fromBits(val.low, val.high, typeof unsigned === 'boolean' ? unsigned : val.unsigned);
}
/**
* Converts the specified value to a Long using the appropriate from* function for its type.
* @function
* @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @returns {!Long}
*/
// Long.fromValue = fromValue;
// NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
// no runtime penalty for these.
/**
* @type {number}
* @const
* @inner
*/
var TWO_PWR_16_DBL = 1 << 16;
/**
* @type {number}
* @const
* @inner
*/
var TWO_PWR_24_DBL = 1 << 24;
/**
* @type {number}
* @const
* @inner
*/
var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
/**
* @type {number}
* @const
* @inner
*/
var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
/**
* @type {number}
* @const
* @inner
*/
var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
/**
* @type {!Long}
* @const
* @inner
*/
var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL);
/**
* @type {!Long}
* @inner
*/
export var ZERO = fromInt(0);
/**
* Signed zero.
* @type {!Long}
*/
// Long.ZERO = ZERO;
/**
* @type {!Long}
* @inner
*/
export var UZERO = fromInt(0, true);
/**
* Unsigned zero.
* @type {!Long}
*/
// Long.UZERO = UZERO;
/**
* @type {!Long}
* @inner
*/
export var ONE = fromInt(1);
/**
* Signed one.
* @type {!Long}
*/
// Long.ONE = ONE;
/**
* @type {!Long}
* @inner
*/
export var UONE = fromInt(1, true);
/**
* Unsigned one.
* @type {!Long}
*/
// Long.UONE = UONE;
/**
* @type {!Long}
* @inner
*/
export var NEG_ONE = fromInt(-1);
/**
* Signed negative one.
* @type {!Long}
*/
// Long.NEG_ONE = NEG_ONE;
/**
* @type {!Long}
* @inner
*/
export var MAX_VALUE = fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0, false);
/**
* Maximum signed value.
* @type {!Long}
*/
// Long.MAX_VALUE = MAX_VALUE;
/**
* @type {!Long}
* @inner
*/
export var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF | 0, 0xFFFFFFFF | 0, true);
/**
* Maximum unsigned value.
* @type {!Long}
*/
// Long.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE;
/**
* @type {!Long}
* @inner
*/
export var MIN_VALUE = fromBits(0, 0x80000000 | 0, false);
/**
* Minimum signed value.
* @type {!Long}
*/
// Long.MIN_VALUE = MIN_VALUE;
/**
* @alias Long.prototype
* @inner
*/
// var LongPrototype = Long.prototype;
/**
* Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
* @this {!Long}
* @returns {number}
*/
export function toInt($this) {
return $this.unsigned ? $this.low >>> 0 : $this.low;
}
;
/**
* Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
* @this {!Long}
* @returns {number}
*/
export function toNumber($this) {
if ($this.unsigned)
return (($this.high >>> 0) * TWO_PWR_32_DBL) + ($this.low >>> 0);
return $this.high * TWO_PWR_32_DBL + ($this.low >>> 0);
}
;
/**
* Converts the Long to a string written in the specified radix.
* @this {!Long}
* @param {number=} radix Radix (2-36), defaults to 10
* @returns {string}
* @override
* @throws {RangeError} If `radix` is out of range
*/
export function toString($this, radix) {
radix = radix || 10;
if (radix < 2 || 36 < radix)
throw RangeError('radix');
if (isZero($this))
return '0';
if (isNegative($this)) { // Unsigned Longs are never negative
if (equals($this, MIN_VALUE)) {
// We need to change the Long value before it can be negated, so we remove
// the bottom-most digit in this base and then recurse to do the rest.
var radixLong = fromNumber(radix), div = divide($this, radixLong), rem1 = subtract(multiply(div, radixLong), $this);
return toString(div, radix) + toInt(rem1).toString(radix);
}
else
return '-' + toString(negate($this), radix);
}
// Do several (6) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = fromNumber(pow_dbl(radix, 6), $this.unsigned), rem = $this;
var result = '';
while (true) {
var remDiv = divide(rem, radixToPower), intval = toInt(subtract(rem, multiply(remDiv, radixToPower))) >>> 0, digits = intval.toString(radix);
rem = remDiv;
if (isZero(rem))
return digits + result;
else {
while (digits.length < 6)
digits = '0' + digits;
result = '' + digits + result;
}
}
}
;
/**
* Gets the high 32 bits as a signed integer.
* @this {!Long}
* @returns {number} Signed high bits
*/
export function getHighBits($this) {
return $this.high;
}
;
/**
* Gets the high 32 bits as an unsigned integer.
* @this {!Long}
* @returns {number} Unsigned high bits
*/
export function getHighBitsUnsigned($this) {
return $this.high >>> 0;
}
;
/**
* Gets the low 32 bits as a signed integer.
* @this {!Long}
* @returns {number} Signed low bits
*/
export function getLowBits($this) {
return $this.low;
}
;
/**
* Gets the low 32 bits as an unsigned integer.
* @this {!Long}
* @returns {number} Unsigned low bits
*/
export function getLowBitsUnsigned($this) {
return $this.low >>> 0;
}
;
/**
* Gets the number of bits needed to represent the absolute value of this Long.
* @this {!Long}
* @returns {number}
*/
export function getNumBitsAbs($this) {
if (isNegative($this)) // Unsigned Longs are never negative
return equals($this, MIN_VALUE) ? 64 : getNumBitsAbs(negate($this));
var val = $this.high != 0 ? $this.high : $this.low;
for (var bit = 31; bit > 0; bit--)
if ((val & (1 << bit)) != 0)
break;
return $this.high != 0 ? bit + 33 : bit + 1;
}
;
/**
* Tests if this Long's value equals zero.
* @this {!Long}
* @returns {boolean}
*/
export function isZero($this) {
return $this.high === 0 && $this.low === 0;
}
;
/**
* Tests if this Long's value equals zero. This is an alias of {@link Long#isZero}.
* @returns {boolean}
*/
// LongPrototype.eqz = LongPrototype.isZero;
/**
* Tests if this Long's value is negative.
* @this {!Long}
* @returns {boolean}
*/
export function isNegative($this) {
return !$this.unsigned && $this.high < 0;
}
;
/**
* Tests if this Long's value is positive.
* @this {!Long}
* @returns {boolean}
*/
export function isPositive($this) {
return $this.unsigned || $this.high >= 0;
}
;
/**
* Tests if this Long's value is odd.
* @this {!Long}
* @returns {boolean}
*/
export function isOdd($this) {
return ($this.low & 1) === 1;
}
;
/**
* Tests if this Long's value is even.
* @this {!Long}
* @returns {boolean}
*/
export function isEven($this) {
return ($this.low & 1) === 0;
}
;
/**
* Tests if this Long's value equals the specified's.
* @this {!Long}
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
export function equals($this, other) {
if (!isLong(other))
other = fromValue(other);
if ($this.unsigned !== other.unsigned && ($this.high >>> 31) === 1 && (other.high >>> 31) === 1)
return false;
return $this.high === other.high && $this.low === other.low;
}
;
/**
* Tests if this Long's value equals the specified's. This is an alias of {@link Long#equals}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.eq = LongPrototype.equals;
/**
* Tests if this Long's value differs from the specified's.
* @this {!Long}
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
export function notEquals($this, other) {
return !equals($this, /* validates */ other);
}
;
/**
* Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.neq = LongPrototype.notEquals;
/**
* Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.ne = LongPrototype.notEquals;
/**
* Tests if this Long's value is less than the specified's.
* @this {!Long}
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
export function lessThan($this, other) {
return compare($this, /* validates */ other) < 0;
}
;
/**
* Tests if this Long's value is less than the specified's. This is an alias of {@link Long#lessThan}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.lt = LongPrototype.lessThan;
/**
* Tests if this Long's value is less than or equal the specified's.
* @this {!Long}
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
export function lessThanOrEqual($this, other) {
return compare($this, /* validates */ other) <= 0;
}
;
/**
* Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.lte = LongPrototype.lessThanOrEqual;
/**
* Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.le = LongPrototype.lessThanOrEqual;
/**
* Tests if this Long's value is greater than the specified's.
* @this {!Long}
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
export function greaterThan($this, other) {
return compare($this, /* validates */ other) > 0;
}
;
/**
* Tests if this Long's value is greater than the specified's. This is an alias of {@link Long#greaterThan}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.gt = LongPrototype.greaterThan;
/**
* Tests if this Long's value is greater than or equal the specified's.
* @this {!Long}
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
export function greaterThanOrEqual($this, other) {
return compare($this, /* validates */ other) >= 0;
}
;
/**
* Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.gte = LongPrototype.greaterThanOrEqual;
/**
* Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}.
* @function
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
// LongPrototype.ge = LongPrototype.greaterThanOrEqual;
/**
* Compares this Long's value with the specified's.
* @this {!Long}
* @param {!Long|number|string} other Other value
* @returns {number} 0 if they are the same, 1 if the this is greater and -1
* if the given one is greater
*/
export function compare($this, other) {
if (!isLong(other))
other = fromValue(other);
if (equals($this, other))
return 0;
var thisNeg = isNegative($this), otherNeg = isNegative(other);
if (thisNeg && !otherNeg)
return -1;
if (!thisNeg && otherNeg)
return 1;
// At this point the sign bits are the same
if (!$this.unsigned)
return isNegative(subtract($this, other)) ? -1 : 1;
// Both are positive if at least one is unsigned
return (other.high >>> 0) > ($this.high >>> 0) || (other.high === $this.high && (other.low >>> 0) > ($this.low >>> 0)) ? -1 : 1;
}
;
/**
* Compares this Long's value with the specified's. This is an alias of {@link Long#compare}.
* @function
* @param {!Long|number|string} other Other value
* @returns {number} 0 if they are the same, 1 if the this is greater and -1
* if the given one is greater
*/
// LongPrototype.comp = LongPrototype.compare;
/**
* Negates this Long's value.
* @this {!Long}
* @returns {!Long} Negated Long
*/
export function negate($this) {
if (!$this.unsigned && equals($this, MIN_VALUE))
return MIN_VALUE;
return add(not($this), ONE);
}
;
/**
* Negates this Long's value. This is an alias of {@link Long#negate}.
* @function
* @returns {!Long} Negated Long
*/
// LongPrototype.neg = LongPrototype.negate;
/**
* Returns the sum of this and the specified Long.
* @this {!Long}
* @param {!Long|number|string} addend Addend
* @returns {!Long} Sum
*/
export function add($this, addend) {
if (!isLong(addend))
addend = fromValue(addend);
// Divide each number into 4 chunks of 16 bits, and then sum the chunks.
var a48 = $this.high >>> 16;
var a32 = $this.high & 0xFFFF;
var a16 = $this.low >>> 16;
var a00 = $this.low & 0xFFFF;
var b48 = addend.high >>> 16;
var b32 = addend.high & 0xFFFF;
var b16 = addend.low >>> 16;
var b00 = addend.low & 0xFFFF;
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
c00 += a00 + b00;
c16 += c00 >>> 16;
c00 &= 0xFFFF;
c16 += a16 + b16;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c32 += a32 + b32;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c48 += a48 + b48;
c48 &= 0xFFFF;
return fromBits((c16 << 16) | c00, (c48 << 16) | c32, $this.unsigned);
}
;
/**
* Returns the difference of this and the specified Long.
* @this {!Long}
* @param {!Long|number|string} subtrahend Subtrahend
* @returns {!Long} Difference
*/
export function subtract($this, subtrahend) {
if (!isLong(subtrahend))
subtrahend = fromValue(subtrahend);
return add($this, negate(subtrahend));
}
;
/**
* Returns the difference of this and the specified Long. This is an alias of {@link Long#subtract}.
* @function
* @param {!Long|number|string} subtrahend Subtrahend
* @returns {!Long} Difference
*/
// LongPrototype.sub = LongPrototype.subtract;
/**
* Returns the product of this and the specified Long.
* @this {!Long}
* @param {!Long|number|string} multiplier Multiplier
* @returns {!Long} Product
*/
export function multiply($this, multiplier) {
if (isZero($this))
return $this.unsigned ? UZERO : ZERO;
if (!isLong(multiplier))
multiplier = fromValue(multiplier);
// use wasm support if present
if (wasm) {
var low = wasm.mul($this.low, $this.high, multiplier.low, multiplier.high);
return fromBits(low, wasm.get_high(), $this.unsigned);
}
if (isZero(multiplier))
return $this.unsigned ? UZERO : ZERO;
if (equals($this, MIN_VALUE))
return isOdd(multiplier) ? MIN_VALUE : ZERO;
if (equals(multiplier, MIN_VALUE))
return isOdd($this) ? MIN_VALUE : ZERO;
if (isNegative($this)) {
if (isNegative(multiplier))
return multiply(negate($this), negate(multiplier));
else
return negate(multiply(negate($this), multiplier));
}
else if (isNegative(multiplier))
return negate(multiply($this, negate(multiplier)));
// If both longs are small, use float multiplication
if (lessThan($this, TWO_PWR_24) && lessThan(multiplier, TWO_PWR_24))
return fromNumber(toNumber($this) * toNumber(multiplier), $this.unsigned);
// Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
// We can skip products that would overflow.
var a48 = $this.high >>> 16;
var a32 = $this.high & 0xFFFF;
var a16 = $this.low >>> 16;
var a00 = $this.low & 0xFFFF;
var b48 = multiplier.high >>> 16;
var b32 = multiplier.high & 0xFFFF;
var b16 = multiplier.low >>> 16;
var b00 = multiplier.low & 0xFFFF;
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
c00 += a00 * b00;
c16 += c00 >>> 16;
c00 &= 0xFFFF;
c16 += a16 * b00;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c16 += a00 * b16;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c32 += a32 * b00;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c32 += a16 * b16;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c32 += a00 * b32;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
c48 &= 0xFFFF;
return fromBits((c16 << 16) | c00, (c48 << 16) | c32, $this.unsigned);
}
;
/**
* Returns the product of this and the specified Long. This is an alias of {@link Long#multiply}.
* @function
* @param {!Long|number|string} multiplier Multiplier
* @returns {!Long} Product
*/
// LongPrototype.mul = LongPrototype.multiply;
/**
* Returns this Long divided by the specified. The result is signed if this Long is signed or
* unsigned if this Long is unsigned.
* @this {!Long}
* @param {!Long|number|string} divisor Divisor
* @returns {!Long} Quotient
*/
export function divide($this, divisor) {
if (!isLong(divisor))
divisor = fromValue(divisor);
if (isZero(divisor))
throw Error('division by zero');
// use wasm support if present
if (wasm) {
// guard against signed division overflow: the largest
// negative number / -1 would be 1 larger than the largest
// positive number, due to two's complement.
if (!$this.unsigned &&
$this.high === -0x80000000 &&
divisor.low === -1 && divisor.high === -1) {
// be consistent with non-wasm code path
return $this;
}
var low = ($this.unsigned ? wasm.div_u : wasm.div_s)($this.low, $this.high, divisor.low, divisor.high);
return fromBits(low, wasm.get_high(), $this.unsigned);
}
if (isZero($this))
return $this.unsigned ? UZERO : ZERO;
var approx, rem, res;
if (!$this.unsigned) {
// This section is only relevant for signed longs and is derived from the
// closure library as a whole.
if (equals($this, MIN_VALUE)) {
if (equals(divisor, ONE) || equals(divisor, NEG_ONE))
return MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
else if (equals(divisor, MIN_VALUE))
return ONE;
else {
// At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
var halfThis = shiftRight($this, 1);
approx = shiftLeft(divide(halfThis, divisor), 1);
if (equals(approx, ZERO)) {
return isNegative(divisor) ? ONE : NEG_ONE;
}
else {
rem = subtract($this, multiply(divisor, approx));
res = add(approx, divide(rem, divisor));
return res;
}
}
}
else if (equals(divisor, MIN_VALUE))
return $this.unsigned ? UZERO : ZERO;
if (isNegative($this)) {
if (isNegative(divisor))
return divide(negate($this), negate(divisor));
return negate(divide(negate($this), divisor));
}
else if (isNegative(divisor))
return negate(divide($this, negate(divisor)));
res = ZERO;
}
else {
// The algorithm below has not been made for unsigned longs. It's therefore
// required to take special care of the MSB prior to running it.
if (!divisor.unsigned)
divisor = toUnsigned(divisor);
if (greaterThan(divisor, $this))
return UZERO;
if (greaterThan(divisor, shiftRightUnsigned($this, 1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true
return UONE;
res = UZERO;
}
// Repeat the following until the remainder is less than other: find a
// floating-point that approximates remainder / other *from below*, add this
// into the result, and subtract it from the remainder. It is critical that
// the approximate value is less than or equal to the real value so that the
// remainder never becomes negative.
rem = $this;
while (greaterThanOrEqual(rem, divisor)) {
// Approximate the result of division. This may be a little greater or
// smaller than the actual value.
approx = Math.max(1, Math.floor(toNumber(rem) / toNumber(divisor)));
// We will tweak the approximate result by changing it in the 48-th digit or
// the smallest non-fractional digit, whichever is larger.
var log2 = Math.ceil(Math.log(approx) / Math.LN2), delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48),
// Decrease the approximation until it is smaller than the remainder. Note
// that if it is too large, the product overflows and is negative.
approxRes = fromNumber(approx), approxRem = multiply(approxRes, divisor);
while (isNegative(approxRem) || greaterThan(approxRem, rem)) {
approx -= delta;
approxRes = fromNumber(approx, $this.unsigned);
approxRem = multiply(approxRes, divisor);
}
// We know the answer can't be zero... and actually, zero would cause
// infinite recursion since we would make no progress.
if (isZero(approxRes))
approxRes = ONE;
res = add(res, approxRes);
rem = subtract(rem, approxRem);
}
return res;
}
;
/**
* Returns this Long divided by the specified. This is an alias of {@link Long#divide}.
* @function
* @param {!Long|number|string} divisor Divisor
* @returns {!Long} Quotient
*/
// LongPrototype.div = LongPrototype.divide;
/**
* Returns this Long modulo the specified.
* @this {!Long}
* @param {!Long|number|string} divisor Divisor
* @returns {!Long} Remainder
*/
export function modulo($this, divisor) {
if (!isLong(divisor))
divisor = fromValue(divisor);
// use wasm support if present
if (wasm) {
var low = ($this.unsigned ? wasm.rem_u : wasm.rem_s)($this.low, $this.high, divisor.low, divisor.high);
return fromBits(low, wasm.get_high(), $this.unsigned);
}
return subtract($this, multiply(divide($this, divisor), divisor));
}
;
/**
* Returns this Long modulo the specified. This is an alias of {@link Long#modulo}.
* @function
* @param {!Long|number|string} divisor Divisor
* @returns {!Long} Remainder
*/
// LongPrototype.mod = LongPrototype.modulo;
/**
* Returns this Long modulo the specified. This is an alias of {@link Long#modulo}.
* @function
* @param {!Long|number|string} divisor Divisor
* @returns {!Long} Remainder
*/
// LongPrototype.rem = LongPrototype.modulo;
/**
* Returns the bitwise NOT of this Long.
* @this {!Long}
* @returns {!Long}
*/
export function not($this) {
return fromBits(~$this.low, ~$this.high, $this.unsigned);
}
;
/**
* Returns the bitwise AND of this Long and the specified.
* @this {!Long}
* @param {!Long|number|string} other Other Long
* @returns {!Long}
*/
export function and($this, other) {
if (!isLong(other))
other = fromValue(other);
return fromBits($this.low & other.low, $this.high & other.high, $this.unsigned);
}
;
/**
* Returns the bitwise OR of this Long and the specified.
* @this {!Long}
* @param {!Long|number|string} other Other Long
* @returns {!Long}
*/
export function or($this, other) {
if (!isLong(other))
other = fromValue(other);
return fromBits($this.low | other.low, $this.high | other.high, $this.unsigned);
}
;
/**
* Returns the bitwise XOR of this Long and the given one.
* @this {!Long}
* @param {!Long|number|string} other Other Long
* @returns {!Long}
*/
export function xor($this, other) {
if (!isLong(other))
other = fromValue(other);
return fromBits($this.low ^ other.low, $this.high ^ other.high, $this.unsigned);
}
;
/**
* Returns this Long with bits shifted to the left by the given amount.
* @this {!Long}
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
export function shiftLeft($this, numBits) {
if (isLong(numBits))
numBits = toInt(numBits);
if ((numBits &= 63) === 0)
return $this;
else if (numBits < 32)
return fromBits($this.low << numBits, ($this.high << numBits) | ($this.low >>> (32 - numBits)), $this.unsigned);
else
return fromBits(0, $this.low << (numBits - 32), $this.unsigned);
}
;
/**
* Returns this Long with bits shifted to the left by the given amount. This is an alias of {@link Long#shiftLeft}.
* @function
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
// LongPrototype.shl = LongPrototype.shiftLeft;
/**
* Returns this Long with bits arithmetically shifted to the right by the given amount.
* @this {!Long}
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
export function shiftRight($this, numBits) {
if (isLong(numBits))
numBits = toInt(numBits);
if ((numBits &= 63) === 0)
return $this;
else if (numBits < 32)
return fromBits(($this.low >>> numBits) | ($this.high << (32 - numBits)), $this.high >> numBits, $this.unsigned);
else
return fromBits($this.high >> (numBits - 32), $this.high >= 0 ? 0 : -1, $this.unsigned);
}
;
/**
* Returns this Long with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Long#shiftRight}.
* @function
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
// LongPrototype.shr = LongPrototype.shiftRight;
/**
* Returns this Long with bits logically shifted to the right by the given amount.
* @this {!Long}
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
export function shiftRightUnsigned($this, numBits) {
if (isLong(numBits))
numBits = toInt(numBits);
numBits &= 63;
if (numBits === 0)
return $this;
else {
var high = $this.high;
if (numBits < 32) {
var low = $this.low;
return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, $this.unsigned);
}
else if (numBits === 32)
return fromBits(high, 0, $this.unsigned);
else
return fromBits(high >>> (numBits - 32), 0, $this.unsigned);
}
}
;
/**
* Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}.
* @function
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
// LongPrototype.shru = LongPrototype.shiftRightUnsigned;
/**
* Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}.
* @function
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
// LongPrototype.shr_u = LongPrototype.shiftRightUnsigned;
/**
* Returns this Long with bits rotated to the left by the given amount.
* @this {!Long}
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Rotated Long
*/
export const rotateLeft = function rotateLeft(numBits) {
var b;
if (isLong(numBits))
numBits = numBits.toInt();
if ((numBits &= 63) === 0)
return this;
if (numBits === 32)
return fromBits(this.high, this.low, this.unsigned);
if (numBits < 32) {
b = (32 - numBits);
return fromBits(((this.low << numBits) | (this.high >>> b)), ((this.high << numBits) | (this.low >>> b)), this.unsigned);
}
numBits -= 32;
b = (32 - numBits);
return fromBits(((this.high << numBits) | (this.low >>> b)), ((this.low << numBits) | (this.high >>> b)), this.unsigned);
};
/**
* Returns this Long with bits rotated to the left by the given amount. This is an alias of {@link Long#rotateLeft}.
* @function
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Rotated Long
*/
// LongPrototype.rotl = LongPrototype.rotateLeft;
/**
* Returns this Long with bits rotated to the right by the given amount.
* @this {!Long}
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Rotated Long
*/
export const rotateRight = function rotateRight(numBits) {
var b;
if (isLong(numBits))
numBits = numBits.toInt();
if ((numBits &= 63) === 0)
return this;
if (numBits === 32)
return fromBits(this.high, this.low, this.unsigned);
if (numBits < 32) {
b = (32 - numBits);
return fromBits(((this.high << b) | (this.low >>> numBits)), ((this.low << b) | (this.high >>> numBits)), this.unsigned);
}
numBits -= 32;
b = (32 - numBits);
return fromBits(((this.low << b) | (this.high >>> numBits)), ((this.high << b) | (this.low >>> numBits)), this.unsigned);
};
/**
* Returns this Long with bits rotated to the right by the given amount. This is an alias of {@link Long#rotateRight}.
* @function
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Rotated Long
*/
// LongPrototype.rotr = LongPrototype.rotateRight;
/**
* Converts this Long to signed.
* @this {!Long}
* @returns {!Long} Signed long
*/
export function toSigned($this) {
if (!$this.unsigned)
return $this;
return fromBits($this.low, $this.high, false);
}
;
/**
* Converts this Long to unsigned.
* @this {!Long}
* @returns {!Long} Unsigned long
*/
export function toUnsigned($this) {
if ($this.unsigned)
return $this;
return fromBits($this.low, $this.high, true);
}
;
/**
* Converts this Long to its byte representation.
* @param {boolean=} le Whether little or big endian, defaults to big endian
* @this {!Long}
* @returns {!Array.<number>} Byte representation
*/
export function toBytes($this, le) {
return le ? toBytesLE($this) : toBytesBE($this);
}
;
/**
* Converts this Long to its little endian byte representation.
* @this {!Long}
* @returns {!Array.<number>} Little endian byte representation
*/
export function toBytesLE($this) {
var hi = $this.high, lo = $this.low;
return [
lo & 0xff,
lo >>> 8 & 0xff,
lo >>> 16 & 0xff,
lo >>> 24,
hi & 0xff,
hi >>> 8 & 0xff,
hi >>> 16 & 0xff,
hi >>> 24
];
}
;
/**
* Converts this Long to its big endian byte representation.
* @this {!Long}
* @returns {!Array.<number>} Big endian byte representation
*/
export function toBytesBE($this) {
var hi = $this.high, lo = $this.low;
return [
hi >>> 24,
hi >>> 16 & 0xff,
hi >>> 8 & 0xff,
hi & 0xff,
lo >>> 24,
lo >>> 16 & 0xff,
lo >>> 8 & 0xff,
lo & 0xff
];
}
;
/**
* Creates a Long from its byte representation.
* @param {!Array.<number>} bytes Byte representation
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @param {boolean=} le Whether little or big endian, defaults to big endian
* @returns {Long} The corresponding Long value
*/
export function fromBytes(bytes, unsigned, le) {
return le ? fromBytesLE(bytes, unsigned) : fromBytesBE(bytes, unsigned);
}
;
/**
* Creates a Long from its little endian byte representation.
* @param {!Array.<number>} bytes Little endian byte representation
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @returns {Long} The corresponding Long value
*/
export function fromBytesLE(bytes, unsigned) {
return new Long(bytes[0] |
bytes[1] << 8 |
bytes[2] << 16 |
bytes[3] << 24, bytes[4] |
bytes[5] << 8 |
bytes[6] << 16 |
bytes[7] << 24, unsigned);
}
;
/**
* Creates a Long from its big endian byte representation.
* @param {!Array.<number>} bytes Big endian byte representation
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
* @returns {Long} The corresponding Long value
*/
export function fromBytesBE(bytes, unsigned) {
return new Long(bytes[4] << 24 |
bytes[5] << 16 |
bytes[6] << 8 |
bytes[7], bytes[0] << 24 |
bytes[1] << 16 |
bytes[2] << 8 |
bytes[3], unsigned);
}
;
//# sourceMappingURL=long.js.map