text: // 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
  /* tslint:disable */
  import { symbol } from "../Numeric.js";
  
  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); }
  
  Long.prototype[symbol] = function () {
      const x = this;
      return {
          multiply: y => multiply(x, y),
          toPrecision: sd => String(x) + (0).toPrecision(sd).substr(1),
          toExponential: dp => String(x) + (0).toExponential(dp).substr(1),
          toFixed: dp => String(x) + (0).toFixed(dp).substr(1),
          toHex: () => toString(x.unsigned ? x : fromBytes(toBytes(x), true), 16),
      }
  }
  
  // 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
      );
  };
  