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