Index: sdk/lib/_internal/compiler/js_lib/js_number.dart |
diff --git a/sdk/lib/_internal/compiler/js_lib/js_number.dart b/sdk/lib/_internal/compiler/js_lib/js_number.dart |
deleted file mode 100644 |
index b340247a59fa3f338ba2c5bc115c51b4574db8df..0000000000000000000000000000000000000000 |
--- a/sdk/lib/_internal/compiler/js_lib/js_number.dart |
+++ /dev/null |
@@ -1,561 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// 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. |
- |
-part of _interceptors; |
- |
-/** |
- * The super interceptor class for [JSInt] and [JSDouble]. The compiler |
- * recognizes this class as an interceptor, and changes references to |
- * [:this:] to actually use the receiver of the method, which is |
- * generated as an extra argument added to each member. |
- * |
- * Note that none of the methods here delegate to a method defined on JSInt or |
- * JSDouble. This is exploited in [tryComputeConstantInterceptor]. |
- */ |
-class JSNumber extends Interceptor implements num { |
- const JSNumber(); |
- |
- int compareTo(num b) { |
- if (b is! num) throw argumentErrorValue(b); |
- if (this < b) { |
- return -1; |
- } else if (this > b) { |
- return 1; |
- } else if (this == b) { |
- if (this == 0) { |
- bool bIsNegative = b.isNegative; |
- if (isNegative == bIsNegative) return 0; |
- if (isNegative) return -1; |
- return 1; |
- } |
- return 0; |
- } else if (isNaN) { |
- if (b.isNaN) { |
- return 0; |
- } |
- return 1; |
- } else { |
- return -1; |
- } |
- } |
- |
- bool get isNegative => (this == 0) ? (1 / this) < 0 : this < 0; |
- |
- bool get isNaN => JS('bool', r'isNaN(#)', this); |
- |
- bool get isInfinite { |
- return JS('bool', r'# == (1/0)', this) |
- || JS('bool', r'# == (-1/0)', this); |
- } |
- |
- bool get isFinite => JS('bool', r'isFinite(#)', this); |
- |
- num remainder(num b) { |
- if (b is! num) throw argumentErrorValue(b); |
- return JS('num', r'# % #', this, b); |
- } |
- |
- num abs() => JS('returns:num;effects:none;depends:none;throws:never', |
- r'Math.abs(#)', this); |
- |
- num get sign => this > 0 ? 1 : this < 0 ? -1 : this; |
- |
- static const int _MIN_INT32 = -0x80000000; |
- static const int _MAX_INT32 = 0x7FFFFFFF; |
- |
- int toInt() { |
- if (this >= _MIN_INT32 && this <= _MAX_INT32) { |
- return JS('int', '# | 0', this); |
- } |
- if (JS('bool', r'isFinite(#)', this)) { |
- return JS('int', r'# + 0', truncateToDouble()); // Converts -0.0 to +0.0. |
- } |
- // This is either NaN, Infinity or -Infinity. |
- throw new UnsupportedError(JS("String", '"" + #', this)); |
- } |
- |
- int truncate() => toInt(); |
- |
- int ceil() => ceilToDouble().toInt(); |
- |
- int floor() => floorToDouble().toInt(); |
- |
- int round() { |
- if (this > 0) { |
- // This path excludes the special cases -0.0, NaN and -Infinity, leaving |
- // only +Infinity, for which a direct test is faster than [isFinite]. |
- if (JS('bool', r'# !== (1/0)', this)) { |
- return JS('int', r'Math.round(#)', this); |
- } |
- } else if (JS('bool', '# > (-1/0)', this)) { |
- // This test excludes NaN and -Infinity, leaving only -0.0. |
- // |
- // Subtraction from zero rather than negation forces -0.0 to 0.0 so code |
- // inside Math.round and code to handle result never sees -0.0, which on |
- // some JavaScript VMs can be a slow path. |
- return JS('int', r'0 - Math.round(0 - #)', this); |
- } |
- // This is either NaN, Infinity or -Infinity. |
- throw new UnsupportedError(JS("String", '"" + #', this)); |
- } |
- |
- double ceilToDouble() => JS('num', r'Math.ceil(#)', this); |
- |
- double floorToDouble() => JS('num', r'Math.floor(#)', this); |
- |
- double roundToDouble() { |
- if (this < 0) { |
- return JS('num', r'-Math.round(-#)', this); |
- } else { |
- return JS('num', r'Math.round(#)', this); |
- } |
- } |
- |
- double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble(); |
- |
- num clamp(lowerLimit, upperLimit) { |
- if (lowerLimit is! num) throw argumentErrorValue(lowerLimit); |
- if (upperLimit is! num) throw argumentErrorValue(upperLimit); |
- if (lowerLimit.compareTo(upperLimit) > 0) { |
- throw argumentErrorValue(lowerLimit); |
- } |
- if (this.compareTo(lowerLimit) < 0) return lowerLimit; |
- if (this.compareTo(upperLimit) > 0) return upperLimit; |
- return this; |
- } |
- |
- // The return type is intentionally omitted to avoid type checker warnings |
- // from assigning JSNumber to double. |
- toDouble() => this; |
- |
- String toStringAsFixed(int fractionDigits) { |
- checkInt(fractionDigits); |
- if (fractionDigits < 0 || fractionDigits > 20) { |
- throw new RangeError(fractionDigits); |
- } |
- String result = JS('String', r'#.toFixed(#)', this, fractionDigits); |
- if (this == 0 && isNegative) return "-$result"; |
- return result; |
- } |
- |
- String toStringAsExponential([int fractionDigits]) { |
- String result; |
- if (fractionDigits != null) { |
- checkInt(fractionDigits); |
- if (fractionDigits < 0 || fractionDigits > 20) { |
- throw new RangeError(fractionDigits); |
- } |
- result = JS('String', r'#.toExponential(#)', this, fractionDigits); |
- } else { |
- result = JS('String', r'#.toExponential()', this); |
- } |
- if (this == 0 && isNegative) return "-$result"; |
- return result; |
- } |
- |
- String toStringAsPrecision(int precision) { |
- checkInt(precision); |
- if (precision < 1 || precision > 21) { |
- throw new RangeError(precision); |
- } |
- String result = JS('String', r'#.toPrecision(#)', |
- this, precision); |
- if (this == 0 && isNegative) return "-$result"; |
- return result; |
- } |
- |
- String toRadixString(int radix) { |
- checkInt(radix); |
- if (radix < 2 || radix > 36) { |
- throw new RangeError.range(radix, 2, 36, "radix"); |
- } |
- String result = JS('String', r'#.toString(#)', this, radix); |
- const int rightParenCode = 0x29; |
- if (result.codeUnitAt(result.length - 1) != rightParenCode) { |
- return result; |
- } |
- return _handleIEtoString(result); |
- } |
- |
- static String _handleIEtoString(String result) { |
- // Result is probably IE's untraditional format for large numbers, |
- // e.g., "8.0000000000008(e+15)" for 0x8000000000000800.toString(16). |
- var match = JS('List|Null', |
- r'/^([\da-z]+)(?:\.([\da-z]+))?\(e\+(\d+)\)$/.exec(#)', |
- result); |
- if (match == null) { |
- // Then we don't know how to handle it at all. |
- throw new UnsupportedError("Unexpected toString result: $result"); |
- } |
- String result = JS('String', '#', match[1]); |
- int exponent = JS("int", "+#", match[3]); |
- if (match[2] != null) { |
- result = JS('String', '# + #', result, match[2]); |
- exponent -= JS('int', '#.length', match[2]); |
- } |
- return result + "0" * exponent; |
- } |
- |
- // Note: if you change this, also change the function [S]. |
- String toString() { |
- if (this == 0 && JS('bool', '(1 / #) < 0', this)) { |
- return '-0.0'; |
- } else { |
- return JS('String', r'"" + (#)', this); |
- } |
- } |
- |
- int get hashCode => JS('int', '# & 0x1FFFFFFF', this); |
- |
- num operator -() => JS('num', r'-#', this); |
- |
- num operator +(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('num', '# + #', this, other); |
- } |
- |
- num operator -(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('num', '# - #', this, other); |
- } |
- |
- num operator /(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('num', '# / #', this, other); |
- } |
- |
- num operator *(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('num', '# * #', this, other); |
- } |
- |
- num operator %(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- // Euclidean Modulo. |
- num result = JS('num', r'# % #', this, other); |
- if (result == 0) return 0; // Make sure we don't return -0.0. |
- if (result > 0) return result; |
- if (JS('num', '#', other) < 0) { |
- return result - JS('num', '#', other); |
- } else { |
- return result + JS('num', '#', other); |
- } |
- } |
- |
- bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value); |
- |
- int operator ~/(num other) { |
- if (false) _tdivFast(other); // Ensure resolution. |
- if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) { |
- return JS('int', r'(# / #) | 0', this, other); |
- } else { |
- return _tdivSlow(other); |
- } |
- } |
- |
- int _tdivFast(num other) { |
- return _isInt32(this) |
- ? JS('int', r'(# / #) | 0', this, other) |
- : (JS('num', r'# / #', this, other)).toInt(); |
- } |
- |
- int _tdivSlow(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return (JS('num', r'# / #', this, other)).toInt(); |
- } |
- |
- // TODO(ngeoffray): Move the bit operations below to [JSInt] and |
- // make them take an int. Because this will make operations slower, |
- // we define these methods on number for now but we need to decide |
- // the grain at which we do the type checks. |
- |
- num operator <<(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- if (JS('num', '#', other) < 0) throw argumentErrorValue(other); |
- return _shlPositive(other); |
- } |
- |
- num _shlPositive(num other) { |
- // JavaScript only looks at the last 5 bits of the shift-amount. Shifting |
- // by 33 is hence equivalent to a shift by 1. |
- return JS('bool', r'# > 31', other) |
- ? 0 |
- : JS('JSUInt32', r'(# << #) >>> 0', this, other); |
- } |
- |
- num operator >>(num other) { |
- if (false) _shrReceiverPositive(other); |
- if (other is !num) throw argumentErrorValue(other); |
- if (JS('num', '#', other) < 0) throw argumentErrorValue(other); |
- return _shrOtherPositive(other); |
- } |
- |
- num _shrOtherPositive(num other) { |
- return JS('num', '#', this) > 0 |
- ? _shrBothPositive(other) |
- // For negative numbers we just clamp the shift-by amount. |
- // `this` could be negative but not have its 31st bit set. |
- // The ">>" would then shift in 0s instead of 1s. Therefore |
- // we cannot simply return 0xFFFFFFFF. |
- : JS('JSUInt32', r'(# >> #) >>> 0', this, other > 31 ? 31 : other); |
- } |
- |
- num _shrReceiverPositive(num other) { |
- if (JS('num', '#', other) < 0) throw argumentErrorValue(other); |
- return _shrBothPositive(other); |
- } |
- |
- num _shrBothPositive(num other) { |
- return JS('bool', r'# > 31', other) |
- // JavaScript only looks at the last 5 bits of the shift-amount. In JS |
- // shifting by 33 is hence equivalent to a shift by 1. Shortcut the |
- // computation when that happens. |
- ? 0 |
- // Given that `this` is positive we must not use '>>'. Otherwise a |
- // number that has the 31st bit set would be treated as negative and |
- // shift in ones. |
- : JS('JSUInt32', r'# >>> #', this, other); |
- } |
- |
- num operator &(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('JSUInt32', r'(# & #) >>> 0', this, other); |
- } |
- |
- num operator |(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('JSUInt32', r'(# | #) >>> 0', this, other); |
- } |
- |
- num operator ^(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('JSUInt32', r'(# ^ #) >>> 0', this, other); |
- } |
- |
- bool operator <(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('bool', '# < #', this, other); |
- } |
- |
- bool operator >(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('bool', '# > #', this, other); |
- } |
- |
- bool operator <=(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('bool', '# <= #', this, other); |
- } |
- |
- bool operator >=(num other) { |
- if (other is !num) throw argumentErrorValue(other); |
- return JS('bool', '# >= #', this, other); |
- } |
- |
- Type get runtimeType => num; |
-} |
- |
-/** |
- * The interceptor class for [int]s. |
- * |
- * This class implements double since in JavaScript all numbers are doubles, so |
- * while we want to treat `2.0` as an integer for some operations, its |
- * interceptor should answer `true` to `is double`. |
- */ |
-class JSInt extends JSNumber implements int, double { |
- const JSInt(); |
- |
- bool get isEven => (this & 1) == 0; |
- |
- bool get isOdd => (this & 1) == 1; |
- |
- int toUnsigned(int width) { |
- return this & ((1 << width) - 1); |
- } |
- |
- int toSigned(int width) { |
- int signMask = 1 << (width - 1); |
- return (this & (signMask - 1)) - (this & signMask); |
- } |
- |
- int get bitLength { |
- int nonneg = this < 0 ? -this - 1 : this; |
- if (nonneg >= 0x100000000) { |
- nonneg = nonneg ~/ 0x100000000; |
- return _bitCount(_spread(nonneg)) + 32; |
- } |
- return _bitCount(_spread(nonneg)); |
- } |
- |
- // Returns pow(this, e) % m. |
- int modPow(int e, int m) { |
- if (e is! int) throw argumentErrorValue(e); |
- if (m is! int) throw argumentErrorValue(m); |
- if (e < 0) throw new RangeError(e); |
- if (m <= 0) throw new RangeError(m); |
- if (e == 0) return 1; |
- int b = this; |
- if (b < 0 || b > m) { |
- b %= m; |
- } |
- int r = 1; |
- while (e > 0) { |
- if (e.isOdd) { |
- r = (r * b) % m; |
- } |
- e ~/= 2; |
- b = (b * b) % m; |
- } |
- return r; |
- } |
- |
- // If inv is false, returns gcd(x, y). |
- // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1. |
- // If inv is true and gcd(x, y) != 1, throws RangeError("Not coprime"). |
- static int _binaryGcd(int x, int y, bool inv) { |
- int s = 1; |
- if (!inv) { |
- while (x.isEven && y.isEven) { |
- x ~/= 2; |
- y ~/= 2; |
- s *= 2; |
- } |
- if (y.isOdd) { |
- var t = x; |
- x = y; |
- y = t; |
- } |
- } |
- final bool ac = x.isEven; |
- int u = x; |
- int v = y; |
- int a = 1, |
- b = 0, |
- c = 0, |
- d = 1; |
- do { |
- while (u.isEven) { |
- u ~/= 2; |
- if (ac) { |
- if (!a.isEven || !b.isEven) { |
- a += y; |
- b -= x; |
- } |
- a ~/= 2; |
- } else if (!b.isEven) { |
- b -= x; |
- } |
- b ~/= 2; |
- } |
- while (v.isEven) { |
- v ~/= 2; |
- if (ac) { |
- if (!c.isEven || !d.isEven) { |
- c += y; |
- d -= x; |
- } |
- c ~/= 2; |
- } else if (!d.isEven) { |
- d -= x; |
- } |
- d ~/= 2; |
- } |
- if (u >= v) { |
- u -= v; |
- if (ac) a -= c; |
- b -= d; |
- } else { |
- v -= u; |
- if (ac) c -= a; |
- d -= b; |
- } |
- } while (u != 0); |
- if (!inv) return s*v; |
- if (v != 1) throw new RangeError("Not coprime"); |
- if (d < 0) { |
- d += x; |
- if (d < 0) d += x; |
- } else if (d > x) { |
- d -= x; |
- if (d > x) d -= x; |
- } |
- return d; |
- } |
- |
- // Returns 1/this % m, with m > 0. |
- int modInverse(int m) { |
- if (m is! int) throw new ArgumentError(m); |
- if (m <= 0) throw new RangeError(m); |
- if (m == 1) return 0; |
- int t = this; |
- if ((t < 0) || (t >= m)) t %= m; |
- if (t == 1) return 1; |
- if ((t == 0) || (t.isEven && m.isEven)) throw new RangeError("Not coprime"); |
- return _binaryGcd(m, t, true); |
- } |
- |
- // Returns gcd of abs(this) and abs(other), with this != 0 and other !=0. |
- int gcd(int other) { |
- if (other is! int) throw new ArgumentError(other); |
- if ((this == 0) || (other == 0)) throw new RangeError(0); |
- int x = this.abs(); |
- int y = other.abs(); |
- if ((x == 1) || (y == 1)) return 1; |
- return _binaryGcd(x, y, false); |
- } |
- |
- // Assumes i is <= 32-bit and unsigned. |
- static int _bitCount(int i) { |
- // See "Hacker's Delight", section 5-1, "Counting 1-Bits". |
- |
- // The basic strategy is to use "divide and conquer" to |
- // add pairs (then quads, etc.) of bits together to obtain |
- // sub-counts. |
- // |
- // A straightforward approach would look like: |
- // |
- // i = (i & 0x55555555) + ((i >> 1) & 0x55555555); |
- // i = (i & 0x33333333) + ((i >> 2) & 0x33333333); |
- // i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F); |
- // i = (i & 0x00FF00FF) + ((i >> 8) & 0x00FF00FF); |
- // i = (i & 0x0000FFFF) + ((i >> 16) & 0x0000FFFF); |
- // |
- // The code below removes unnecessary &'s and uses a |
- // trick to remove one instruction in the first line. |
- |
- i = _shru(i, 0) - (_shru(i, 1) & 0x55555555); |
- i = (i & 0x33333333) + (_shru(i, 2) & 0x33333333); |
- i = 0x0F0F0F0F & (i + _shru(i, 4)); |
- i += _shru(i, 8); |
- i += _shru(i, 16); |
- return (i & 0x0000003F); |
- } |
- |
- static _shru(int value, int shift) => JS('int', '# >>> #', value, shift); |
- static _shrs(int value, int shift) => JS('int', '# >> #', value, shift); |
- static _ors(int a, int b) => JS('int', '# | #', a, b); |
- |
- // Assumes i is <= 32-bit |
- static int _spread(int i) { |
- i = _ors(i, _shrs(i, 1)); |
- i = _ors(i, _shrs(i, 2)); |
- i = _ors(i, _shrs(i, 4)); |
- i = _ors(i, _shrs(i, 8)); |
- i = _shru(_ors(i, _shrs(i, 16)), 0); |
- return i; |
- } |
- |
- Type get runtimeType => int; |
- |
- int operator ~() => JS('JSUInt32', r'(~#) >>> 0', this); |
-} |
- |
-class JSDouble extends JSNumber implements double { |
- const JSDouble(); |
- Type get runtimeType => double; |
-} |
- |
-class JSPositiveInt extends JSInt {} |
-class JSUInt32 extends JSPositiveInt {} |
-class JSUInt31 extends JSUInt32 {} |