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 part of fixnum; | 5 part of fixnum; |
6 | 6 |
7 /** | 7 /** |
8 * An immutable 64-bit signed integer, in the range [-2^63, 2^63 - 1]. | 8 * An immutable 64-bit signed integer, in the range [-2^63, 2^63 - 1]. |
9 * Arithmetic operations may overflow in order to maintain this range. | 9 * Arithmetic operations may overflow in order to maintain this range. |
10 */ | 10 */ |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 * [:((top & 0xffffffff) << 32) | (bottom & 0xffffffff):]. | 233 * [:((top & 0xffffffff) << 32) | (bottom & 0xffffffff):]. |
234 */ | 234 */ |
235 int64.fromInts(int top, int bottom) { | 235 int64.fromInts(int top, int bottom) { |
236 top &= 0xffffffff; | 236 top &= 0xffffffff; |
237 bottom &= 0xffffffff; | 237 bottom &= 0xffffffff; |
238 _l = bottom & _MASK; | 238 _l = bottom & _MASK; |
239 _m = ((top & 0xfff) << 10) | ((bottom >> _BITS) & 0x3ff); | 239 _m = ((top & 0xfff) << 10) | ((bottom >> _BITS) & 0x3ff); |
240 _h = (top >> 12) & _MASK_2; | 240 _h = (top >> 12) & _MASK_2; |
241 } | 241 } |
242 | 242 |
243 int64 _promote(other) { | 243 // Returns the [int64] representation of the specified value or null for |
244 if (other == null) { | 244 // incompatible types. |
245 throw new ArgumentError(null); | 245 int64 _promote(val) { |
justinfagnani
2013/07/26 23:44:40
Same as the int32 comment here, all but == throws
Chris Bracken
2013/07/27 01:07:11
Done.
| |
246 } else if (other is intx) { | 246 if (val is int64) { |
247 other = other.toInt64(); | 247 return val; |
248 } else if (other is int) { | 248 } else if (val is int) { |
249 other = new int64.fromInt(other); | 249 return new int64.fromInt(val); |
250 } else if (val is int32) { | |
251 return val.toInt64(); | |
250 } | 252 } |
251 if (other is !int64) { | 253 return null; |
252 throw new Exception("Can't promote $other to int64"); | |
253 } | |
254 return other; | |
255 } | 254 } |
256 | 255 |
257 int64 operator +(other) { | 256 int64 operator +(other) { |
258 int64 o = _promote(other); | 257 int64 o = _promote(other); |
258 if (o == null) { | |
259 throw new ArgumentError(other); | |
260 } | |
259 int sum0 = _l + o._l; | 261 int sum0 = _l + o._l; |
260 int sum1 = _m + o._m + _shiftRight(sum0, _BITS); | 262 int sum1 = _m + o._m + _shiftRight(sum0, _BITS); |
261 int sum2 = _h + o._h + _shiftRight(sum1, _BITS); | 263 int sum2 = _h + o._h + _shiftRight(sum1, _BITS); |
262 | 264 |
263 int64 result = new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2); | 265 int64 result = new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2); |
264 return result; | 266 return result; |
265 } | 267 } |
266 | 268 |
267 int64 operator -(other) { | 269 int64 operator -(other) { |
268 int64 o = _promote(other); | 270 int64 o = _promote(other); |
269 | 271 if (o == null) { |
272 throw new ArgumentError(other); | |
273 } | |
270 int sum0 = _l - o._l; | 274 int sum0 = _l - o._l; |
271 int sum1 = _m - o._m + _shiftRight(sum0, _BITS); | 275 int sum1 = _m - o._m + _shiftRight(sum0, _BITS); |
272 int sum2 = _h - o._h + _shiftRight(sum1, _BITS); | 276 int sum2 = _h - o._h + _shiftRight(sum1, _BITS); |
273 | 277 |
274 int64 result = new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2); | 278 int64 result = new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2); |
275 return result; | 279 return result; |
276 } | 280 } |
277 | 281 |
278 int64 operator -() { | 282 int64 operator -() { |
279 // Like 0 - this. | 283 // Like 0 - this. |
280 int sum0 = -_l; | 284 int sum0 = -_l; |
281 int sum1 = -_m + _shiftRight(sum0, _BITS); | 285 int sum1 = -_m + _shiftRight(sum0, _BITS); |
282 int sum2 = -_h + _shiftRight(sum1, _BITS); | 286 int sum2 = -_h + _shiftRight(sum1, _BITS); |
283 | 287 |
284 return new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2); | 288 return new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2); |
285 } | 289 } |
286 | 290 |
287 int64 operator *(other) { | 291 int64 operator *(other) { |
288 int64 o = _promote(other); | 292 int64 o = _promote(other); |
293 if (o == null) { | |
294 throw new ArgumentError(other); | |
295 } | |
289 // Grab 13-bit chunks. | 296 // Grab 13-bit chunks. |
290 int a0 = _l & 0x1fff; | 297 int a0 = _l & 0x1fff; |
291 int a1 = (_l >> 13) | ((_m & 0xf) << 9); | 298 int a1 = (_l >> 13) | ((_m & 0xf) << 9); |
292 int a2 = (_m >> 4) & 0x1fff; | 299 int a2 = (_m >> 4) & 0x1fff; |
293 int a3 = (_m >> 17) | ((_h & 0xff) << 5); | 300 int a3 = (_m >> 17) | ((_h & 0xff) << 5); |
294 int a4 = (_h & 0xfff00) >> 8; | 301 int a4 = (_h & 0xfff00) >> 8; |
295 | 302 |
296 int b0 = o._l & 0x1fff; | 303 int b0 = o._l & 0x1fff; |
297 int b1 = (o._l >> 13) | ((o._m & 0xf) << 9); | 304 int b1 = (o._l >> 13) | ((o._m & 0xf) << 9); |
298 int b2 = (o._m >> 4) & 0x1fff; | 305 int b2 = (o._m >> 4) & 0x1fff; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
368 } | 375 } |
369 | 376 |
370 int64 operator %(other) { | 377 int64 operator %(other) { |
371 if (other.isZero) { | 378 if (other.isZero) { |
372 throw new IntegerDivisionByZeroException(); | 379 throw new IntegerDivisionByZeroException(); |
373 } | 380 } |
374 if (this.isZero) { | 381 if (this.isZero) { |
375 return ZERO; | 382 return ZERO; |
376 } | 383 } |
377 int64 o = _promote(other).abs(); | 384 int64 o = _promote(other).abs(); |
385 if (o == null) { | |
386 throw new ArgumentError(other); | |
387 } | |
378 _divMod(this, o, true); | 388 _divMod(this, o, true); |
379 return _remainder < 0 ? (_remainder + o) : _remainder; | 389 return _remainder < 0 ? (_remainder + o) : _remainder; |
380 } | 390 } |
381 | 391 |
382 int64 operator ~/(other) => _divMod(this, _promote(other), false); | 392 int64 operator ~/(other) => _divMod(this, _promote(other), false); |
justinfagnani
2013/07/26 23:44:40
This will end up throwing a NoSuchMethodError (nul
Chris Bracken
2013/07/27 01:07:11
Done.
| |
383 | 393 |
384 // int64 remainder(other) => this - (this ~/ other) * other; | 394 // int64 remainder(other) => this - (this ~/ other) * other; |
385 int64 remainder(other) { | 395 int64 remainder(other) { |
386 if (other.isZero) { | 396 if (other.isZero) { |
387 throw new IntegerDivisionByZeroException(); | 397 throw new IntegerDivisionByZeroException(); |
388 } | 398 } |
389 int64 o = _promote(other).abs(); | 399 int64 o = _promote(other).abs(); |
400 if (o == null) { | |
401 throw new ArgumentError(other); | |
402 } | |
390 _divMod(this, o, true); | 403 _divMod(this, o, true); |
391 return _remainder; | 404 return _remainder; |
392 } | 405 } |
393 | 406 |
394 int64 operator &(other) { | 407 int64 operator &(other) { |
395 int64 o = _promote(other); | 408 int64 o = _promote(other); |
409 if (o == null) { | |
410 throw new ArgumentError(other); | |
411 } | |
396 int a0 = _l & o._l; | 412 int a0 = _l & o._l; |
397 int a1 = _m & o._m; | 413 int a1 = _m & o._m; |
398 int a2 = _h & o._h; | 414 int a2 = _h & o._h; |
399 return new int64._bits(a0, a1, a2); | 415 return new int64._bits(a0, a1, a2); |
400 } | 416 } |
401 | 417 |
402 int64 operator |(other) { | 418 int64 operator |(other) { |
403 int64 o = _promote(other); | 419 int64 o = _promote(other); |
420 if (o == null) { | |
421 throw new ArgumentError(other); | |
422 } | |
404 int a0 = _l | o._l; | 423 int a0 = _l | o._l; |
405 int a1 = _m | o._m; | 424 int a1 = _m | o._m; |
406 int a2 = _h | o._h; | 425 int a2 = _h | o._h; |
407 return new int64._bits(a0, a1, a2); | 426 return new int64._bits(a0, a1, a2); |
408 } | 427 } |
409 | 428 |
410 int64 operator ^(other) { | 429 int64 operator ^(other) { |
411 int64 o = _promote(other); | 430 int64 o = _promote(other); |
431 if (o == null) { | |
432 throw new ArgumentError(other); | |
433 } | |
412 int a0 = _l ^ o._l; | 434 int a0 = _l ^ o._l; |
413 int a1 = _m ^ o._m; | 435 int a1 = _m ^ o._m; |
414 int a2 = _h ^ o._h; | 436 int a2 = _h ^ o._h; |
415 return new int64._bits(a0, a1, a2); | 437 return new int64._bits(a0, a1, a2); |
416 } | 438 } |
417 | 439 |
418 int64 operator ~() { | 440 int64 operator ~() { |
419 var result = new int64._bits((~_l) & _MASK, (~_m) & _MASK, (~_h) & _MASK_2); | 441 var result = new int64._bits((~_l) & _MASK, (~_m) & _MASK, (~_h) & _MASK_2); |
420 return result; | 442 return result; |
421 } | 443 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 } | 530 } |
509 | 531 |
510 return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2); | 532 return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2); |
511 } | 533 } |
512 | 534 |
513 /** | 535 /** |
514 * Returns [true] if this [int64] has the same numeric value as the | 536 * Returns [true] if this [int64] has the same numeric value as the |
515 * given object. The argument may be an [int] or an [intx]. | 537 * given object. The argument may be an [int] or an [intx]. |
516 */ | 538 */ |
517 bool operator ==(other) { | 539 bool operator ==(other) { |
518 if (other == null) { | 540 int64 o = _promote(other); |
541 if (o == null) { | |
519 return false; | 542 return false; |
520 } | 543 } |
521 int64 o = _promote(other); | |
522 return _l == o._l && _m == o._m && _h == o._h; | 544 return _l == o._l && _m == o._m && _h == o._h; |
523 } | 545 } |
524 | 546 |
525 int compareTo(Comparable other) { | 547 int compareTo(Comparable other) { |
526 int64 o = _promote(other); | 548 int64 o = _promote(other); |
549 if (o == null) { | |
550 throw new ArgumentError(other); | |
551 } | |
527 int signa = _h >> (_BITS2 - 1); | 552 int signa = _h >> (_BITS2 - 1); |
528 int signb = o._h >> (_BITS2 - 1); | 553 int signb = o._h >> (_BITS2 - 1); |
529 if (signa != signb) { | 554 if (signa != signb) { |
530 return signa == 0 ? 1 : -1; | 555 return signa == 0 ? 1 : -1; |
531 } | 556 } |
532 if (_h > o._h) { | 557 if (_h > o._h) { |
533 return 1; | 558 return 1; |
534 } else if (_h < o._h) { | 559 } else if (_h < o._h) { |
535 return -1; | 560 return -1; |
536 } | 561 } |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
990 if (h == 0 && m != 0 && l == 0) { | 1015 if (h == 0 && m != 0 && l == 0) { |
991 return int32._numberOfTrailingZeros(m) + _BITS; | 1016 return int32._numberOfTrailingZeros(m) + _BITS; |
992 } | 1017 } |
993 if (h != 0 && m == 0 && l == 0) { | 1018 if (h != 0 && m == 0 && l == 0) { |
994 return int32._numberOfTrailingZeros(h) + _BITS01; | 1019 return int32._numberOfTrailingZeros(h) + _BITS01; |
995 } | 1020 } |
996 | 1021 |
997 return -1; | 1022 return -1; |
998 } | 1023 } |
999 | 1024 |
1000 int64 _divMod(int64 a, int64 b, bool computeRemainder) { | 1025 int64 _divMod(int64 a, int64 b, bool computeRemainder) { |
justinfagnani
2013/07/26 23:44:40
It looks like this is acting like a static method,
Chris Bracken
2013/07/27 01:07:11
It's used in toString() and toRadixString() with n
justinfagnani
2013/07/27 01:23:54
What I mean is that this method doesn't mix a and
| |
1001 if (b.isZero) { | 1026 if (b.isZero) { |
1002 throw new IntegerDivisionByZeroException(); | 1027 throw new IntegerDivisionByZeroException(); |
1003 } | 1028 } |
1004 if (a.isZero) { | 1029 if (a.isZero) { |
1005 if (computeRemainder) { | 1030 if (computeRemainder) { |
1006 _remainder = ZERO; | 1031 _remainder = ZERO; |
1007 } | 1032 } |
1008 return ZERO; | 1033 return ZERO; |
1009 } | 1034 } |
1010 // MIN_VALUE / MIN_VALUE = 1, anything other a / MIN_VALUE is 0. | 1035 // MIN_VALUE / MIN_VALUE = 1, anything other a / MIN_VALUE is 0. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1088 } | 1113 } |
1089 } | 1114 } |
1090 return ZERO; | 1115 return ZERO; |
1091 } | 1116 } |
1092 | 1117 |
1093 // Generate the quotient using bit-at-a-time long division. | 1118 // Generate the quotient using bit-at-a-time long division. |
1094 return _divModHelper(aIsCopy ? a : new int64._copy(a), b, negative, | 1119 return _divModHelper(aIsCopy ? a : new int64._copy(a), b, negative, |
1095 aIsNegative, aIsMinValue, computeRemainder); | 1120 aIsNegative, aIsMinValue, computeRemainder); |
1096 } | 1121 } |
1097 } | 1122 } |
OLD | NEW |