fable-compiler
Version:
Fable compiler
1,102 lines • 35.8 kB
JavaScript
// Adapted from: https://github.com/dcodeIO/long.js/blob/f572e3a17d313730cf11eb838f6d2a5e31626f8a/src/long.js
// Apache License 2.0: https://github.com/dcodeIO/long.js/blob/master/LICENSE
/* tslint:disable */
import { isValid } from "./Int32";
import { combineHashCodes } from "./Util";
/**
* 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 default 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 () {
return combineHashCodes([this.unsigned ? 1 : 0, this.high, this.low]);
};
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); };
export const neg = op_UnaryNegation;
export const not = op_LogicalNot;
export const add = op_Addition;
export const sub = op_Subtraction;
export const mul = op_Multiply;
export const div = op_Division;
export const mod = op_Modulus;
export const shl = op_LeftShift;
export const shr = op_RightShift;
export const and = op_BitwiseAnd;
export const or = op_BitwiseOr;
export const xor = op_ExclusiveOr;
// 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
*/
function isLong(obj) {
return (obj && obj["__isLong__"]) === true;
}
/**
* 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;
}
}
/**
* @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 op_UnaryNegation(fromNumber(-value, unsigned));
return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
}
/**
* @param {number} value
* @param {boolean} unsigned
* @param {number} kind
* @returns {!Long}
* @inner
*/
export function fromInteger(value, unsigned, kind) {
var x;
var xh = 0;
switch (kind) {
case 0:
x = value << 24 >> 24;
xh = x;
break;
case 4:
x = value << 24 >>> 24;
break;
case 1:
x = value << 16 >> 16;
xh = x;
break;
case 5:
x = value << 16 >>> 16;
break;
case 2:
x = value >> 0;
xh = x;
break;
case 6: x = value >>> 0;
}
return fromBits(x, xh >> 31, unsigned);
}
/**
* @param {number} lowBits
* @param {number} highBits
* @param {boolean=} unsigned
* @returns {!Long}
* @inner
*/
export function fromBits(lowBits, highBits, unsigned) {
return new Long(lowBits, highBits, unsigned);
}
/**
* @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 op_UnaryNegation(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 = op_Addition(op_Multiply(result, power), fromNumber(value));
}
else {
result = op_Multiply(result, radixToPower);
result = op_Addition(result, fromNumber(value));
}
}
result.unsigned = unsigned;
return result;
}
function getMaxValue(unsigned, radix, isNegative) {
switch (radix) {
case 2: return unsigned ?
"1111111111111111111111111111111111111111111111111111111111111111" :
(isNegative ? "1000000000000000000000000000000000000000000000000000000000000000"
: "111111111111111111111111111111111111111111111111111111111111111");
case 8: return unsigned ?
"1777777777777777777777" :
(isNegative ? "1000000000000000000000" : "777777777777777777777");
case 10: return unsigned ?
"18446744073709551615" :
(isNegative ? "9223372036854775808" : "9223372036854775807");
case 16: return unsigned ?
"FFFFFFFFFFFFFFFF" :
(isNegative ? "8000000000000000" : "7FFFFFFFFFFFFFFF");
default: throw new Error("Invalid radix.");
}
}
export function parse(str, style, unsigned, bitsize, radix) {
const res = isValid(str, style, radix);
if (res != null) {
const lessOrEqual = (x, y) => {
const len = Math.max(x.length, y.length);
return x.padStart(len, "0") <= y.padStart(len, "0");
};
const isNegative = res.sign === "-";
const maxValue = getMaxValue(unsigned || res.radix !== 10, res.radix, isNegative);
if (lessOrEqual(res.digits.toUpperCase(), maxValue)) {
str = isNegative ? res.sign + res.digits : res.digits;
return fromString(str, unsigned, res.radix);
}
}
throw new Error("Input string was not in a correct format.");
}
export function tryParse(str, style, unsigned, bitsize) {
try {
const v = parse(str, style, unsigned, bitsize);
return [true, v];
}
catch (_a) {
// supress error
}
return [false, ZERO];
}
/**
* @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);
}
// 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);
/**
* @type {!Long}
* @inner
*/
export var UZERO = fromInt(0, true);
/**
* @type {!Long}
* @inner
*/
export var ONE = fromInt(1);
/**
* @type {!Long}
* @inner
*/
export var UONE = fromInt(1, true);
/**
* @type {!Long}
* @inner
*/
export var NEG_ONE = fromInt(-1);
/**
* @type {!Long}
* @inner
*/
export var MAX_VALUE = fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0, false);
/**
* @type {!Long}
* @inner
*/
export var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF | 0, 0xFFFFFFFF | 0, true);
/**
* @type {!Long}
* @inner
*/
export var MIN_VALUE = fromBits(0, 0x80000000 | 0, false);
/**
* Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
* @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).
* @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.
* @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 = op_Division($this, radixLong), rem1 = op_Subtraction(op_Multiply(div, radixLong), $this);
return toString(div, radix) + toInt(rem1).toString(radix);
}
else
return '-' + toString(op_UnaryNegation($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 = op_Division(rem, radixToPower), intval = toInt(op_Subtraction(rem, op_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.
* @returns {number} Signed high bits
*/
export function getHighBits($this) {
return $this.high;
}
;
/**
* Gets the high 32 bits as an unsigned integer.
* @returns {number} Unsigned high bits
*/
export function getHighBitsUnsigned($this) {
return $this.high >>> 0;
}
;
/**
* Gets the low 32 bits as a signed integer.
* @returns {number} Signed low bits
*/
export function getLowBits($this) {
return $this.low;
}
;
/**
* Gets the low 32 bits as an unsigned integer.
* @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.
* @returns {number}
*/
export function getNumBitsAbs($this) {
if (isNegative($this)) // Unsigned Longs are never negative
return equals($this, MIN_VALUE) ? 64 : getNumBitsAbs(op_UnaryNegation($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.
* @returns {boolean}
*/
export function isZero($this) {
return $this.high === 0 && $this.low === 0;
}
;
/**
* Tests if this Long's value is negative.
* @returns {boolean}
*/
export function isNegative($this) {
return !$this.unsigned && $this.high < 0;
}
;
/**
* Tests if this Long's value is positive.
* @returns {boolean}
*/
export function isPositive($this) {
return $this.unsigned || $this.high >= 0;
}
;
/**
* Tests if this Long's value is odd.
* @returns {boolean}
*/
export function isOdd($this) {
return ($this.low & 1) === 1;
}
;
/**
* Tests if this Long's value is even.
* @returns {boolean}
*/
export function isEven($this) {
return ($this.low & 1) === 0;
}
;
/**
* Tests if this Long's value equals the specified's.
* @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 differs from the specified's.
* @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 is less than the specified's.
* @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 or equal the specified's.
* @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 greater than the specified's.
* @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 or equal the specified's.
* @param {!Long|number|string} other Other value
* @returns {boolean}
*/
export function greaterThanOrEqual($this, other) {
return compare($this, /* validates */ other) >= 0;
}
;
/**
* Compares this Long's value with the specified's.
* @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(op_Subtraction($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;
}
;
/**
* Absolute value of the given number.
*/
export function abs($this) {
if (!$this.unsigned && isNegative($this))
return op_UnaryNegation($this);
else
return $this;
}
/**
* Negates this Long's value.
* @returns {!Long} Negated Long
*/
export function op_UnaryNegation($this) {
if (!$this.unsigned && equals($this, MIN_VALUE))
return MIN_VALUE;
return op_Addition(op_LogicalNot($this), ONE);
}
;
/**
* Returns the sum of this and the specified Long.
* @param {!Long|number|string} addend Addend
* @returns {!Long} Sum
*/
export function op_Addition($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.
* @param {!Long|number|string} subtrahend Subtrahend
* @returns {!Long} Difference
*/
export function op_Subtraction($this, subtrahend) {
if (!isLong(subtrahend))
subtrahend = fromValue(subtrahend);
return op_Addition($this, op_UnaryNegation(subtrahend));
}
;
/**
* Returns the product of this and the specified Long.
* @param {!Long|number|string} multiplier Multiplier
* @returns {!Long} Product
*/
export function op_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 op_Multiply(op_UnaryNegation($this), op_UnaryNegation(multiplier));
else
return op_UnaryNegation(op_Multiply(op_UnaryNegation($this), multiplier));
}
else if (isNegative(multiplier))
return op_UnaryNegation(op_Multiply($this, op_UnaryNegation(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 this Long divided by the specified. The result is signed if this Long is signed or
* unsigned if this Long is unsigned.
* @param {!Long|number|string} divisor Divisor
* @returns {!Long} Quotient
*/
export function op_Division($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 = op_RightShift($this, 1);
approx = op_LeftShift(op_Division(halfThis, divisor), 1);
if (equals(approx, ZERO)) {
return isNegative(divisor) ? ONE : NEG_ONE;
}
else {
rem = op_Subtraction($this, op_Multiply(divisor, approx));
res = op_Addition(approx, op_Division(rem, divisor));
return res;
}
}
}
else if (equals(divisor, MIN_VALUE))
return $this.unsigned ? UZERO : ZERO;
if (isNegative($this)) {
if (isNegative(divisor))
return op_Division(op_UnaryNegation($this), op_UnaryNegation(divisor));
return op_UnaryNegation(op_Division(op_UnaryNegation($this), divisor));
}
else if (isNegative(divisor))
return op_UnaryNegation(op_Division($this, op_UnaryNegation(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, op_RightShiftUnsigned($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 = op_Multiply(approxRes, divisor);
while (isNegative(approxRem) || greaterThan(approxRem, rem)) {
approx -= delta;
approxRes = fromNumber(approx, $this.unsigned);
approxRem = op_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 = op_Addition(res, approxRes);
rem = op_Subtraction(rem, approxRem);
}
return res;
}
;
/**
* Returns this Long modulo the specified.
* @param {!Long|number|string} divisor Divisor
* @returns {!Long} Remainder
*/
export function op_Modulus($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 op_Subtraction($this, op_Multiply(op_Division($this, divisor), divisor));
}
;
/**
* Returns the bitwise NOT of this Long.
* @returns {!Long}
*/
export function op_LogicalNot($this) {
return fromBits(~$this.low, ~$this.high, $this.unsigned);
}
;
/**
* Returns the bitwise AND of this Long and the specified.
* @param {!Long|number|string} other Other Long
* @returns {!Long}
*/
export function op_BitwiseAnd($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.
* @param {!Long|number|string} other Other Long
* @returns {!Long}
*/
export function op_BitwiseOr($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.
* @param {!Long|number|string} other Other Long
* @returns {!Long}
*/
export function op_ExclusiveOr($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.
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
export function op_LeftShift($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 arithmetically shifted to the right by the given amount.
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
export function op_RightShift($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 logically shifted to the right by the given amount.
* @param {number|!Long} numBits Number of bits
* @returns {!Long} Shifted Long
*/
export function op_RightShiftUnsigned($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);
}
}
;
/**
* Converts this Long to signed.
* @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.
* @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
* @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.
* @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.
* @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);
}
;
export function unixEpochMillisecondsToTicks(ms, offset) {
return op_Multiply(op_Addition(op_Addition(fromNumber(ms), 62135596800000), offset), 10000);
}
export function ticksToUnixEpochMilliseconds(ticks) {
return toNumber(op_Subtraction(op_Division(ticks, 10000), 62135596800000));
}
export function makeRangeStepFunction(step, last, unsigned) {
const stepComparedWithZero = compare(step, unsigned ? UZERO : ZERO);
if (stepComparedWithZero === 0) {
throw new Error("The step of a range cannot be zero");
}
const stepGreaterThanZero = stepComparedWithZero > 0;
return (x) => {
const comparedWithLast = compare(x, last);
if ((stepGreaterThanZero && comparedWithLast <= 0)
|| (!stepGreaterThanZero && comparedWithLast >= 0)) {
return [x, op_Addition(x, step)];
}
else {
return null;
}
};
}
//# sourceMappingURL=Long.js.map