OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class _Double implements double { | 5 class _Double implements double { |
6 factory _Double.fromInteger(int value) native "Double_doubleFromInteger"; | 6 factory _Double.fromInteger(int value) |
| 7 native "Double_doubleFromInteger"; |
7 | 8 |
8 // TODO: Make a stared static method for hashCode and _identityHashCode | 9 // TODO: Make a stared static method for hashCode and _identityHashCode |
9 // when semantics are corrected as described in: | 10 // when semantics are corrected as described in: |
10 // https://github.com/dart-lang/sdk/issues/2884 | 11 // https://github.com/dart-lang/sdk/issues/2884 |
11 int get hashCode => (isNaN || isInfinite) ? 0 : toInt(); | 12 int get hashCode => (isNaN || isInfinite) ? 0 : toInt(); |
12 int get _identityHashCode => (isNaN || isInfinite) ? 0 : toInt(); | 13 int get _identityHashCode => (isNaN || isInfinite) ? 0 : toInt(); |
13 | 14 |
14 double operator +(num other) { | 15 double operator +(num other) { |
15 return _add(other.toDouble()); | 16 return _add(other.toDouble()); |
16 } | 17 } |
17 | |
18 double _add(double other) native "Double_add"; | 18 double _add(double other) native "Double_add"; |
19 | 19 |
20 double operator -(num other) { | 20 double operator -(num other) { |
21 return _sub(other.toDouble()); | 21 return _sub(other.toDouble()); |
22 } | 22 } |
23 | |
24 double _sub(double other) native "Double_sub"; | 23 double _sub(double other) native "Double_sub"; |
25 | 24 |
26 double operator *(num other) { | 25 double operator *(num other) { |
27 return _mul(other.toDouble()); | 26 return _mul(other.toDouble()); |
28 } | 27 } |
29 | |
30 double _mul(double other) native "Double_mul"; | 28 double _mul(double other) native "Double_mul"; |
31 | 29 |
32 int operator ~/(num other) { | 30 int operator ~/(num other) { |
33 return _trunc_div(other.toDouble()); | 31 return _trunc_div(other.toDouble()); |
34 } | 32 } |
35 | |
36 int _trunc_div(double other) native "Double_trunc_div"; | 33 int _trunc_div(double other) native "Double_trunc_div"; |
37 | 34 |
38 double operator /(num other) { | 35 double operator /(num other) { |
39 return _div(other.toDouble()); | 36 return _div(other.toDouble()); |
40 } | 37 } |
41 | |
42 double _div(double other) native "Double_div"; | 38 double _div(double other) native "Double_div"; |
43 | 39 |
44 double operator %(num other) { | 40 double operator %(num other) { |
45 return _modulo(other.toDouble()); | 41 return _modulo(other.toDouble()); |
46 } | 42 } |
47 | |
48 double _modulo(double other) native "Double_modulo"; | 43 double _modulo(double other) native "Double_modulo"; |
49 | 44 |
50 double remainder(num other) { | 45 double remainder(num other) { |
51 return _remainder(other.toDouble()); | 46 return _remainder(other.toDouble()); |
52 } | 47 } |
53 | |
54 double _remainder(double other) native "Double_remainder"; | 48 double _remainder(double other) native "Double_remainder"; |
55 | 49 |
56 double operator -() native "Double_flipSignBit"; | 50 double operator -() native "Double_flipSignBit"; |
57 | 51 |
58 bool operator ==(other) { | 52 bool operator ==(other) { |
59 if (!(other is num)) return false; | 53 if (!(other is num)) return false; |
60 return _equal(other.toDouble()); | 54 return _equal(other.toDouble()); |
61 } | 55 } |
62 | |
63 bool _equal(double other) native "Double_equal"; | 56 bool _equal(double other) native "Double_equal"; |
64 bool _equalToInteger(int other) native "Double_equalToInteger"; | 57 bool _equalToInteger(int other) native "Double_equalToInteger"; |
65 bool operator <(num other) { | 58 bool operator <(num other) { |
66 return other > this; | 59 return other > this; |
67 } | 60 } |
68 | |
69 bool operator >(num other) { | 61 bool operator >(num other) { |
70 return _greaterThan(other.toDouble()); | 62 return _greaterThan(other.toDouble()); |
71 } | 63 } |
72 | |
73 bool _greaterThan(double other) native "Double_greaterThan"; | 64 bool _greaterThan(double other) native "Double_greaterThan"; |
74 bool operator >=(num other) { | 65 bool operator >=(num other) { |
75 return (this == other) || (this > other); | 66 return (this == other) || (this > other); |
76 } | 67 } |
77 | |
78 bool operator <=(num other) { | 68 bool operator <=(num other) { |
79 return (this == other) || (this < other); | 69 return (this == other) || (this < other); |
80 } | 70 } |
81 | |
82 double _addFromInteger(int other) { | 71 double _addFromInteger(int other) { |
83 return new _Double.fromInteger(other)._add(this); | 72 return new _Double.fromInteger(other)._add(this); |
84 } | 73 } |
85 | |
86 double _subFromInteger(int other) { | 74 double _subFromInteger(int other) { |
87 return new _Double.fromInteger(other)._sub(this); | 75 return new _Double.fromInteger(other)._sub(this); |
88 } | 76 } |
89 | |
90 double _mulFromInteger(int other) { | 77 double _mulFromInteger(int other) { |
91 return new _Double.fromInteger(other)._mul(this); | 78 return new _Double.fromInteger(other)._mul(this); |
92 } | 79 } |
93 | |
94 int _truncDivFromInteger(int other) { | 80 int _truncDivFromInteger(int other) { |
95 return new _Double.fromInteger(other)._trunc_div(this); | 81 return new _Double.fromInteger(other)._trunc_div(this); |
96 } | 82 } |
97 | |
98 double _moduloFromInteger(int other) { | 83 double _moduloFromInteger(int other) { |
99 return new _Double.fromInteger(other)._modulo(this); | 84 return new _Double.fromInteger(other)._modulo(this); |
100 } | 85 } |
101 | |
102 double _remainderFromInteger(int other) { | 86 double _remainderFromInteger(int other) { |
103 return new _Double.fromInteger(other)._remainder(this); | 87 return new _Double.fromInteger(other)._remainder(this); |
104 } | 88 } |
105 | |
106 bool _greaterThanFromInteger(int other) | 89 bool _greaterThanFromInteger(int other) |
107 native "Double_greaterThanFromInteger"; | 90 native "Double_greaterThanFromInteger"; |
108 | 91 |
109 bool get isNegative native "Double_getIsNegative"; | 92 bool get isNegative native "Double_getIsNegative"; |
110 bool get isInfinite native "Double_getIsInfinite"; | 93 bool get isInfinite native "Double_getIsInfinite"; |
111 bool get isNaN native "Double_getIsNaN"; | 94 bool get isNaN native "Double_getIsNaN"; |
112 bool get isFinite => !isInfinite && !isNaN; // Can be optimized. | 95 bool get isFinite => !isInfinite && !isNaN; // Can be optimized. |
113 | 96 |
114 double abs() { | 97 double abs() { |
115 // Handle negative 0.0. | 98 // Handle negative 0.0. |
116 if (this == 0.0) return 0.0; | 99 if (this == 0.0) return 0.0; |
117 return this < 0.0 ? -this : this; | 100 return this < 0.0 ? -this : this; |
118 } | 101 } |
119 | 102 |
120 double get sign { | 103 double get sign { |
121 if (this > 0.0) return 1.0; | 104 if (this > 0.0) return 1.0; |
122 if (this < 0.0) return -1.0; | 105 if (this < 0.0) return -1.0; |
123 return this; // +/-0.0 or NaN. | 106 return this; // +/-0.0 or NaN. |
124 } | 107 } |
125 | 108 |
126 int round() => roundToDouble().toInt(); | 109 int round() => roundToDouble().toInt(); |
127 int floor() => floorToDouble().toInt(); | 110 int floor() => floorToDouble().toInt(); |
128 int ceil() => ceilToDouble().toInt(); | 111 int ceil () => ceilToDouble().toInt(); |
129 int truncate() => truncateToDouble().toInt(); | 112 int truncate() => truncateToDouble().toInt(); |
130 | 113 |
131 double roundToDouble() native "Double_round"; | 114 double roundToDouble() native "Double_round"; |
132 double floorToDouble() native "Double_floor"; | 115 double floorToDouble() native "Double_floor"; |
133 double ceilToDouble() native "Double_ceil"; | 116 double ceilToDouble() native "Double_ceil"; |
134 double truncateToDouble() native "Double_truncate"; | 117 double truncateToDouble() native "Double_truncate"; |
135 | 118 |
136 num clamp(num lowerLimit, num upperLimit) { | 119 num clamp(num lowerLimit, num upperLimit) { |
137 if (lowerLimit is! num) { | 120 if (lowerLimit is! num) { |
138 throw new ArgumentError.value(lowerLimit, "lowerLimit", "not a number"); | 121 throw new ArgumentError.value(lowerLimit, "lowerLimit", "not a number"); |
139 } | 122 } |
140 if (upperLimit is! num) { | 123 if (upperLimit is! num) { |
141 throw new ArgumentError.value(upperLimit, "upperLimit", "not a number"); | 124 throw new ArgumentError.value(upperLimit, "upperLimit", "not a number"); |
142 } | 125 } |
143 | 126 |
144 if (lowerLimit.compareTo(upperLimit) > 0) { | 127 if (lowerLimit.compareTo(upperLimit) > 0) { |
145 throw new ArgumentError(lowerLimit); | 128 throw new ArgumentError(lowerLimit); |
146 } | 129 } |
147 if (lowerLimit.isNaN) return lowerLimit; | 130 if (lowerLimit.isNaN) return lowerLimit; |
148 if (this.compareTo(lowerLimit) < 0) return lowerLimit; | 131 if (this.compareTo(lowerLimit) < 0) return lowerLimit; |
149 if (this.compareTo(upperLimit) > 0) return upperLimit; | 132 if (this.compareTo(upperLimit) > 0) return upperLimit; |
150 return this; | 133 return this; |
151 } | 134 } |
152 | 135 |
153 int toInt() native "Double_toInt"; | 136 int toInt() native "Double_toInt"; |
154 num _toBigintOrDouble() { | 137 num _toBigintOrDouble() { return this; } |
155 return this; | 138 double toDouble() { return this; } |
156 } | |
157 | |
158 double toDouble() { | |
159 return this; | |
160 } | |
161 | 139 |
162 static const int CACHE_SIZE_LOG2 = 3; | 140 static const int CACHE_SIZE_LOG2 = 3; |
163 static const int CACHE_LENGTH = 1 << (CACHE_SIZE_LOG2 + 1); | 141 static const int CACHE_LENGTH = 1 << (CACHE_SIZE_LOG2 + 1); |
164 static const int CACHE_MASK = CACHE_LENGTH - 1; | 142 static const int CACHE_MASK = CACHE_LENGTH - 1; |
165 // Each key (double) followed by its toString result. | 143 // Each key (double) followed by its toString result. |
166 static final List _cache = new List(CACHE_LENGTH); | 144 static final List _cache = new List(CACHE_LENGTH); |
167 static int _cacheEvictIndex = 0; | 145 static int _cacheEvictIndex = 0; |
168 | 146 |
169 String _toString() native "Double_toString"; | 147 String _toString() native "Double_toString"; |
170 | 148 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 | 186 |
209 // Step 5 and 6 skipped. Will be dealt with by native function. | 187 // Step 5 and 6 skipped. Will be dealt with by native function. |
210 | 188 |
211 // Step 7. | 189 // Step 7. |
212 if (x >= 1e21 || x <= -1e21) { | 190 if (x >= 1e21 || x <= -1e21) { |
213 return x.toString(); | 191 return x.toString(); |
214 } | 192 } |
215 | 193 |
216 return _toStringAsFixed(fractionDigits); | 194 return _toStringAsFixed(fractionDigits); |
217 } | 195 } |
218 | |
219 String _toStringAsFixed(int fractionDigits) native "Double_toStringAsFixed"; | 196 String _toStringAsFixed(int fractionDigits) native "Double_toStringAsFixed"; |
220 | 197 |
221 String toStringAsExponential([int fractionDigits]) { | 198 String toStringAsExponential([int fractionDigits]) { |
222 // See ECMAScript-262, 15.7.4.6 for details. | 199 // See ECMAScript-262, 15.7.4.6 for details. |
223 | 200 |
224 // The EcmaScript specification checks for NaN and Infinity before looking | 201 // The EcmaScript specification checks for NaN and Infinity before looking |
225 // at the fractionDigits. In Dart we are consistent with toStringAsFixed and | 202 // at the fractionDigits. In Dart we are consistent with toStringAsFixed and |
226 // look at the fractionDigits first. | 203 // look at the fractionDigits first. |
227 | 204 |
228 // Step 7. | 205 // Step 7. |
(...skipping 10 matching lines...) Expand all Loading... |
239 if (isNaN) return "NaN"; | 216 if (isNaN) return "NaN"; |
240 if (this == double.INFINITY) return "Infinity"; | 217 if (this == double.INFINITY) return "Infinity"; |
241 if (this == -double.INFINITY) return "-Infinity"; | 218 if (this == -double.INFINITY) return "-Infinity"; |
242 | 219 |
243 // The dart function prints the shortest representation when fractionDigits | 220 // The dart function prints the shortest representation when fractionDigits |
244 // equals null. The native function wants -1 instead. | 221 // equals null. The native function wants -1 instead. |
245 fractionDigits = (fractionDigits == null) ? -1 : fractionDigits; | 222 fractionDigits = (fractionDigits == null) ? -1 : fractionDigits; |
246 | 223 |
247 return _toStringAsExponential(fractionDigits); | 224 return _toStringAsExponential(fractionDigits); |
248 } | 225 } |
249 | |
250 String _toStringAsExponential(int fractionDigits) | 226 String _toStringAsExponential(int fractionDigits) |
251 native "Double_toStringAsExponential"; | 227 native "Double_toStringAsExponential"; |
252 | 228 |
253 String toStringAsPrecision(int precision) { | 229 String toStringAsPrecision(int precision) { |
254 // See ECMAScript-262, 15.7.4.7 for details. | 230 // See ECMAScript-262, 15.7.4.7 for details. |
255 | 231 |
256 // The EcmaScript specification checks for NaN and Infinity before looking | 232 // The EcmaScript specification checks for NaN and Infinity before looking |
257 // at the fractionDigits. In Dart we are consistent with toStringAsFixed and | 233 // at the fractionDigits. In Dart we are consistent with toStringAsFixed and |
258 // look at the fractionDigits first. | 234 // look at the fractionDigits first. |
259 | 235 |
260 if (precision is! int) { | 236 if (precision is! int) { |
261 throw new ArgumentError.value(precision, "precision", "not an integer"); | 237 throw new ArgumentError.value(precision, "precision", "not an integer"); |
262 } | 238 } |
263 // Step 8. | 239 // Step 8. |
264 if (precision < 1 || precision > 21) { | 240 if (precision < 1 || precision > 21) { |
265 throw new RangeError.range(precision, 1, 21, "precision"); | 241 throw new RangeError.range(precision, 1, 21, "precision"); |
266 } | 242 } |
267 | 243 |
268 if (isNaN) return "NaN"; | 244 if (isNaN) return "NaN"; |
269 if (this == double.INFINITY) return "Infinity"; | 245 if (this == double.INFINITY) return "Infinity"; |
270 if (this == -double.INFINITY) return "-Infinity"; | 246 if (this == -double.INFINITY) return "-Infinity"; |
271 | 247 |
272 return _toStringAsPrecision(precision); | 248 return _toStringAsPrecision(precision); |
273 } | 249 } |
274 | |
275 String _toStringAsPrecision(int fractionDigits) | 250 String _toStringAsPrecision(int fractionDigits) |
276 native "Double_toStringAsPrecision"; | 251 native "Double_toStringAsPrecision"; |
277 | 252 |
278 // Order is: NaN > Infinity > ... > 0.0 > -0.0 > ... > -Infinity. | 253 // Order is: NaN > Infinity > ... > 0.0 > -0.0 > ... > -Infinity. |
279 int compareTo(num other) { | 254 int compareTo(num other) { |
280 const int EQUAL = 0, LESS = -1, GREATER = 1; | 255 const int EQUAL = 0, LESS = -1, GREATER = 1; |
281 if (this < other) { | 256 if (this < other) { |
282 return LESS; | 257 return LESS; |
283 } else if (this > other) { | 258 } else if (this > other) { |
284 return GREATER; | 259 return GREATER; |
285 } else if (this == other) { | 260 } else if (this == other) { |
286 if (this == 0.0) { | 261 if (this == 0.0) { |
287 bool thisIsNegative = isNegative; | 262 bool thisIsNegative = isNegative; |
288 bool otherIsNegative = other.isNegative; | 263 bool otherIsNegative = other.isNegative; |
289 if (thisIsNegative == otherIsNegative) { | 264 if (thisIsNegative == otherIsNegative) { |
290 return EQUAL; | 265 return EQUAL; |
291 } | 266 } |
292 return thisIsNegative ? LESS : GREATER; | 267 return thisIsNegative ? LESS : GREATER; |
293 } else { | 268 } else { |
294 return EQUAL; | 269 return EQUAL; |
295 } | 270 } |
296 } else if (isNaN) { | 271 } else if (isNaN) { |
297 return other.isNaN ? EQUAL : GREATER; | 272 return other.isNaN ? EQUAL : GREATER; |
298 } else { | 273 } else { |
299 // Other is NaN. | 274 // Other is NaN. |
300 return LESS; | 275 return LESS; |
301 } | 276 } |
302 } | 277 } |
303 } | 278 } |
OLD | NEW |