Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: utils/fixnum/int64.dart

Issue 10381133: Add 'fixnum' library to utils/ (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * An immutable 64-bit signed integer, in the range [-2^63, 2^63 - 1].
7 * Arithmetic operations may overflow in order to maintain this range.
8 */
9 class int64 implements intx {
10 // Note: instances of int64 are immutable outside of this library,
11 // therefore we may return a reference to an existing instance.
12 // We take care to perform mutation only on internally-generated
13 // instances before they are exposed to external code.
14
15 // Note: several functions require _BITS == 22 -- do not change this value
Mads Ager (google) 2012/05/15 07:37:39 End comment with a period. Also, I think it would
16 static final int _BITS = 22;
17 static final int _BITS01 = 44; // 2 * BITS
18 static final int _BITS2 = 20; // 64 - BITS01
19 static final int _MASK = 4194303; // (1 << BITS) - 1
20 static final int _MASK_2 = 1048575; // (1 << BITS2) - 1
21 static final int _SIGN_BIT = 19; // BITS2 - 1
22 static final int _SIGN_BIT_VALUE = 524288; // 1 << SIGN_BIT
23
24 static int64 _remainder;
25
26 static int64 _MAX_VALUE;
27 static int64 _MIN_VALUE;
28 static int64 _ZERO;
29 static int64 _ONE;
30 static int64 _TWO;
31
32 /**
33 * The maximum positive value attainable by an [int64], namely
34 * 9,223,372,036,854,775,807.
35 */
36 static int64 get MAX_VALUE() {
37 if (_MAX_VALUE == null) {
38 _MAX_VALUE = new int64._bits(_MASK, _MASK, _MASK_2 >> 1);
39 }
40 return _MAX_VALUE;
41 }
42
43 /**
44 * The minimum positive value attainable by an [int64], namely
45 * -9,223,372,036,854,775,808.
46 */
47 static int64 get MIN_VALUE() {
48 if (_MIN_VALUE == null) {
49 _MIN_VALUE = new int64._bits(0, 0, _SIGN_BIT_VALUE);
50 }
51 return _MIN_VALUE;
52 }
53
54 /**
55 * An [int64] constant equal to 0.
56 */
57 static int64 get ZERO() {
58 if (_ZERO == null) {
59 _ZERO = new int64();
60 }
61 return _ZERO;
62 }
63
64 /**
65 * An [int64] constant equal to 1.
66 */
67 static int64 get ONE() {
68 if (_ONE == null) {
69 _ONE = new int64._bits(1, 0, 0);
70 }
71 return _ONE;
72 }
73
74 /**
75 * An [int64] constant equal to 2.
76 */
77 static int64 get TWO() {
78 if (_TWO == null) {
79 _TWO = new int64._bits(2, 0, 0);
80 }
81 return _TWO;
82 }
83
84 /**
85 * Parses a [String] in a given [radix] between 2 and 16 and returns an
86 * [int64].
87 */
88 // TODO(rice) - make this faster by converting several digits at once
89 static int64 parseRadix(String s, int radix) {
90 if ((radix <= 1) || (radix > 16)) {
91 throw "Bad radix: $radix";
92 }
93 int64 x = ZERO;
94 int i = 0;
95 bool negative = false;
96 if (s[0] == '-') {
97 negative = true;
98 i++;
99 }
100 for (; i < s.length; i++) {
101 int c = s.charCodeAt(i);
102 int digit = int32._decodeHex(c);
103 if (digit < 0 || digit >= radix) {
104 throw new Exception("Non-radix char code: $c");
105 }
106 x = (x * radix) + digit;
107 }
108 return negative ? -x : x;
109 }
110
111 /**
112 * Parses a decimal [String] and returns an [int64].
113 */
114 static int64 parseInt(String s) => parseRadix(s, 10);
115
116 /**
117 * Parses a hexadecimal [String] and returns an [int64].
118 */
119 static int64 parseHex(String s) => parseRadix(s, 16);
120
121 // Low, middle, and high bits. _l and _m are in the range
122 // [0, 2^22 - 1] and _h is in the range [0, 2^20 - 1].
123 int _l, _m, _h;
124
125 /**
126 * Constructs an [int64] equal to 0.
127 */
128 int64() : _l = 0, _m = 0, _h = 0;
129
130 /**
131 * Constructs an [int64] with a given bitwise representation. No validation
132 * is performed.
133 */
134 int64._bits(int this._l, int this._m, int this._h);
135
136 /**
137 * Constructs an [int64] with the same value as an existing [int64].
138 */
139 int64._copy(int64 other) {
140 _l = other._l;
141 _m = other._m;
142 _h = other._h;
143 }
144
145 // Determine whether the platform supports ints greater than 2^53
146 // without loss of precision.
147 static bool _haveBigIntsCached = null;
148
149 static bool get _haveBigInts() {
150 if (_haveBigIntsCached == null) {
151 var x = 9007199254740992;
152 var y = x + 1;
153 var same = y == x;
154 _haveBigIntsCached = !same;
155 }
156 return _haveBigIntsCached;
157 }
158
159 /**
160 * Constructs an [int64] with a given [int] value.
161 */
162 int64.fromInt(int value) {
163 bool negative = false;
164 if (value < 0) {
165 negative = true;
166 value = -value - 1;
167 }
168 if (_haveBigInts) {
169 _l = value & _MASK;
170 _m = (value >> _BITS) & _MASK;
171 _h = (value >> _BITS01) & _MASK_2;
172 } else {
173 // Avoid using bitwise operations that coerce their input to 32 bits
174 _h = value ~/ 17592186044416; // 2^44
175 value -= _h * 17592186044416;
176 _m = value ~/ 4194304; // 2^22
177 value -= _m * 4194304;
178 _l = value;
179 }
180
181 if (negative) {
182 _l = ~_l & _MASK;
183 _m = ~_m & _MASK;
184 _h = ~_h & _MASK_2;
185 }
186 }
187
188 factory int64.fromBytes(List<int> bytes) {
189 int top = bytes[7] & 0xff;
190 top <<= 8;
191 top |= bytes[6] & 0xff;
192 top <<= 8;
193 top |= bytes[5] & 0xff;
194 top <<= 8;
195 top |= bytes[4] & 0xff;
196
197 int bottom = bytes[3] & 0xff;
198 bottom <<= 8;
199 bottom |= bytes[2] & 0xff;
200 bottom <<= 8;
201 bottom |= bytes[1] & 0xff;
202 bottom <<= 8;
203 bottom |= bytes[0] & 0xff;
204
205 return new int64.fromInts(top, bottom);
206 }
207
208 factory int64.fromBytesBigEndian(List<int> bytes) {
209 int top = bytes[0] & 0xff;
210 top <<= 8;
211 top |= bytes[1] & 0xff;
212 top <<= 8;
213 top |= bytes[2] & 0xff;
214 top <<= 8;
215 top |= bytes[3] & 0xff;
216
217 int bottom = bytes[4] & 0xff;
218 bottom <<= 8;
219 bottom |= bytes[5] & 0xff;
220 bottom <<= 8;
221 bottom |= bytes[6] & 0xff;
222 bottom <<= 8;
223 bottom |= bytes[7] & 0xff;
224
225 return new int64.fromInts(top, bottom);
226 }
227
228 /**
229 * Constructs an [int64] from a pair of 32-bit integers having the value
230 * [:((top & 0xffffffff) << 32) | (bottom & 0xffffffff):].
231 */
232 int64.fromInts(int top, int bottom) {
233 top &= 0xffffffff;
234 bottom &= 0xffffffff;
235 _l = bottom & _MASK;
236 _m = ((top & 0xfff) << 10) | ((bottom >> _BITS) & 0x3ff);
237 _h = (top >> 12) & _MASK_2;
238 }
239
240 int64 _promote(other) {
241 if (other == null) {
242 throw new NullPointerException();
243 } else if (other is intx) {
244 other = other.toInt64();
245 } else if (other is int) {
246 other = new int64.fromInt(other);
247 }
248 if (other is !int64) {
249 throw new Exception("Can't promote $other to int64");
250 }
251 return other;
252 }
253
254 int64 operator +(other) {
255 int64 o = _promote(other);
256 int sum0 = _l + o._l;
257 int sum1 = _m + o._m + (sum0 >> _BITS);
258 int sum2 = _h + o._h + (sum1 >> _BITS);
259
260 int64 result = new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
261 return result;
262 }
263
264 int64 operator -(other) {
265 int64 o = _promote(other);
266 int sum0 = _l - o._l;
267 int sum1 = _m - o._m + (sum0 >> _BITS);
268 int sum2 = _h - o._h + (sum1 >> _BITS);
269
270 return new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
271 }
272
273 int64 operator negate() {
274 // Like 0 - this
275 int sum0 = -_l;
276 int sum1 = -_m + (sum0 >> _BITS);
277 int sum2 = -_h + (sum1 >> _BITS);
278
279 return new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
280 }
281
282 int64 operator *(other) {
283 int64 o = _promote(other);
284 // Grab 13-bit chunks
285 int a0 = _l & 0x1fff;
286 int a1 = (_l >> 13) | ((_m & 0xf) << 9);
287 int a2 = (_m >> 4) & 0x1fff;
288 int a3 = (_m >> 17) | ((_h & 0xff) << 5);
289 int a4 = (_h & 0xfff00) >> 8;
290
291 int b0 = o._l & 0x1fff;
292 int b1 = (o._l >> 13) | ((o._m & 0xf) << 9);
293 int b2 = (o._m >> 4) & 0x1fff;
294 int b3 = (o._m >> 17) | ((o._h & 0xff) << 5);
295 int b4 = (o._h & 0xfff00) >> 8;
296
297 // Compute partial products
298 // Optimization: if b is small, avoid multiplying by parts that are 0
299 int p0 = a0 * b0; // << 0
300 int p1 = a1 * b0; // << 13
301 int p2 = a2 * b0; // << 26
302 int p3 = a3 * b0; // << 39
303 int p4 = a4 * b0; // << 52
304
305 if (b1 != 0) {
306 p1 += a0 * b1;
307 p2 += a1 * b1;
308 p3 += a2 * b1;
309 p4 += a3 * b1;
310 }
311 if (b2 != 0) {
312 p2 += a0 * b2;
313 p3 += a1 * b2;
314 p4 += a2 * b2;
315 }
316 if (b3 != 0) {
317 p3 += a0 * b3;
318 p4 += a1 * b3;
319 }
320 if (b4 != 0) {
321 p4 += a0 * b4;
322 }
323
324 // Accumulate into 22-bit chunks:
325 // .........................................c10|...................c00|
326 // |....................|..................xxxx|xxxxxxxxxxxxxxxxxxxxxx| p0
327 // |....................|......................|......................|
328 // |....................|...................c11|......c01.............|
329 // |....................|....xxxxxxxxxxxxxxxxxx|xxxxxxxxx.............| p1
330 // |....................|......................|......................|
331 // |.................c22|...............c12....|......................|
332 // |..........xxxxxxxxxx|xxxxxxxxxxxxxxxxxx....|......................| p2
333 // |....................|......................|......................|
334 // |.................c23|..c13.................|......................|
335 // |xxxxxxxxxxxxxxxxxxxx|xxxxx.................|......................| p3
336 // |....................|......................|......................|
337 // |.........c24........|......................|......................|
338 // |xxxxxxxxxxxx........|......................|......................| p4
339
340 int c00 = p0 & 0x3fffff;
341 int c01 = (p1 & 0x1ff) << 13;
342 int c0 = c00 + c01;
343
344 int c10 = p0 >> 22;
345 int c11 = p1 >> 9;
346 int c12 = (p2 & 0x3ffff) << 4;
347 int c13 = (p3 & 0x1f) << 17;
348 int c1 = c10 + c11 + c12 + c13;
349
350 int c22 = p2 >> 18;
351 int c23 = p3 >> 5;
352 int c24 = (p4 & 0xfff) << 8;
353 int c2 = c22 + c23 + c24;
354
355 // Propagate high bits from c0 -> c1, c1 -> c2
356 c1 += c0 >> _BITS;
357 c0 &= _MASK;
358 c2 += c1 >> _BITS;
359 c1 &= _MASK;
360 c2 &= _MASK_2;
361
362 return new int64._bits(c0, c1, c2);
363 }
364
365 int64 operator %(other) {
366 if (other.isZero()) {
367 throw new IntegerDivisionByZeroException();
368 }
369 if (this.isZero()) {
370 return ZERO;
371 }
372 int64 o = _promote(other).abs();
373 _divMod(this, o, true);
374 return _remainder < 0 ? (_remainder + o) : _remainder;
375 }
376
377 int64 operator ~/(other) => _divMod(this, _promote(other), false);
378
379 // int64 remainder(other) => this - (this ~/ other) * other;
380 int64 remainder(other) {
381 if (other.isZero()) {
382 throw new IntegerDivisionByZeroException();
383 }
384 int64 o = _promote(other).abs();
385 _divMod(this, o, true);
386 return _remainder;
387 }
388
389 int64 operator &(other) {
390 int64 o = _promote(other);
391 int a0 = _l & o._l;
392 int a1 = _m & o._m;
393 int a2 = _h & o._h;
394 return new int64._bits(a0, a1, a2);
395 }
396
397 int64 operator |(other) {
398 int64 o = _promote(other);
399 int a0 = _l | o._l;
400 int a1 = _m | o._m;
401 int a2 = _h | o._h;
402 return new int64._bits(a0, a1, a2);
403 }
404
405 int64 operator ^(other) {
406 int64 o = _promote(other);
407 int a0 = _l ^ o._l;
408 int a1 = _m ^ o._m;
409 int a2 = _h ^ o._h;
410 return new int64._bits(a0, a1, a2);
411 }
412
413 int64 operator ~() {
414 var result = new int64._bits((~_l) & _MASK, (~_m) & _MASK, (~_h) & _MASK_2);
415 return result;
416 }
417
418 int64 operator <<(int n) {
419 if (n < 0) {
420 throw new IllegalArgumentException("$n");
421 }
422 n &= 63;
423
424 int res0, res1, res2;
425 if (n < _BITS) {
426 res0 = _l << n;
427 res1 = (_m << n) | (_l >> (_BITS - n));
428 res2 = (_h << n) | (_m >> (_BITS - n));
429 } else if (n < _BITS01) {
430 res0 = 0;
431 res1 = _l << (n - _BITS);
432 res2 = (_m << (n - _BITS)) | (_l >> (_BITS01 - n));
433 } else {
434 res0 = 0;
435 res1 = 0;
436 res2 = _l << (n - _BITS01);
437 }
438
439 return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
440 }
441
442 int64 operator >>(int n) {
443 if (n < 0) {
444 throw new IllegalArgumentException("$n");
445 }
446 n &= 63;
447
448 int res0, res1, res2;
449
450 // Sign extend h(a)
451 int a2 = _h;
452 bool negative = (a2 & _SIGN_BIT_VALUE) != 0;
453 if (negative) {
454 a2 |= ~_MASK_2;
455 }
456
457 if (n < _BITS) {
458 res2 = a2 >> n;
459 res1 = (_m >> n) | (a2 << (_BITS - n));
460 res0 = (_l >> n) | (_m << (_BITS - n));
461 } else if (n < _BITS01) {
462 res2 = negative ? _MASK_2 : 0;
463 res1 = a2 >> (n - _BITS);
464 res0 = (_m >> (n - _BITS)) | (a2 << (_BITS01 - n));
465 } else {
466 res2 = negative ? _MASK_2 : 0;
467 res1 = negative ? _MASK : 0;
468 res0 = a2 >> (n - _BITS01);
469 }
470
471 return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
472 }
473
474 int64 shiftRightUnsigned(int n) {
475 if (n < 0) {
476 throw new IllegalArgumentException("$n");
477 }
478 n &= 63;
479
480 int res0, res1, res2;
481 int a2 = _h & _MASK_2;
482 if (n < _BITS) {
483 res2 = a2 >> n; // was >>>
484 res1 = (_m >> n) | (a2 << (_BITS - n));
485 res0 = (_l >> n) | (_m << (_BITS - n));
486 } else if (n < _BITS01) {
487 res2 = 0;
488 res1 = a2 >> (n - _BITS); // was >>>
489 res0 = (_m >> (n - _BITS)) | (_h << (_BITS01 - n));
490 } else {
491 res2 = 0;
492 res1 = 0;
493 res0 = a2 >> (n - _BITS01); // was >>>
494 }
495
496 return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
497 }
498
499 /**
500 * Returns [true] if this [int64] has the same numeric value as the
501 * given object. The argument may be an [int] or an [intx].
502 */
503 bool operator ==(other) {
504 if (other == null) {
505 return false;
506 }
507 int64 o = _promote(other);
508 return _l == o._l && _m == o._m && _h == o._h;
509 }
510
511 int compareTo(Comparable other) {
512 int64 o = _promote(other);
513 int signa = _h >> (_BITS2 - 1);
514 int signb = o._h >> (_BITS2 - 1);
515 if (signa != signb) {
516 return signa == 0 ? 1 : -1;
517 }
518 if (_h > o._h) {
519 return 1;
520 } else if (_h < o._h) {
521 return -1;
522 }
523 if (_m > o._m) {
524 return 1;
525 } else if (_m < o._m) {
526 return -1;
527 }
528 if (_l > o._l) {
529 return 1;
530 } else if (_l < o._l) {
531 return -1;
532 }
533 return 0;
534 }
535
536 bool operator <(other) {
537 return this.compareTo(other) < 0;
538 }
539
540 bool operator <=(other) {
541 return this.compareTo(other) <= 0;
542 }
543
544 bool operator >(other) {
545 return this.compareTo(other) > 0;
546 }
547
548 bool operator >=(other) {
549 return this.compareTo(other) >= 0;
550 }
551
552 bool isEven() => (_l & 0x1) == 0;
553 bool isMaxValue() => (_h == _MASK_2 >> 1) && _m == _MASK && _l == _MASK;
554 bool isMinValue() => _h == _SIGN_BIT_VALUE && _m == 0 && _l == 0;
555 bool isNegative() => (_h >> (_BITS2 - 1)) != 0;
556 bool isOdd() => (_l & 0x1) == 1;
557 bool isZero() => _h == 0 && _m == 0 && _l == 0;
558
559 /**
560 * Returns a hash code based on all the bits of this [int64].
561 */
562 int hashCode() {
563 int bottom = ((_m & 0x3ff) << 22) | _l;
564 int top = (_h << 12) | ((_m >> 10) & 0xfff);
565 return bottom ^ top;
566 }
567
568 int64 abs() {
569 return this < 0 ? -this : this;
570 }
571
572 /**
573 * Returns the number of leading zeros in this [int64] as an [int]
574 * between 0 and 64.
575 */
576 int numberOfLeadingZeros() {
577 int b2 = int32._numberOfLeadingZeros(_h);
578 if (b2 == 32) {
579 int b1 = int32._numberOfLeadingZeros(_m);
580 if (b1 == 32) {
581 return int32._numberOfLeadingZeros(_l) + 32;
Mads Ager (google) 2012/05/15 07:37:39 Should we either make the computation explicit her
582 } else {
583 return b1 + _BITS2 - (32 - _BITS);
584 }
585 } else {
586 return b2 - (32 - _BITS2);
587 }
588 }
589
590 /**
591 * Returns the number of trailing zeros in this [int64] as an [int]
592 * between 0 and 64.
593 */
594 int numberOfTrailingZeros() {
595 int zeros = int32._numberOfTrailingZeros(_l);
596 if (zeros < 32) {
597 return zeros;
598 }
599
600 zeros = int32._numberOfTrailingZeros(_m);
601 if (zeros < 32) {
602 return 22 + zeros;
603 }
604
605 zeros = int32._numberOfTrailingZeros(_h);
606 if (zeros < 32) {
607 return 44 + zeros;
608 }
609 // All zeros
610 return 64;
611 }
612
613 List<int> toBytes() {
614 List<int> result = new List<int>(8);
615 result[0] = _l & 0xff;
616 result[1] = (_l >> 8) & 0xff;
617 result[2] = ((_m << 6) & 0xfc) | ((_l >> 16) & 0x3f);
618 result[3] = (_m >> 2) & 0xff;
619 result[4] = (_m >> 10) & 0xff;
620 result[5] = ((_h << 4) & 0xf0) | ((_m >> 18) & 0xf);
621 result[6] = (_h >> 4) & 0xff;
622 result[7] = (_h >> 12) & 0xff;
623 return result;
624 }
625
626 int toInt() {
627 int l = _l;
628 int m = _m;
629 int h = _h;
630 bool negative = false;
631 if ((_h & _SIGN_BIT_VALUE) != 0) {
632 l = ~_l & _MASK;
633 m = ~_m & _MASK;
634 h = ~_h & _MASK_2;
635 negative = true;
636 }
637
638 int result;
639 if (_haveBigInts) {
640 result = (h << 44) | (m << 22) | l;
641 } else {
642 result = (h * 17592186044416) + (m * 4194304) + l;
643 }
644 return negative ? -result - 1 : result;
645 }
646
647 /**
648 * Returns an [int32] containing the low 32 bits of this [int64].
649 */
650 int32 toInt32() {
651 return new int32.fromInt(((_m & 0x3ff) << 22) | _l);
652 }
653
654 /**
655 * Returns [this].
656 */
657 int64 toInt64() => this;
658
659 /**
660 * Returns the value of this [int64] as a decimal [String].
661 */
662 // TODO(rice) - make this faster by converting several digits at once
663 String toString() {
664 int64 a = this;
665 if (a.isZero()) {
666 return "0";
667 }
668 if (a.isMinValue()) {
669 return "-9223372036854775808";
670 }
671
672 String result = "";
673 bool negative = false;
674 if (a.isNegative()) {
675 negative = true;
676 a = -a;
677 }
678
679 int64 ten = new int64._bits(10, 0, 0);
680 while (!a.isZero()) {
681 a = _divMod(a, ten, true);
682 result = "${_remainder._l}$result";
683 }
684 return negative ? "-$result" : result;
685 }
686
687 String _hexDigit(int digit) => "0123456789ABCDEF"[digit];
688
689 // TODO(rice) - make this faster by avoiding arithmetic
690 String toHexString() {
691 int64 x = new int64._copy(this);
692 if (isZero()) {
693 return "0";
694 }
695 String hexStr = "";
696 int64 digit_f = new int64.fromInt(0xf);
697 while (!x.isZero()) {
698 int digit = x._l & 0xf;
699 hexStr = "${_hexDigit(digit)}$hexStr";
700 x = x.shiftRightUnsigned(4);
701 }
702 return hexStr;
703 }
704
705 // Precompute the radix strings for MIN_VALUE to avoid the problem
706 // of overflow of -MIN_VALUE.
707 List<String> _minValues = const <String>[
708 null, null,
709 "-1000000000000000000000000000000000000000000000000000000000000000", // 2
710 "-2021110011022210012102010021220101220222", // base 3
711 "-20000000000000000000000000000000", // base 4
712 "-1104332401304422434310311213", // base 5
713 "-1540241003031030222122212", // base 6
714 "-22341010611245052052301", // base 7
715 "-1000000000000000000000", // base 8
716 "-67404283172107811828", // base 9
717 "-9223372036854775808", // base 10
718 "-1728002635214590698", // base 11
719 "-41A792678515120368", // base 12
720 "-10B269549075433C38", // base 13
721 "-4340724C6C71DC7A8", // base 14
722 "-160E2AD3246366808", // base 15
723 "-8000000000000000" // base 16
724 ];
725
726 String toRadixString(int radix) {
727 if ((radix <= 1) || (radix > 16)) {
728 throw "Bad radix: $radix";
729 }
730 int64 a = this;
731 if (a.isZero()) {
732 return "0";
733 }
734 if (a.isMinValue()) {
735 return _minValues[radix];
736 }
737
738 String result = "";
739 bool negative = false;
740 if (a.isNegative()) {
741 negative = true;
742 a = -a;
743 }
744
745 int64 r = new int64._bits(radix, 0, 0);
746 while (!a.isZero()) {
747 a = _divMod(a, r, true);
748 result = "${_hexDigit(_remainder._l)}$result";
749 }
750 return negative ? "-$result" : result;
751 }
752
753 // Implementation of ~/ and %
754
755 // Note: mutates [this]
756 void _negate() {
757 int neg0 = (~_l + 1) & _MASK;
758 int neg1 = (~_m + (neg0 == 0 ? 1 : 0)) & _MASK;
759 int neg2 = (~_h + ((neg0 == 0 && neg1 == 0) ? 1 : 0)) & _MASK_2;
760
761 _l = neg0;
762 _m = neg1;
763 _h = neg2;
764 }
765
766 // Note: mutates [this]
767 void _setBit(int bit) {
768 if (bit < _BITS) {
769 _l |= 0x1 << bit;
770 } else if (bit < _BITS01) {
771 _m |= 0x1 << (bit - _BITS);
772 } else {
773 _h |= 0x1 << (bit - _BITS01);
774 }
775 }
776
777 // Note: mutates [this]
778 void _toShru1() {
779 int a2 = _h;
780 int a1 = _m;
781 int a0 = _l;
782
783 _h = a2 >> 1;
784 _m = (a1 >> 1) | ((a2 & 0x1) << (_BITS - 1));
785 _l = (a0 >> 1) | ((a1 & 0x1) << (_BITS - 1));
786 }
787
788 /**
789 * Attempt to subtract b from a if a >= b:
790 *
791 * if (a >= b) {
792 * a -= b;
793 * return true;
794 * } else {
795 * return false;
796 * }
797 */
798 // Note: mutates [a]
799 static bool _trialSubtract(int64 a, int64 b) {
800 // Early exit
801 int sum2 = a._h - b._h;
802 if (sum2 < 0) {
803 return false;
804 }
805
806 int sum0 = a._l - b._l;
807 int sum1 = a._m - b._m + (sum0 >> _BITS);
808 sum2 += (sum1 >> _BITS);
809
810 if (sum2 < 0) {
811 return false;
812 }
813
814 a._l = sum0 & _MASK;
815 a._m = sum1 & _MASK;
816 a._h = sum2 & _MASK_2;
817
818 return true;
819 }
820
821 // Note: mutates [a] via _trialSubtract
822 static int64 _divModHelper(int64 a, int64 b,
823 bool negative, bool aIsNegative, bool aIsMinValue,
824 bool computeRemainder) {
825
826 // Align the leading one bits of a and b by shifting b left
827 int shift = b.numberOfLeadingZeros() - a.numberOfLeadingZeros();
828 int64 bshift = b << shift;
829
830 // Quotient must be a new instance since we mutate it
831 int64 quotient = new int64();
832 while (shift >= 0) {
833 bool gte = _trialSubtract(a, bshift);
834 if (gte) {
835 quotient._setBit(shift);
836 if (a.isZero()) {
837 break;
838 }
839 }
840
841 bshift._toShru1();
842 shift--;
843 }
844
845 if (negative) {
846 quotient._negate();
847 }
848
849 if (computeRemainder) {
850 if (aIsNegative) {
851 _remainder = -a;
852 if (aIsMinValue) {
853 _remainder = _remainder - ONE;
854 }
855 } else {
856 _remainder = a;
857 }
858 }
859
860 return quotient;
861 }
862
863 int64 _divModByMinValue(bool computeRemainder) {
864 // MIN_VALUE / MIN_VALUE == 1, remainder = 0
865 // (x != MIN_VALUE) / MIN_VALUE == 0, remainder == x
866 if (isMinValue()) {
867 if (computeRemainder) {
868 _remainder = ZERO;
869 }
870 return ONE;
871 }
872 if (computeRemainder) {
873 _remainder = this;
874 }
875 return ZERO;
876 }
877
878 /**
879 * this &= ((1L << bits) - 1)
880 */
881 // Note: mutates [this]
882 int64 _maskRight(int bits) {
883 int b0, b1, b2;
884 if (bits <= _BITS) {
885 b0 = _l & ((1 << bits) - 1);
886 b1 = b2 = 0;
887 } else if (bits <= _BITS01) {
888 b0 = _l;
889 b1 = _m & ((1 << (bits - _BITS)) - 1);
890 b2 = 0;
891 } else {
892 b0 = _l;
893 b1 = _m;
894 b2 = _h & ((1 << (bits - _BITS01)) - 1);
895 }
896
897 _l = b0;
898 _m = b1;
899 _h = b2;
900 }
901
902 int64 _divModByShift(int64 a, int bpower, bool negative, bool aIsCopy,
903 bool aIsNegative, bool computeRemainder) {
904 int64 c = a >> bpower;
905 if (negative) {
906 c._negate();
907 }
908
909 if (computeRemainder) {
910 if (!aIsCopy) {
911 a = new int64._copy(a);
912 }
913 a._maskRight(bpower);
914 if (aIsNegative) {
915 a._negate();
916 }
917 _remainder = a;
918 }
919 return c;
920 }
921
922 /**
923 * Return the exact log base 2 of this, or -1 if this is not a power of two.
924 */
925 int _powerOfTwo() {
926 // Power of two or 0
927 int l = _l;
928 if ((l & (l - 1)) != 0) {
929 return -1;
930 }
931 int m = _m;
932 if ((m & (m - 1)) != 0) {
933 return -1;
934 }
935 int h = _h;
936 if ((h & (h - 1)) != 0) {
937 return -1;
938 }
939 if (h == 0 && m == 0 && l == 0) {
940 return -1;
941 }
942 if (h == 0 && m == 0 && l != 0) {
943 return int32._numberOfTrailingZeros(l);
944 }
945 if (h == 0 && m != 0 && l == 0) {
946 return int32._numberOfTrailingZeros(m) + _BITS;
947 }
948 if (h != 0 && m == 0 && l == 0) {
949 return int32._numberOfTrailingZeros(h) + _BITS01;
950 }
951
952 return -1;
953 }
954
955 int64 _divMod(int64 a, int64 b, bool computeRemainder) {
956 if (b.isZero()) {
957 throw new IntegerDivisionByZeroException();
958 }
959 if (a.isZero()) {
960 if (computeRemainder) {
961 _remainder = ZERO;
962 }
963 return ZERO;
964 }
965 // MIN_VALUE / MIN_VALUE = 1, anything other a / MIN_VALUE is 0
966 if (b.isMinValue()) {
967 return a._divModByMinValue(computeRemainder);
968 }
969 // Normalize b to abs(b), keeping track of the parity in 'negative'.
970 // We can do this because we have already ensured that b != MIN_VALUE.
971 bool negative = false;
972 if (b.isNegative()) {
973 b = -b;
974 negative = !negative;
975 }
976 // If b == 2^n, bpower will be n, otherwise it will be -1
977 int bpower = b._powerOfTwo();
978
979 // True if the original value of a is negative
980 bool aIsNegative = false;
981 // True if the original value of a is Long.MIN_VALUE
982 bool aIsMinValue = false;
983
984 /*
985 * Normalize a to a positive value, keeping track of the sign change in
986 * 'negative' (which tracks the sign of both a and b and is used to
987 * determine the sign of the quotient) and 'aIsNegative' (which is used to
988 * determine the sign of the remainder).
989 *
990 * For all values of a except MIN_VALUE, we can just negate a and modify
991 * negative and aIsNegative appropriately. When a == MIN_VALUE, negation is
992 * not possible without overflowing 64 bits, so instead of computing
993 * abs(MIN_VALUE) / abs(b) we compute (abs(MIN_VALUE) - 1) / abs(b). The
994 * only circumstance under which these quotients differ is when b is a power
995 * of two, which will divide abs(MIN_VALUE) == 2^64 exactly. In this case,
996 * we can get the proper result by shifting MIN_VALUE in unsigned fashion.
997 *
998 * We make a single copy of a before the first operation that needs to
999 * modify its value.
1000 */
1001 bool aIsCopy = false;
1002 if (a.isMinValue()) {
1003 aIsMinValue = true;
1004 aIsNegative = true;
1005 // If b is not a power of two, treat -a as MAX_VALUE (instead of the
1006 // actual value (MAX_VALUE + 1)).
1007 if (bpower == -1) {
1008 a = new int64._copy(MAX_VALUE);
1009 aIsCopy = true;
1010 negative = !negative;
1011 } else {
1012 // Signed shift of MIN_VALUE produces the right answer
1013 int64 c = a >> bpower;
1014 if (negative) {
1015 c._negate();
1016 }
1017 if (computeRemainder) {
1018 _remainder = ZERO;
1019 }
1020 return c;
1021 }
1022 } else if (a.isNegative()) {
1023 aIsNegative = true;
1024 a = -a;
1025 aIsCopy = true;
1026 negative = !negative;
1027 }
1028
1029 // Now both a and b are non-negative
1030 // If b is a power of two, just shift
1031 if (bpower != -1) {
1032 return _divModByShift(a, bpower, negative, aIsCopy, aIsNegative,
1033 computeRemainder);
1034 }
1035
1036 // if a < b, the quotient is 0 and the remainder is a
1037 if (a < b) {
1038 if (computeRemainder) {
1039 if (aIsNegative) {
1040 _remainder = -a;
1041 } else {
1042 _remainder = aIsCopy ? a : new int64._copy(a);
1043 }
1044 }
1045 return ZERO;
1046 }
1047
1048 // Generate the quotient using bit-at-a-time long division
1049 return _divModHelper(aIsCopy ? a : new int64._copy(a), b, negative,
1050 aIsNegative, aIsMinValue, computeRemainder);
1051 }
1052 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698