diff --git a/lib/src/int64.dart b/lib/src/int64.dart index a64b902..de4728e 100644 --- a/lib/src/int64.dart +++ b/lib/src/int64.dart @@ -2,197 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// ignore_for_file: constant_identifier_names - // `dart:html` is only available on dart2js (dart2wasm won't support it), so we // can check availability of it to test whether we're compiling to JS. Other // targets (AOT, JIT, Wasm) support 64-bit `int`s. -import 'int64_native.dart' if (dart.library.html) 'int64_emulated.dart'; -import 'intx.dart'; -import 'utilities.dart' as u; - -/// An immutable 64-bit signed integer, in the range `[-2^63, 2^63 - 1]`. -/// Arithmetic operations may overflow in order to maintain this range. -abstract class Int64 implements IntX { - /// The maximum positive value attainable by an [Int64], namely - /// 9,223,372,036,854,775,807. - static const Int64 MAX_VALUE = Int64Impl.MAX_VALUE; - - /// The minimum positive value attainable by an [Int64], namely - /// -9,223,372,036,854,775,808. - static const Int64 MIN_VALUE = Int64Impl.MIN_VALUE; - - /// An [Int64] constant equal to 0. - static const Int64 ZERO = Int64Impl.ZERO; - - /// An [Int64] constant equal to 1. - static const Int64 ONE = Int64Impl.ONE; - - /// An [Int64] constant equal to 2. - static const Int64 TWO = Int64Impl.TWO; - - factory Int64([int value = 0]) => Int64Impl(value); - - /// Constructs an [Int64] from a pair of 32-bit integers having the value - /// [:((high & 0xffffffff) << 32) | (low & 0xffffffff):]. - factory Int64.fromInts(int high, int low) => Int64Impl.fromInts(high, low); - - factory Int64.fromBytes(List bytes) => Int64Impl.fromBytes(bytes); - - factory Int64.fromBytesBigEndian(List bytes) => - Int64Impl.fromBytesBigEndian(bytes); - - /// Parses [source] as a decimal numeral. - /// - /// Returns an [Int64] with the numerical value of [source]. If the numerical - /// value of [source] does not fit in a signed 64 bit integer, the numerical - /// value is truncated to the lowest 64 bits of the value's binary - /// representation, interpreted as a 64-bit two's complement integer. - /// - /// The [source] string must contain a sequence of digits (`0`-`9`), possibly - /// prefixed by a `-` sign. - /// - /// Throws a [FormatException] if the input is not a valid decimal integer - /// numeral. - static Int64 parseInt(String source) => - Int64Impl.parseRadix(source, 10, true)!; - - /// Parses [source] as a decimal numeral. - /// - /// Returns an [Int64] with the numerical value of [source]. If the numerical - /// value of [source] does not fit in a signed 64 bit integer, the numerical - /// value is truncated to the lowest 64 bits of the value's binary - /// representation, interpreted as a 64-bit two's complement integer. - /// - /// The [source] string must contain a sequence of digits (`0`-`9`), possibly - /// prefixed by a `-` sign. - /// - /// Returns `null` if the input is not a valid decimal integer numeral. - static Int64? tryParseInt(String source) => - Int64Impl.parseRadix(source, 10, false); - - /// Parses [source] in a given [radix] between 2 and 36. - /// - /// Returns an [Int64] with the numerical value of [source]. If the numerical - /// value of [source] does not fit in a signed 64 bit integer, the numerical - /// value is truncated to the lowest 64 bits of the value's binary - /// representation, interpreted as a 64-bit two's complement integer. - /// - /// The [source] string must contain a sequence of base-[radix] digits (using - /// letters from `a` to `z` as digits with values 10 through 25 for radixes - /// above 10), possibly prefixed by a `-` sign. - /// - /// Throws a [FormatException] if the input is not recognized as a valid - /// integer numeral. - static Int64 parseRadix(String source, int radix) => - Int64Impl.parseRadix(source, u.validateRadix(radix), true)!; - - /// Parses [source] in a given [radix] between 2 and 36. - /// - /// Returns an [Int64] with the numerical value of [source]. If the numerical - /// value of [source] does not fit in a signed 64 bit integer, the numerical - /// value is truncated to the lowest 64 bits of the value's binary - /// representation, interpreted as a 64-bit two's complement integer. - /// - /// The [source] string must contain a sequence of base-[radix] digits (using - /// letters from `a` to `z` as digits with values 10 through 25 for radixes - /// above 10), possibly prefixed by a `-` sign. - /// - /// Returns `null` if the input is not recognized as a valid integer numeral. - static Int64? tryParseRadix(String source, int radix) => - Int64Impl.parseRadix(source, u.validateRadix(radix), false); - - /// Parses [source] as a hexadecimal numeral. - /// - /// Returns an [Int64] with the numerical value of [source]. If the numerical - /// value of [source] does not fit in a signed 64 bit integer, the numerical - /// value is truncated to the lowest 64 bits of the value's binary - /// representation, interpreted as a 64-bit two's complement integer. - /// - /// The [source] string must contain a sequence of hexadecimal digits - /// (`0`-`9`, `a`-`f` or `A`-`F`), possibly prefixed by a `-` sign. - /// - /// Throws a [FormatException] if the input is not a valid hexadecimal - /// integer numeral. - static Int64 parseHex(String source) => - Int64Impl.parseRadix(source, 16, true)!; - - /// Parses [source] as a hexadecimal numeral. - /// - /// Returns an [Int64] with the numerical value of [source]. If the numerical - /// value of [source] does not fit in a signed 64 bit integer, the numerical - /// value is truncated to the lowest 64 bits of the value's binary - /// representation, interpreted as a 64-bit two's complement integer. - /// - /// The [source] string must contain a sequence of hexadecimal digits - /// (`0`-`9`, `a`-`f` or `A`-`F`), possibly prefixed by a `-` sign. - /// - /// Returns `null` if the input is not a valid hexadecimal integer numeral. - static Int64? tryParseHex(String source) => - Int64Impl.parseRadix(source, 16, false); - - String toRadixStringUnsigned(int radix); - - /// Returns the digits of `this` when interpreted as an unsigned 64-bit value. - String toStringUnsigned(); - - @override - Int64 operator +(Object other); - - @override - Int64 operator -(Object other); - - @override - Int64 operator -(); - - @override - Int64 operator *(Object other); - - @override - Int64 operator %(Object other); - - @override - Int64 operator ~/(Object other); - - @override - Int64 remainder(Object other); - - @override - Int64 operator &(Object other); - - @override - Int64 operator |(Object other); - - @override - Int64 operator ^(Object other); - - @override - Int64 operator ~(); - - @override - Int64 operator <<(int shiftAmount); - - @override - Int64 operator >>(int shiftAmount); - - @override - Int64 shiftRightUnsigned(int shiftAmount); - - @override - Int64 abs(); - - @override - Int64 clamp(Object lowerLimit, Object upperLimit); - - @override - Int64 toSigned(int width); - - /// Returns whether this [Int64] has the same numeric value as the given - /// object. The argument may be an [int] or an [IntX]. - @override - bool operator ==(Object other); - - /// Returns a hash code based on the numeric value. - @override - int get hashCode; -} +export 'int64_native.dart' if (dart.library.html) 'int64_emulated.dart'; diff --git a/lib/src/int64_emulated.dart b/lib/src/int64_emulated.dart index 1295cab..ecf8630 100644 --- a/lib/src/int64_emulated.dart +++ b/lib/src/int64_emulated.dart @@ -4,16 +4,14 @@ // ignore_for_file: constant_identifier_names -// Many locals are declared as `int` or `double`. We keep local variable types -// because the types are critical to the efficiency of many operations. -// -// ignore_for_file: omit_local_variable_types +// Conditional import in `int64.dart` confuses analyzer. +// ignore_for_file: invalid_override import 'int32.dart'; -import 'int64.dart'; +import 'intx.dart'; import 'utilities.dart' as u; -class Int64Impl implements Int64 { +class Int64 implements IntX { // A 64-bit integer is represented internally as three non-negative // integers, storing the 22 low, 22 middle, and 20 high bits of the // 64-bit value. _l (low) and _m (middle) are in the range @@ -36,21 +34,35 @@ class Int64Impl implements Int64 { static const int _SIGN_BIT = 19; // _BITS2 - 1 static const int _SIGN_BIT_MASK = 1 << _SIGN_BIT; - static const Int64Impl MAX_VALUE = Int64Impl._bits(_MASK, _MASK, _MASK2 >> 1); + static const Int64 MAX_VALUE = Int64._bits(_MASK, _MASK, _MASK2 >> 1); - static const Int64Impl MIN_VALUE = Int64Impl._bits(0, 0, _SIGN_BIT_MASK); + static const Int64 MIN_VALUE = Int64._bits(0, 0, _SIGN_BIT_MASK); - static const Int64Impl ZERO = Int64Impl._bits(0, 0, 0); + static const Int64 ZERO = Int64._bits(0, 0, 0); - static const Int64Impl ONE = Int64Impl._bits(1, 0, 0); + static const Int64 ONE = Int64._bits(1, 0, 0); - static const Int64Impl TWO = Int64Impl._bits(2, 0, 0); + static const Int64 TWO = Int64._bits(2, 0, 0); - /// Constructs an [Int64Impl] with a given bitwise representation. No + /// Constructs an [Int64] with a given bitwise representation. No /// validation is performed. - const Int64Impl._bits(this._l, this._m, this._h); + const Int64._bits(this._l, this._m, this._h); - static Int64Impl? parseRadix(String s, int radix, bool throwOnError) { + static Int64 parseInt(String source) => _parseRadix(source, 10, true)!; + + static Int64? tryParseInt(String source) => _parseRadix(source, 10, false); + + static Int64 parseRadix(String source, int radix) => + _parseRadix(source, u.validateRadix(radix), true)!; + + static Int64? tryParseRadix(String source, int radix) => + _parseRadix(source, u.validateRadix(radix), false); + + static Int64 parseHex(String source) => _parseRadix(source, 16, true)!; + + static Int64? tryParseHex(String source) => _parseRadix(source, 16, false); + + static Int64? _parseRadix(String s, int radix, bool throwOnError) { int i = 0; bool negative = false; if (s.startsWith('-')) { @@ -88,10 +100,10 @@ class Int64Impl implements Int64 { if (negative) return _negate(d0, d1, d2); - return Int64Impl._masked(d0, d1, d2); + return Int64._masked(d0, d1, d2); } - factory Int64Impl([int value = 0]) { + factory Int64([int value = 0]) { int v0 = 0, v1 = 0, v2 = 0; bool negative = false; if (value < 0) { @@ -107,11 +119,11 @@ class Int64Impl implements Int64 { v0 = value; return negative - ? Int64Impl._negate(_MASK & v0, _MASK & v1, _MASK2 & v2) - : Int64Impl._masked(v0, v1, v2); + ? Int64._negate(_MASK & v0, _MASK & v1, _MASK2 & v2) + : Int64._masked(v0, v1, v2); } - factory Int64Impl.fromBytes(List bytes) { + factory Int64.fromBytes(List bytes) { // 20 bits into top, 22 into middle and bottom. var split1 = bytes[5] & 0xFF; var high = @@ -123,10 +135,10 @@ class Int64Impl implements Int64 { (split2 >> 6); var low = (split2 << 16) | ((bytes[1] & 0xFF) << 8) | (bytes[0] & 0xFF); // Top bits from above will be masked off here. - return Int64Impl._masked(low, middle, high); + return Int64._masked(low, middle, high); } - factory Int64Impl.fromBytesBigEndian(List bytes) { + factory Int64.fromBytesBigEndian(List bytes) { var split1 = bytes[2] & 0xFF; var high = ((bytes[0] & 0xFF) << 12) | ((bytes[1] & 0xFF) << 4) | (split1 >> 4); @@ -137,52 +149,52 @@ class Int64Impl implements Int64 { (split2 >> 6); var low = (split2 << 16) | ((bytes[6] & 0xFF) << 8) | (bytes[7] & 0xFF); // Top bits from above will be masked off here. - return Int64Impl._masked(low, middle, high); + return Int64._masked(low, middle, high); } - factory Int64Impl.fromInts(int top, int bottom) { + factory Int64.fromInts(int top, int bottom) { top &= 0xffffffff; bottom &= 0xffffffff; int d0 = _MASK & bottom; int d1 = ((0xfff & top) << 10) | (0x3ff & (bottom >> _BITS)); int d2 = _MASK2 & (top >> 12); - return Int64Impl._masked(d0, d1, d2); + return Int64._masked(d0, d1, d2); } - // Returns the [Int64Impl] representation of the specified value. Throws + // Returns the [Int64] representation of the specified value. Throws // [ArgumentError] for non-integer arguments. - static Int64Impl _promote(value) { - if (value is Int64Impl) { + static Int64 _promote(value) { + if (value is Int64) { return value; } else if (value is int) { - return Int64Impl(value); + return Int64(value); } else if (value is Int32) { - return value.toInt64() as Int64Impl; + return value.toInt64() as Int64; } throw ArgumentError.value(value, 'other', 'not an int, Int32 or Int64'); } @override - Int64Impl operator +(Object other) { - Int64Impl o = _promote(other); + Int64 operator +(Object other) { + Int64 o = _promote(other); int sum0 = _l + o._l; int sum1 = _m + o._m + (sum0 >> _BITS); int sum2 = _h + o._h + (sum1 >> _BITS); - return Int64Impl._masked(sum0, sum1, sum2); + return Int64._masked(sum0, sum1, sum2); } @override - Int64Impl operator -(Object other) { - Int64Impl o = _promote(other); + Int64 operator -(Object other) { + Int64 o = _promote(other); return _sub(_l, _m, _h, o._l, o._m, o._h); } @override - Int64Impl operator -() => _negate(_l, _m, _h); + Int64 operator -() => _negate(_l, _m, _h); @override - Int64Impl operator *(Object other) { - Int64Impl o = _promote(other); + Int64 operator *(Object other) { + Int64 o = _promote(other); // Grab 13-bit chunks. int a0 = _l & 0x1fff; @@ -259,50 +271,50 @@ class Int64Impl implements Int64 { c1 += c0 >> _BITS; c2 += c1 >> _BITS; - return Int64Impl._masked(c0, c1, c2); + return Int64._masked(c0, c1, c2); } @override - Int64Impl operator %(Object other) => _divide(this, other, _RETURN_MOD); + Int64 operator %(Object other) => _divide(this, other, _RETURN_MOD); @override - Int64Impl operator ~/(Object other) => _divide(this, other, _RETURN_DIV); + Int64 operator ~/(Object other) => _divide(this, other, _RETURN_DIV); @override - Int64Impl remainder(Object other) => _divide(this, other, _RETURN_REM); + Int64 remainder(Object other) => _divide(this, other, _RETURN_REM); @override - Int64Impl operator &(Object other) { - Int64Impl o = _promote(other); + Int64 operator &(Object other) { + Int64 o = _promote(other); int a0 = _l & o._l; int a1 = _m & o._m; int a2 = _h & o._h; - return Int64Impl._masked(a0, a1, a2); + return Int64._masked(a0, a1, a2); } @override - Int64Impl operator |(Object other) { - Int64Impl o = _promote(other); + Int64 operator |(Object other) { + Int64 o = _promote(other); int a0 = _l | o._l; int a1 = _m | o._m; int a2 = _h | o._h; - return Int64Impl._masked(a0, a1, a2); + return Int64._masked(a0, a1, a2); } @override - Int64Impl operator ^(Object other) { - Int64Impl o = _promote(other); + Int64 operator ^(Object other) { + Int64 o = _promote(other); int a0 = _l ^ o._l; int a1 = _m ^ o._m; int a2 = _h ^ o._h; - return Int64Impl._masked(a0, a1, a2); + return Int64._masked(a0, a1, a2); } @override - Int64Impl operator ~() => Int64Impl._masked(~_l, ~_m, ~_h); + Int64 operator ~() => Int64._masked(~_l, ~_m, ~_h); @override - Int64Impl operator <<(int n) { + Int64 operator <<(int n) { if (n < 0) { throw ArgumentError.value(n); } @@ -325,16 +337,16 @@ class Int64Impl implements Int64 { res2 = _l << (n - _BITS01); } - return Int64Impl._masked(res0, res1, res2); + return Int64._masked(res0, res1, res2); } @override - Int64Impl operator >>(int n) { + Int64 operator >>(int n) { if (n < 0) { throw ArgumentError.value(n); } if (n >= 64) { - return isNegative ? const Int64Impl._bits(_MASK, _MASK, _MASK2) : ZERO; + return isNegative ? const Int64._bits(_MASK, _MASK, _MASK2) : ZERO; } int res0, res1, res2; @@ -371,11 +383,11 @@ class Int64Impl implements Int64 { } } - return Int64Impl._masked(res0, res1, res2); + return Int64._masked(res0, res1, res2); } @override - Int64Impl shiftRightUnsigned(int n) { + Int64 shiftRightUnsigned(int n) { if (n < 0) { throw ArgumentError.value(n); } @@ -399,22 +411,22 @@ class Int64Impl implements Int64 { res0 = a2 >> (n - _BITS01); } - return Int64Impl._masked(res0, res1, res2); + return Int64._masked(res0, res1, res2); } @override bool operator ==(Object other) { - Int64Impl? o; - if (other is Int64Impl) { + Int64? o; + if (other is Int64) { o = other; } else if (other is int) { if (_h == 0 && _m == 0) return _l == other; // Since we know one of [_h] or [_m] is non-zero, if [other] fits in the // low word then it can't be numerically equal. if ((_MASK & other) == other) return false; - o = Int64Impl(other); + o = Int64(other); } else if (other is Int32) { - o = other.toInt64() as Int64Impl; + o = other.toInt64() as Int64; } if (o != null) { return _l == o._l && _m == o._m && _h == o._h; @@ -426,7 +438,7 @@ class Int64Impl implements Int64 { int compareTo(Object other) => _compareTo(other); int _compareTo(Object other) { - Int64Impl o = _promote(other); + Int64 o = _promote(other); int signa = _h >> (_BITS2 - 1); int signb = o._h >> (_BITS2 - 1); if (signa != signb) { @@ -497,19 +509,19 @@ class Int64Impl implements Int64 { @override int get hashCode { // TODO(sra): Should we ensure that hashCode values match corresponding int? - // i.e. should `new Int64Impl(x).hashCode == x.hashCode`? + // i.e. should `new Int64(x).hashCode == x.hashCode`? int bottom = ((_m & 0x3ff) << _BITS) | _l; int top = (_h << 12) | ((_m >> 10) & 0xfff); return bottom ^ top; } @override - Int64Impl abs() => isNegative ? -this : this; + Int64 abs() => isNegative ? -this : this; @override - Int64Impl clamp(Object lowerLimit, Object upperLimit) { - Int64Impl lower = _promote(lowerLimit); - Int64Impl upper = _promote(upperLimit); + Int64 clamp(Object lowerLimit, Object upperLimit) { + Int64 lower = _promote(lowerLimit); + Int64 upper = _promote(upperLimit); if (this < lower) return lower; if (this > upper) return upper; return this; @@ -551,35 +563,35 @@ class Int64Impl implements Int64 { } @override - Int64Impl toSigned(int width) { + Int64 toSigned(int width) { if (width < 1 || width > 64) throw RangeError.range(width, 1, 64); if (width > _BITS01) { - return Int64Impl._masked(_l, _m, _h.toSigned(width - _BITS01)); + return Int64._masked(_l, _m, _h.toSigned(width - _BITS01)); } else if (width > _BITS) { int m = _m.toSigned(width - _BITS); return m.isNegative - ? Int64Impl._masked(_l, m, _MASK2) - : Int64Impl._masked(_l, m, 0); // Masking for type inferrer. + ? Int64._masked(_l, m, _MASK2) + : Int64._masked(_l, m, 0); // Masking for type inferrer. } else { int l = _l.toSigned(width); return l.isNegative - ? Int64Impl._masked(l, _MASK, _MASK2) - : Int64Impl._masked(l, 0, 0); // Masking for type inferrer. + ? Int64._masked(l, _MASK, _MASK2) + : Int64._masked(l, 0, 0); // Masking for type inferrer. } } @override - Int64Impl toUnsigned(int width) { + Int64 toUnsigned(int width) { if (width < 0 || width > 64) throw RangeError.range(width, 0, 64); if (width > _BITS01) { int h = _h.toUnsigned(width - _BITS01); - return Int64Impl._masked(_l, _m, h); + return Int64._masked(_l, _m, h); } else if (width > _BITS) { int m = _m.toUnsigned(width - _BITS); - return Int64Impl._masked(_l, m, 0); + return Int64._masked(_l, m, 0); } else { int l = _l.toUnsigned(width); - return Int64Impl._masked(l, 0, 0); + return Int64._masked(l, 0, 0); } } @@ -621,7 +633,7 @@ class Int64Impl implements Int64 { Int32 toInt32() => Int32(((_m & 0x3ff) << _BITS) | _l); @override - Int64Impl toInt64() => this; + Int64 toInt64() => this; @override String toString() => _toRadixString(10); @@ -629,7 +641,7 @@ class Int64Impl implements Int64 { @override String toHexString() { if (isZero) return '0'; - Int64Impl x = this; + Int64 x = this; String hexStr = ''; while (!x.isZero) { int digit = x._l & 0xf; @@ -639,11 +651,9 @@ class Int64Impl implements Int64 { return hexStr; } - @override @pragma('dart2js:noInline') String toStringUnsigned() => _toRadixStringUnsigned(10, _l, _m, _h, ''); - @override @pragma('dart2js:noInline') String toRadixStringUnsigned(int radix) => _toRadixStringUnsigned(u.validateRadix(radix), _l, _m, _h, ''); @@ -815,17 +825,17 @@ class Int64Impl implements Int64 { String toDebugString() => 'Int64[_l=$_l, _m=$_m, _h=$_h]'; - static Int64Impl _masked(int low, int medium, int high) => - Int64Impl._bits(_MASK & low, _MASK & medium, _MASK2 & high); + static Int64 _masked(int low, int medium, int high) => + Int64._bits(_MASK & low, _MASK & medium, _MASK2 & high); - static Int64Impl _sub(int a0, int a1, int a2, int b0, int b1, int b2) { + static Int64 _sub(int a0, int a1, int a2, int b0, int b1, int b2) { int diff0 = a0 - b0; int diff1 = a1 - b1 - ((diff0 >> _BITS) & 1); int diff2 = a2 - b2 - ((diff1 >> _BITS) & 1); return _masked(diff0, diff1, diff2); } - static Int64Impl _negate(int b0, int b1, int b2) => _sub(0, 0, 0, b0, b1, b2); + static Int64 _negate(int b0, int b1, int b2) => _sub(0, 0, 0, b0, b1, b2); String _hexDigit(int digit) => '0123456789ABCDEF'[digit]; @@ -844,8 +854,8 @@ class Int64Impl implements Int64 { // Implementation of '~/', '%' and 'remainder'. - static Int64Impl _divide(Int64Impl a, other, int what) { - Int64Impl b = _promote(other); + static Int64 _divide(Int64 a, other, int what) { + Int64 b = _promote(other); if (b.isZero) { throw UnsupportedError('Division by zero'); } @@ -870,7 +880,7 @@ class Int64Impl implements Int64 { static const _RETURN_REM = 2; static const _RETURN_MOD = 3; - static Int64Impl _divideHelper( + static Int64 _divideHelper( // up to 64 bits unsigned in a2/a1/a0 and b2/b1/b0 int a0, int a1, @@ -977,18 +987,18 @@ class Int64Impl implements Int64 { } // 0 <= R < B - assert(Int64Impl.ZERO <= Int64Impl._bits(r0, r1, r2)); + assert(Int64.ZERO <= Int64._bits(r0, r1, r2)); assert(r2 < b2 || // Handles case where B = -(MIN_VALUE) - Int64Impl._bits(r0, r1, r2) < Int64Impl._bits(b0, b1, b2)); + Int64._bits(r0, r1, r2) < Int64._bits(b0, b1, b2)); assert(what == _RETURN_DIV || what == _RETURN_MOD || what == _RETURN_REM); if (what == _RETURN_DIV) { if (aNeg != bNeg) return _negate(q0, q1, q2); - return Int64Impl._masked(q0, q1, q2); // Masking for type inferrer. + return Int64._masked(q0, q1, q2); // Masking for type inferrer. } if (!aNeg) { - return Int64Impl._masked(r0, r1, r2); // Masking for type inferrer. + return Int64._masked(r0, r1, r2); // Masking for type inferrer. } if (what == _RETURN_MOD) { diff --git a/lib/src/int64_native.dart b/lib/src/int64_native.dart index 60d46b3..9e3da86 100644 --- a/lib/src/int64_native.dart +++ b/lib/src/int64_native.dart @@ -5,39 +5,49 @@ // ignore_for_file: constant_identifier_names import 'int32.dart'; -import 'int64.dart'; +import 'intx.dart'; import 'utilities.dart' as u; -class Int64Impl implements Int64 { +/// An immutable 64-bit signed integer, in the range `[-2^63, 2^63 - 1]`. +/// Arithmetic operations may overflow in order to maintain this range. +class Int64 implements IntX { final int _i; - static const Int64Impl MAX_VALUE = Int64Impl(9223372036854775807); + /// The maximum positive value attainable by an [Int64], namely + /// 9,223,372,036,854,775,807. + static const Int64 MAX_VALUE = Int64(9223372036854775807); - static const Int64Impl MIN_VALUE = Int64Impl(-9223372036854775808); + /// The minimum positive value attainable by an [Int64], namely + /// -9,223,372,036,854,775,808. + static const Int64 MIN_VALUE = Int64(-9223372036854775808); - static const Int64Impl ZERO = Int64Impl(0); + /// An [Int64] constant equal to 0. + static const Int64 ZERO = Int64(0); - static const Int64Impl ONE = Int64Impl(1); + /// An [Int64] constant equal to 1. + static const Int64 ONE = Int64(1); - static const Int64Impl TWO = Int64Impl(2); + /// An [Int64] constant equal to 2. + static const Int64 TWO = Int64(2); - const Int64Impl([int value = 0]) : _i = value; + const Int64([int value = 0]) : _i = value; - factory Int64Impl.fromInts(int top, int bottom) => - Int64Impl((top << 32) | (bottom & 0xFFFFFFFF)); + /// Constructs an [Int64] from a pair of 32-bit integers having the value + /// [:((high & 0xffffffff) << 32) | (low & 0xffffffff):]. + factory Int64.fromInts(int high, int low) => + Int64((high << 32) | (low & 0xFFFFFFFF)); - factory Int64Impl.fromBytes(List bytes) => - Int64Impl(((bytes[7] & 0xFF) << 56) | - ((bytes[6] & 0xFF) << 48) | - ((bytes[5] & 0xFF) << 40) | - ((bytes[4] & 0xFF) << 32) | - ((bytes[3] & 0xFF) << 24) | - ((bytes[2] & 0xFF) << 16) | - ((bytes[1] & 0xFF) << 8) | - (bytes[0] & 0xFF)); + factory Int64.fromBytes(List bytes) => Int64(((bytes[7] & 0xFF) << 56) | + ((bytes[6] & 0xFF) << 48) | + ((bytes[5] & 0xFF) << 40) | + ((bytes[4] & 0xFF) << 32) | + ((bytes[3] & 0xFF) << 24) | + ((bytes[2] & 0xFF) << 16) | + ((bytes[1] & 0xFF) << 8) | + (bytes[0] & 0xFF)); - factory Int64Impl.fromBytesBigEndian(List bytes) => - Int64Impl(((bytes[0] & 0xFF) << 56) | + factory Int64.fromBytesBigEndian(List bytes) => + Int64(((bytes[0] & 0xFF) << 56) | ((bytes[1] & 0xFF) << 48) | ((bytes[2] & 0xFF) << 40) | ((bytes[3] & 0xFF) << 32) | @@ -46,7 +56,92 @@ class Int64Impl implements Int64 { ((bytes[6] & 0xFF) << 8) | (bytes[7] & 0xFF)); - static Int64Impl? parseRadix(String s, int radix, bool throwOnError) { + /// Parses [source] as a decimal numeral. + /// + /// Returns an [Int64] with the numerical value of [source]. If the numerical + /// value of [source] does not fit in a signed 64 bit integer, the numerical + /// value is truncated to the lowest 64 bits of the value's binary + /// representation, interpreted as a 64-bit two's complement integer. + /// + /// The [source] string must contain a sequence of digits (`0`-`9`), possibly + /// prefixed by a `-` sign. + /// + /// Throws a [FormatException] if the input is not a valid decimal integer + /// numeral. + static Int64 parseInt(String source) => _parseRadix(source, 10, true)!; + + /// Parses [source] as a decimal numeral. + /// + /// Returns an [Int64] with the numerical value of [source]. If the numerical + /// value of [source] does not fit in a signed 64 bit integer, the numerical + /// value is truncated to the lowest 64 bits of the value's binary + /// representation, interpreted as a 64-bit two's complement integer. + /// + /// The [source] string must contain a sequence of digits (`0`-`9`), possibly + /// prefixed by a `-` sign. + /// + /// Returns `null` if the input is not a valid decimal integer numeral. + static Int64? tryParseInt(String source) => _parseRadix(source, 10, false); + + /// Parses [source] in a given [radix] between 2 and 36. + /// + /// Returns an [Int64] with the numerical value of [source]. If the numerical + /// value of [source] does not fit in a signed 64 bit integer, the numerical + /// value is truncated to the lowest 64 bits of the value's binary + /// representation, interpreted as a 64-bit two's complement integer. + /// + /// The [source] string must contain a sequence of base-[radix] digits (using + /// letters from `a` to `z` as digits with values 10 through 25 for radixes + /// above 10), possibly prefixed by a `-` sign. + /// + /// Throws a [FormatException] if the input is not recognized as a valid + /// integer numeral. + static Int64 parseRadix(String source, int radix) => + _parseRadix(source, u.validateRadix(radix), true)!; + + /// Parses [source] in a given [radix] between 2 and 36. + /// + /// Returns an [Int64] with the numerical value of [source]. If the numerical + /// value of [source] does not fit in a signed 64 bit integer, the numerical + /// value is truncated to the lowest 64 bits of the value's binary + /// representation, interpreted as a 64-bit two's complement integer. + /// + /// The [source] string must contain a sequence of base-[radix] digits (using + /// letters from `a` to `z` as digits with values 10 through 25 for radixes + /// above 10), possibly prefixed by a `-` sign. + /// + /// Returns `null` if the input is not recognized as a valid integer numeral. + static Int64? tryParseRadix(String source, int radix) => + _parseRadix(source, u.validateRadix(radix), false); + + /// Parses [source] as a hexadecimal numeral. + /// + /// Returns an [Int64] with the numerical value of [source]. If the numerical + /// value of [source] does not fit in a signed 64 bit integer, the numerical + /// value is truncated to the lowest 64 bits of the value's binary + /// representation, interpreted as a 64-bit two's complement integer. + /// + /// The [source] string must contain a sequence of hexadecimal digits + /// (`0`-`9`, `a`-`f` or `A`-`F`), possibly prefixed by a `-` sign. + /// + /// Throws a [FormatException] if the input is not a valid hexadecimal + /// integer numeral. + static Int64 parseHex(String source) => _parseRadix(source, 16, true)!; + + /// Parses [source] as a hexadecimal numeral. + /// + /// Returns an [Int64] with the numerical value of [source]. If the numerical + /// value of [source] does not fit in a signed 64 bit integer, the numerical + /// value is truncated to the lowest 64 bits of the value's binary + /// representation, interpreted as a 64-bit two's complement integer. + /// + /// The [source] string must contain a sequence of hexadecimal digits + /// (`0`-`9`, `a`-`f` or `A`-`F`), possibly prefixed by a `-` sign. + /// + /// Returns `null` if the input is not a valid hexadecimal integer numeral. + static Int64? tryParseHex(String source) => _parseRadix(source, 16, false); + + static Int64? _parseRadix(String s, int radix, bool throwOnError) { int charIdx = 0; bool negative = false; if (s.startsWith('-')) { @@ -72,14 +167,14 @@ class Int64Impl implements Int64 { } if (negative) { - return Int64Impl(-i); + return Int64(-i); } - return Int64Impl(i); + return Int64(i); } static int _promote(Object value) { - if (value is Int64Impl) { + if (value is Int64) { return value._i; } else if (value is int) { return value; @@ -90,47 +185,46 @@ class Int64Impl implements Int64 { } @override - Int64Impl operator +(Object other) => Int64Impl(_i + _promote(other)); + Int64 operator +(Object other) => Int64(_i + _promote(other)); @override - Int64Impl operator -(Object other) => Int64Impl(_i - _promote(other)); + Int64 operator -(Object other) => Int64(_i - _promote(other)); @override - Int64Impl operator -() => Int64Impl(-_i); + Int64 operator -() => Int64(-_i); @override - Int64Impl operator *(Object other) => Int64Impl(_i * _promote(other)); + Int64 operator *(Object other) => Int64(_i * _promote(other)); @override - Int64Impl operator %(Object other) => Int64Impl(_i % _promote(other)); + Int64 operator %(Object other) => Int64(_i % _promote(other)); @override - Int64Impl operator ~/(Object other) => Int64Impl(_i ~/ _promote(other)); + Int64 operator ~/(Object other) => Int64(_i ~/ _promote(other)); @override - Int64Impl remainder(Object other) => Int64Impl(_i.remainder(_promote(other))); + Int64 remainder(Object other) => Int64(_i.remainder(_promote(other))); @override - Int64Impl operator &(Object other) => Int64Impl(_i & _promote(other)); + Int64 operator &(Object other) => Int64(_i & _promote(other)); @override - Int64Impl operator |(Object other) => Int64Impl(_i | _promote(other)); + Int64 operator |(Object other) => Int64(_i | _promote(other)); @override - Int64Impl operator ^(Object other) => Int64Impl(_i ^ _promote(other)); + Int64 operator ^(Object other) => Int64(_i ^ _promote(other)); @override - Int64Impl operator ~() => Int64Impl(~_i); + Int64 operator ~() => Int64(~_i); @override - Int64Impl operator <<(int shiftAmount) => Int64Impl(_i << shiftAmount); + Int64 operator <<(int shiftAmount) => Int64(_i << shiftAmount); @override - Int64Impl operator >>(int shiftAmount) => Int64Impl(_i >> shiftAmount); + Int64 operator >>(int shiftAmount) => Int64(_i >> shiftAmount); @override - Int64Impl shiftRightUnsigned(int shiftAmount) => - Int64Impl(_i >>> shiftAmount); + Int64 shiftRightUnsigned(int shiftAmount) => Int64(_i >>> shiftAmount); @override int compareTo(Object other) => _i.compareTo(_promote(other)); @@ -168,9 +262,12 @@ class Int64Impl implements Int64 { @override int get bitLength => _i.bitLength; + /// Returns a hash code based on the numeric value. @override int get hashCode => _i.hashCode; + /// Returns whether this [Int64] has the same numeric value as the given + /// object. The argument may be an [int] or an [IntX]. @override bool operator ==(Object other) => _i == _promote(other); @@ -243,10 +340,8 @@ class Int64Impl implements Int64 { @override String toRadixString(int radix) => _i.toRadixString(radix); - @override String toRadixStringUnsigned(int radix) => _toRadixStringUnsigned(_i, radix); - @override String toStringUnsigned() => _toRadixStringUnsigned(_i, 10); static String _toRadixStringUnsigned(int value, int radix) {