1ffe3c632Sopenharmony_ci/** 2ffe3c632Sopenharmony_ci * @fileoverview Protobufs Int64 representation. 3ffe3c632Sopenharmony_ci */ 4ffe3c632Sopenharmony_cigoog.module('protobuf.Int64'); 5ffe3c632Sopenharmony_ci 6ffe3c632Sopenharmony_ciconst Long = goog.require('goog.math.Long'); 7ffe3c632Sopenharmony_ciconst {assert} = goog.require('goog.asserts'); 8ffe3c632Sopenharmony_ci 9ffe3c632Sopenharmony_ci/** 10ffe3c632Sopenharmony_ci * A container for protobufs Int64/Uint64 data type. 11ffe3c632Sopenharmony_ci * @final 12ffe3c632Sopenharmony_ci */ 13ffe3c632Sopenharmony_ciclass Int64 { 14ffe3c632Sopenharmony_ci /** @return {!Int64} */ 15ffe3c632Sopenharmony_ci static getZero() { 16ffe3c632Sopenharmony_ci return ZERO; 17ffe3c632Sopenharmony_ci } 18ffe3c632Sopenharmony_ci 19ffe3c632Sopenharmony_ci /** @return {!Int64} */ 20ffe3c632Sopenharmony_ci static getMinValue() { 21ffe3c632Sopenharmony_ci return MIN_VALUE; 22ffe3c632Sopenharmony_ci } 23ffe3c632Sopenharmony_ci 24ffe3c632Sopenharmony_ci /** @return {!Int64} */ 25ffe3c632Sopenharmony_ci static getMaxValue() { 26ffe3c632Sopenharmony_ci return MAX_VALUE; 27ffe3c632Sopenharmony_ci } 28ffe3c632Sopenharmony_ci 29ffe3c632Sopenharmony_ci /** 30ffe3c632Sopenharmony_ci * Constructs a Int64 given two 32 bit numbers 31ffe3c632Sopenharmony_ci * @param {number} lowBits 32ffe3c632Sopenharmony_ci * @param {number} highBits 33ffe3c632Sopenharmony_ci * @return {!Int64} 34ffe3c632Sopenharmony_ci */ 35ffe3c632Sopenharmony_ci static fromBits(lowBits, highBits) { 36ffe3c632Sopenharmony_ci return new Int64(lowBits, highBits); 37ffe3c632Sopenharmony_ci } 38ffe3c632Sopenharmony_ci 39ffe3c632Sopenharmony_ci /** 40ffe3c632Sopenharmony_ci * Constructs an Int64 from a signed 32 bit number. 41ffe3c632Sopenharmony_ci * @param {number} value 42ffe3c632Sopenharmony_ci * @return {!Int64} 43ffe3c632Sopenharmony_ci */ 44ffe3c632Sopenharmony_ci static fromInt(value) { 45ffe3c632Sopenharmony_ci // TODO: Use our own checking system here. 46ffe3c632Sopenharmony_ci assert(value === (value | 0), 'value should be a 32-bit integer'); 47ffe3c632Sopenharmony_ci // Right shift 31 bits so all high bits are equal to the sign bit. 48ffe3c632Sopenharmony_ci // Note: cannot use >> 32, because (1 >> 32) = 1 (!). 49ffe3c632Sopenharmony_ci const signExtendedHighBits = value >> 31; 50ffe3c632Sopenharmony_ci return new Int64(value, signExtendedHighBits); 51ffe3c632Sopenharmony_ci } 52ffe3c632Sopenharmony_ci 53ffe3c632Sopenharmony_ci /** 54ffe3c632Sopenharmony_ci * Constructs an Int64 from a number (over 32 bits). 55ffe3c632Sopenharmony_ci * @param {number} value 56ffe3c632Sopenharmony_ci * @return {!Int64} 57ffe3c632Sopenharmony_ci */ 58ffe3c632Sopenharmony_ci static fromNumber(value) { 59ffe3c632Sopenharmony_ci if (value > 0) { 60ffe3c632Sopenharmony_ci return new Int64(value, value / TWO_PWR_32_DBL); 61ffe3c632Sopenharmony_ci } else if (value < 0) { 62ffe3c632Sopenharmony_ci return negate(-value, -value / TWO_PWR_32_DBL); 63ffe3c632Sopenharmony_ci } 64ffe3c632Sopenharmony_ci return ZERO; 65ffe3c632Sopenharmony_ci } 66ffe3c632Sopenharmony_ci 67ffe3c632Sopenharmony_ci /** 68ffe3c632Sopenharmony_ci * Construct an Int64 from a signed decimal string. 69ffe3c632Sopenharmony_ci * @param {string} value 70ffe3c632Sopenharmony_ci * @return {!Int64} 71ffe3c632Sopenharmony_ci */ 72ffe3c632Sopenharmony_ci static fromDecimalString(value) { 73ffe3c632Sopenharmony_ci // TODO: Use our own checking system here. 74ffe3c632Sopenharmony_ci assert(value.length > 0); 75ffe3c632Sopenharmony_ci // The basic Number conversion loses precision, but we can use it for 76ffe3c632Sopenharmony_ci // a quick validation that the format is correct and it is an integer. 77ffe3c632Sopenharmony_ci assert(Math.floor(Number(value)).toString().length == value.length); 78ffe3c632Sopenharmony_ci return decimalStringToInt64(value); 79ffe3c632Sopenharmony_ci } 80ffe3c632Sopenharmony_ci 81ffe3c632Sopenharmony_ci /** 82ffe3c632Sopenharmony_ci * Construct an Int64 from a signed hexadecimal string. 83ffe3c632Sopenharmony_ci * @param {string} value 84ffe3c632Sopenharmony_ci * @return {!Int64} 85ffe3c632Sopenharmony_ci */ 86ffe3c632Sopenharmony_ci static fromHexString(value) { 87ffe3c632Sopenharmony_ci // TODO: Use our own checking system here. 88ffe3c632Sopenharmony_ci assert(value.length > 0); 89ffe3c632Sopenharmony_ci assert(value.slice(0, 2) == '0x' || value.slice(0, 3) == '-0x'); 90ffe3c632Sopenharmony_ci const minus = value[0] === '-'; 91ffe3c632Sopenharmony_ci // Strip the 0x or -0x prefix. 92ffe3c632Sopenharmony_ci value = value.slice(minus ? 3 : 2); 93ffe3c632Sopenharmony_ci const lowBits = parseInt(value.slice(-8), 16); 94ffe3c632Sopenharmony_ci const highBits = parseInt(value.slice(-16, -8) || '', 16); 95ffe3c632Sopenharmony_ci return (minus ? negate : Int64.fromBits)(lowBits, highBits); 96ffe3c632Sopenharmony_ci } 97ffe3c632Sopenharmony_ci 98ffe3c632Sopenharmony_ci // Note to the reader: 99ffe3c632Sopenharmony_ci // goog.math.Long suffers from a code size issue. JsCompiler almost always 100ffe3c632Sopenharmony_ci // considers toString methods to be alive in a program. So if you are 101ffe3c632Sopenharmony_ci // constructing a Long instance the toString method is assumed to be live. 102ffe3c632Sopenharmony_ci // Unfortunately Long's toString method makes a large chunk of code alive 103ffe3c632Sopenharmony_ci // of the entire class adding 1.3kB (gzip) of extra code size. 104ffe3c632Sopenharmony_ci // Callers that are sensitive to code size and are not using Long already 105ffe3c632Sopenharmony_ci // should avoid calling this method. 106ffe3c632Sopenharmony_ci /** 107ffe3c632Sopenharmony_ci * Creates an Int64 instance from a Long value. 108ffe3c632Sopenharmony_ci * @param {!Long} value 109ffe3c632Sopenharmony_ci * @return {!Int64} 110ffe3c632Sopenharmony_ci */ 111ffe3c632Sopenharmony_ci static fromLong(value) { 112ffe3c632Sopenharmony_ci return new Int64(value.getLowBits(), value.getHighBits()); 113ffe3c632Sopenharmony_ci } 114ffe3c632Sopenharmony_ci 115ffe3c632Sopenharmony_ci /** 116ffe3c632Sopenharmony_ci * @param {number} lowBits 117ffe3c632Sopenharmony_ci * @param {number} highBits 118ffe3c632Sopenharmony_ci * @private 119ffe3c632Sopenharmony_ci */ 120ffe3c632Sopenharmony_ci constructor(lowBits, highBits) { 121ffe3c632Sopenharmony_ci /** @const @private {number} */ 122ffe3c632Sopenharmony_ci this.lowBits_ = lowBits | 0; 123ffe3c632Sopenharmony_ci /** @const @private {number} */ 124ffe3c632Sopenharmony_ci this.highBits_ = highBits | 0; 125ffe3c632Sopenharmony_ci } 126ffe3c632Sopenharmony_ci 127ffe3c632Sopenharmony_ci /** 128ffe3c632Sopenharmony_ci * Returns the int64 value as a JavaScript number. This will lose precision 129ffe3c632Sopenharmony_ci * if the number is outside of the safe range for JavaScript of 53 bits 130ffe3c632Sopenharmony_ci * precision. 131ffe3c632Sopenharmony_ci * @return {number} 132ffe3c632Sopenharmony_ci */ 133ffe3c632Sopenharmony_ci asNumber() { 134ffe3c632Sopenharmony_ci const result = this.highBits_ * TWO_PWR_32_DBL + this.getLowBitsUnsigned(); 135ffe3c632Sopenharmony_ci // TODO: Use our own checking system here. 136ffe3c632Sopenharmony_ci assert( 137ffe3c632Sopenharmony_ci Number.isSafeInteger(result), 'conversion to number loses precision.'); 138ffe3c632Sopenharmony_ci return result; 139ffe3c632Sopenharmony_ci } 140ffe3c632Sopenharmony_ci 141ffe3c632Sopenharmony_ci // Note to the reader: 142ffe3c632Sopenharmony_ci // goog.math.Long suffers from a code size issue. JsCompiler almost always 143ffe3c632Sopenharmony_ci // considers toString methods to be alive in a program. So if you are 144ffe3c632Sopenharmony_ci // constructing a Long instance the toString method is assumed to be live. 145ffe3c632Sopenharmony_ci // Unfortunately Long's toString method makes a large chunk of code alive 146ffe3c632Sopenharmony_ci // of the entire class adding 1.3kB (gzip) of extra code size. 147ffe3c632Sopenharmony_ci // Callers that are sensitive to code size and are not using Long already 148ffe3c632Sopenharmony_ci // should avoid calling this method. 149ffe3c632Sopenharmony_ci /** @return {!Long} */ 150ffe3c632Sopenharmony_ci asLong() { 151ffe3c632Sopenharmony_ci return Long.fromBits(this.lowBits_, this.highBits_); 152ffe3c632Sopenharmony_ci } 153ffe3c632Sopenharmony_ci 154ffe3c632Sopenharmony_ci /** @return {number} Signed 32-bit integer value. */ 155ffe3c632Sopenharmony_ci getLowBits() { 156ffe3c632Sopenharmony_ci return this.lowBits_; 157ffe3c632Sopenharmony_ci } 158ffe3c632Sopenharmony_ci 159ffe3c632Sopenharmony_ci /** @return {number} Signed 32-bit integer value. */ 160ffe3c632Sopenharmony_ci getHighBits() { 161ffe3c632Sopenharmony_ci return this.highBits_; 162ffe3c632Sopenharmony_ci } 163ffe3c632Sopenharmony_ci 164ffe3c632Sopenharmony_ci /** @return {number} Unsigned 32-bit integer. */ 165ffe3c632Sopenharmony_ci getLowBitsUnsigned() { 166ffe3c632Sopenharmony_ci return this.lowBits_ >>> 0; 167ffe3c632Sopenharmony_ci } 168ffe3c632Sopenharmony_ci 169ffe3c632Sopenharmony_ci /** @return {number} Unsigned 32-bit integer. */ 170ffe3c632Sopenharmony_ci getHighBitsUnsigned() { 171ffe3c632Sopenharmony_ci return this.highBits_ >>> 0; 172ffe3c632Sopenharmony_ci } 173ffe3c632Sopenharmony_ci 174ffe3c632Sopenharmony_ci /** @return {string} */ 175ffe3c632Sopenharmony_ci toSignedDecimalString() { 176ffe3c632Sopenharmony_ci return joinSignedDecimalString(this); 177ffe3c632Sopenharmony_ci } 178ffe3c632Sopenharmony_ci 179ffe3c632Sopenharmony_ci /** @return {string} */ 180ffe3c632Sopenharmony_ci toUnsignedDecimalString() { 181ffe3c632Sopenharmony_ci return joinUnsignedDecimalString(this); 182ffe3c632Sopenharmony_ci } 183ffe3c632Sopenharmony_ci 184ffe3c632Sopenharmony_ci /** 185ffe3c632Sopenharmony_ci * Returns an unsigned hexadecimal string representation of the Int64. 186ffe3c632Sopenharmony_ci * @return {string} 187ffe3c632Sopenharmony_ci */ 188ffe3c632Sopenharmony_ci toHexString() { 189ffe3c632Sopenharmony_ci let nibbles = new Array(16); 190ffe3c632Sopenharmony_ci let lowBits = this.lowBits_; 191ffe3c632Sopenharmony_ci let highBits = this.highBits_; 192ffe3c632Sopenharmony_ci for (let highIndex = 7, lowIndex = 15; lowIndex > 7; 193ffe3c632Sopenharmony_ci highIndex--, lowIndex--) { 194ffe3c632Sopenharmony_ci nibbles[highIndex] = HEX_DIGITS[highBits & 0xF]; 195ffe3c632Sopenharmony_ci nibbles[lowIndex] = HEX_DIGITS[lowBits & 0xF]; 196ffe3c632Sopenharmony_ci highBits = highBits >>> 4; 197ffe3c632Sopenharmony_ci lowBits = lowBits >>> 4; 198ffe3c632Sopenharmony_ci } 199ffe3c632Sopenharmony_ci // Always leave the least significant hex digit. 200ffe3c632Sopenharmony_ci while (nibbles.length > 1 && nibbles[0] == '0') { 201ffe3c632Sopenharmony_ci nibbles.shift(); 202ffe3c632Sopenharmony_ci } 203ffe3c632Sopenharmony_ci return `0x${nibbles.join('')}`; 204ffe3c632Sopenharmony_ci } 205ffe3c632Sopenharmony_ci 206ffe3c632Sopenharmony_ci /** 207ffe3c632Sopenharmony_ci * @param {*} other object to compare against. 208ffe3c632Sopenharmony_ci * @return {boolean} Whether this Int64 equals the other. 209ffe3c632Sopenharmony_ci */ 210ffe3c632Sopenharmony_ci equals(other) { 211ffe3c632Sopenharmony_ci if (this === other) { 212ffe3c632Sopenharmony_ci return true; 213ffe3c632Sopenharmony_ci } 214ffe3c632Sopenharmony_ci if (!(other instanceof Int64)) { 215ffe3c632Sopenharmony_ci return false; 216ffe3c632Sopenharmony_ci } 217ffe3c632Sopenharmony_ci // Compare low parts first as there is higher chance they are different. 218ffe3c632Sopenharmony_ci const otherInt64 = /** @type{!Int64} */ (other); 219ffe3c632Sopenharmony_ci return (this.lowBits_ === otherInt64.lowBits_) && 220ffe3c632Sopenharmony_ci (this.highBits_ === otherInt64.highBits_); 221ffe3c632Sopenharmony_ci } 222ffe3c632Sopenharmony_ci 223ffe3c632Sopenharmony_ci /** 224ffe3c632Sopenharmony_ci * Returns a number (int32) that is suitable for using in hashed structures. 225ffe3c632Sopenharmony_ci * @return {number} 226ffe3c632Sopenharmony_ci */ 227ffe3c632Sopenharmony_ci hashCode() { 228ffe3c632Sopenharmony_ci return (31 * this.lowBits_ + 17 * this.highBits_) | 0; 229ffe3c632Sopenharmony_ci } 230ffe3c632Sopenharmony_ci} 231ffe3c632Sopenharmony_ci 232ffe3c632Sopenharmony_ci/** 233ffe3c632Sopenharmony_ci * Losslessly converts a 64-bit unsigned integer in 32:32 split representation 234ffe3c632Sopenharmony_ci * into a decimal string. 235ffe3c632Sopenharmony_ci * @param {!Int64} int64 236ffe3c632Sopenharmony_ci * @return {string} The binary number represented as a string. 237ffe3c632Sopenharmony_ci */ 238ffe3c632Sopenharmony_ciconst joinUnsignedDecimalString = (int64) => { 239ffe3c632Sopenharmony_ci const lowBits = int64.getLowBitsUnsigned(); 240ffe3c632Sopenharmony_ci const highBits = int64.getHighBitsUnsigned(); 241ffe3c632Sopenharmony_ci // Skip the expensive conversion if the number is small enough to use the 242ffe3c632Sopenharmony_ci // built-in conversions. 243ffe3c632Sopenharmony_ci // Number.MAX_SAFE_INTEGER = 0x001FFFFF FFFFFFFF, thus any number with 244ffe3c632Sopenharmony_ci // highBits <= 0x1FFFFF can be safely expressed with a double and retain 245ffe3c632Sopenharmony_ci // integer precision. 246ffe3c632Sopenharmony_ci // Proven by: Number.isSafeInteger(0x1FFFFF * 2**32 + 0xFFFFFFFF) == true. 247ffe3c632Sopenharmony_ci if (highBits <= 0x1FFFFF) { 248ffe3c632Sopenharmony_ci return String(TWO_PWR_32_DBL * highBits + lowBits); 249ffe3c632Sopenharmony_ci } 250ffe3c632Sopenharmony_ci 251ffe3c632Sopenharmony_ci // What this code is doing is essentially converting the input number from 252ffe3c632Sopenharmony_ci // base-2 to base-1e7, which allows us to represent the 64-bit range with 253ffe3c632Sopenharmony_ci // only 3 (very large) digits. Those digits are then trivial to convert to 254ffe3c632Sopenharmony_ci // a base-10 string. 255ffe3c632Sopenharmony_ci 256ffe3c632Sopenharmony_ci // The magic numbers used here are - 257ffe3c632Sopenharmony_ci // 2^24 = 16777216 = (1,6777216) in base-1e7. 258ffe3c632Sopenharmony_ci // 2^48 = 281474976710656 = (2,8147497,6710656) in base-1e7. 259ffe3c632Sopenharmony_ci 260ffe3c632Sopenharmony_ci // Split 32:32 representation into 16:24:24 representation so our 261ffe3c632Sopenharmony_ci // intermediate digits don't overflow. 262ffe3c632Sopenharmony_ci const low = lowBits & LOW_24_BITS; 263ffe3c632Sopenharmony_ci const mid = ((lowBits >>> 24) | (highBits << 8)) & LOW_24_BITS; 264ffe3c632Sopenharmony_ci const high = (highBits >> 16) & LOW_16_BITS; 265ffe3c632Sopenharmony_ci 266ffe3c632Sopenharmony_ci // Assemble our three base-1e7 digits, ignoring carries. The maximum 267ffe3c632Sopenharmony_ci // value in a digit at this step is representable as a 48-bit integer, which 268ffe3c632Sopenharmony_ci // can be stored in a 64-bit floating point number. 269ffe3c632Sopenharmony_ci let digitA = low + (mid * 6777216) + (high * 6710656); 270ffe3c632Sopenharmony_ci let digitB = mid + (high * 8147497); 271ffe3c632Sopenharmony_ci let digitC = (high * 2); 272ffe3c632Sopenharmony_ci 273ffe3c632Sopenharmony_ci // Apply carries from A to B and from B to C. 274ffe3c632Sopenharmony_ci const base = 10000000; 275ffe3c632Sopenharmony_ci if (digitA >= base) { 276ffe3c632Sopenharmony_ci digitB += Math.floor(digitA / base); 277ffe3c632Sopenharmony_ci digitA %= base; 278ffe3c632Sopenharmony_ci } 279ffe3c632Sopenharmony_ci 280ffe3c632Sopenharmony_ci if (digitB >= base) { 281ffe3c632Sopenharmony_ci digitC += Math.floor(digitB / base); 282ffe3c632Sopenharmony_ci digitB %= base; 283ffe3c632Sopenharmony_ci } 284ffe3c632Sopenharmony_ci 285ffe3c632Sopenharmony_ci // If digitC is 0, then we should have returned in the trivial code path 286ffe3c632Sopenharmony_ci // at the top for non-safe integers. Given this, we can assume both digitB 287ffe3c632Sopenharmony_ci // and digitA need leading zeros. 288ffe3c632Sopenharmony_ci // TODO: Use our own checking system here. 289ffe3c632Sopenharmony_ci assert(digitC); 290ffe3c632Sopenharmony_ci return digitC + decimalFrom1e7WithLeadingZeros(digitB) + 291ffe3c632Sopenharmony_ci decimalFrom1e7WithLeadingZeros(digitA); 292ffe3c632Sopenharmony_ci}; 293ffe3c632Sopenharmony_ci 294ffe3c632Sopenharmony_ci/** 295ffe3c632Sopenharmony_ci * @param {number} digit1e7 Number < 1e7 296ffe3c632Sopenharmony_ci * @return {string} Decimal representation of digit1e7 with leading zeros. 297ffe3c632Sopenharmony_ci */ 298ffe3c632Sopenharmony_ciconst decimalFrom1e7WithLeadingZeros = (digit1e7) => { 299ffe3c632Sopenharmony_ci const partial = String(digit1e7); 300ffe3c632Sopenharmony_ci return '0000000'.slice(partial.length) + partial; 301ffe3c632Sopenharmony_ci}; 302ffe3c632Sopenharmony_ci 303ffe3c632Sopenharmony_ci/** 304ffe3c632Sopenharmony_ci * Losslessly converts a 64-bit signed integer in 32:32 split representation 305ffe3c632Sopenharmony_ci * into a decimal string. 306ffe3c632Sopenharmony_ci * @param {!Int64} int64 307ffe3c632Sopenharmony_ci * @return {string} The binary number represented as a string. 308ffe3c632Sopenharmony_ci */ 309ffe3c632Sopenharmony_ciconst joinSignedDecimalString = (int64) => { 310ffe3c632Sopenharmony_ci // If we're treating the input as a signed value and the high bit is set, do 311ffe3c632Sopenharmony_ci // a manual two's complement conversion before the decimal conversion. 312ffe3c632Sopenharmony_ci const negative = (int64.getHighBits() & 0x80000000); 313ffe3c632Sopenharmony_ci if (negative) { 314ffe3c632Sopenharmony_ci int64 = negate(int64.getLowBits(), int64.getHighBits()); 315ffe3c632Sopenharmony_ci } 316ffe3c632Sopenharmony_ci 317ffe3c632Sopenharmony_ci const result = joinUnsignedDecimalString(int64); 318ffe3c632Sopenharmony_ci return negative ? '-' + result : result; 319ffe3c632Sopenharmony_ci}; 320ffe3c632Sopenharmony_ci 321ffe3c632Sopenharmony_ci/** 322ffe3c632Sopenharmony_ci * @param {string} dec 323ffe3c632Sopenharmony_ci * @return {!Int64} 324ffe3c632Sopenharmony_ci */ 325ffe3c632Sopenharmony_ciconst decimalStringToInt64 = (dec) => { 326ffe3c632Sopenharmony_ci // Check for minus sign. 327ffe3c632Sopenharmony_ci const minus = dec[0] === '-'; 328ffe3c632Sopenharmony_ci if (minus) { 329ffe3c632Sopenharmony_ci dec = dec.slice(1); 330ffe3c632Sopenharmony_ci } 331ffe3c632Sopenharmony_ci 332ffe3c632Sopenharmony_ci // Work 6 decimal digits at a time, acting like we're converting base 1e6 333ffe3c632Sopenharmony_ci // digits to binary. This is safe to do with floating point math because 334ffe3c632Sopenharmony_ci // Number.isSafeInteger(ALL_32_BITS * 1e6) == true. 335ffe3c632Sopenharmony_ci const base = 1e6; 336ffe3c632Sopenharmony_ci let lowBits = 0; 337ffe3c632Sopenharmony_ci let highBits = 0; 338ffe3c632Sopenharmony_ci function add1e6digit(begin, end = undefined) { 339ffe3c632Sopenharmony_ci // Note: Number('') is 0. 340ffe3c632Sopenharmony_ci const digit1e6 = Number(dec.slice(begin, end)); 341ffe3c632Sopenharmony_ci highBits *= base; 342ffe3c632Sopenharmony_ci lowBits = lowBits * base + digit1e6; 343ffe3c632Sopenharmony_ci // Carry bits from lowBits to 344ffe3c632Sopenharmony_ci if (lowBits >= TWO_PWR_32_DBL) { 345ffe3c632Sopenharmony_ci highBits = highBits + ((lowBits / TWO_PWR_32_DBL) | 0); 346ffe3c632Sopenharmony_ci lowBits = lowBits % TWO_PWR_32_DBL; 347ffe3c632Sopenharmony_ci } 348ffe3c632Sopenharmony_ci } 349ffe3c632Sopenharmony_ci add1e6digit(-24, -18); 350ffe3c632Sopenharmony_ci add1e6digit(-18, -12); 351ffe3c632Sopenharmony_ci add1e6digit(-12, -6); 352ffe3c632Sopenharmony_ci add1e6digit(-6); 353ffe3c632Sopenharmony_ci 354ffe3c632Sopenharmony_ci return (minus ? negate : Int64.fromBits)(lowBits, highBits); 355ffe3c632Sopenharmony_ci}; 356ffe3c632Sopenharmony_ci 357ffe3c632Sopenharmony_ci/** 358ffe3c632Sopenharmony_ci * @param {number} lowBits 359ffe3c632Sopenharmony_ci * @param {number} highBits 360ffe3c632Sopenharmony_ci * @return {!Int64} Two's compliment negation of input. 361ffe3c632Sopenharmony_ci * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Signed_32-bit_integers 362ffe3c632Sopenharmony_ci */ 363ffe3c632Sopenharmony_ciconst negate = (lowBits, highBits) => { 364ffe3c632Sopenharmony_ci highBits = ~highBits; 365ffe3c632Sopenharmony_ci if (lowBits) { 366ffe3c632Sopenharmony_ci lowBits = ~lowBits + 1; 367ffe3c632Sopenharmony_ci } else { 368ffe3c632Sopenharmony_ci // If lowBits is 0, then bitwise-not is 0xFFFFFFFF, 369ffe3c632Sopenharmony_ci // adding 1 to that, results in 0x100000000, which leaves 370ffe3c632Sopenharmony_ci // the low bits 0x0 and simply adds one to the high bits. 371ffe3c632Sopenharmony_ci highBits += 1; 372ffe3c632Sopenharmony_ci } 373ffe3c632Sopenharmony_ci return Int64.fromBits(lowBits, highBits); 374ffe3c632Sopenharmony_ci}; 375ffe3c632Sopenharmony_ci 376ffe3c632Sopenharmony_ci/** @const {!Int64} */ 377ffe3c632Sopenharmony_ciconst ZERO = new Int64(0, 0); 378ffe3c632Sopenharmony_ci 379ffe3c632Sopenharmony_ci/** @const @private {number} */ 380ffe3c632Sopenharmony_ciconst LOW_16_BITS = 0xFFFF; 381ffe3c632Sopenharmony_ci 382ffe3c632Sopenharmony_ci/** @const @private {number} */ 383ffe3c632Sopenharmony_ciconst LOW_24_BITS = 0xFFFFFF; 384ffe3c632Sopenharmony_ci 385ffe3c632Sopenharmony_ci/** @const @private {number} */ 386ffe3c632Sopenharmony_ciconst LOW_31_BITS = 0x7FFFFFFF; 387ffe3c632Sopenharmony_ci 388ffe3c632Sopenharmony_ci/** @const @private {number} */ 389ffe3c632Sopenharmony_ciconst ALL_32_BITS = 0xFFFFFFFF; 390ffe3c632Sopenharmony_ci 391ffe3c632Sopenharmony_ci/** @const {!Int64} */ 392ffe3c632Sopenharmony_ciconst MAX_VALUE = Int64.fromBits(ALL_32_BITS, LOW_31_BITS); 393ffe3c632Sopenharmony_ci 394ffe3c632Sopenharmony_ci/** @const {!Int64} */ 395ffe3c632Sopenharmony_ciconst MIN_VALUE = Int64.fromBits(0, 0x80000000); 396ffe3c632Sopenharmony_ci 397ffe3c632Sopenharmony_ci/** @const {number} */ 398ffe3c632Sopenharmony_ciconst TWO_PWR_32_DBL = 0x100000000; 399ffe3c632Sopenharmony_ci 400ffe3c632Sopenharmony_ci/** @const {string} */ 401ffe3c632Sopenharmony_ciconst HEX_DIGITS = '0123456789abcdef'; 402ffe3c632Sopenharmony_ci 403ffe3c632Sopenharmony_ciexports = Int64; 404