| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 // Copyright 2009 The Go Authors. All rights reserved. | 5 // Copyright 2009 The Go Authors. All rights reserved. |
| 6 // Use of this source code is governed by a BSD-style | 6 // Use of this source code is governed by a BSD-style |
| 7 // license that can be found in the LICENSE file. | 7 // license that can be found in the LICENSE file. |
| 8 | 8 |
| 9 /* | 9 /* |
| 10 * Copyright (c) 2003-2005 Tom Wu | 10 * Copyright (c) 2003-2005 Tom Wu |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 // Min and max of non bigint values. | 54 // Min and max of non bigint values. |
| 55 static const int MIN_INT64 = (-1) << 63; | 55 static const int MIN_INT64 = (-1) << 63; |
| 56 static const int MAX_INT64 = 0x7fffffffffffffff; | 56 static const int MAX_INT64 = 0x7fffffffffffffff; |
| 57 | 57 |
| 58 // Bigint constant values. | 58 // Bigint constant values. |
| 59 // Note: Not declared as final in order to satisfy optimizer, which expects | 59 // Note: Not declared as final in order to satisfy optimizer, which expects |
| 60 // constants to be in canonical form (Smi). | 60 // constants to be in canonical form (Smi). |
| 61 static _Bigint ZERO = new _Bigint(); | 61 static _Bigint ZERO = new _Bigint(); |
| 62 static _Bigint ONE = new _Bigint()._setInt(1); | 62 static _Bigint ONE = new _Bigint()._setInt(1); |
| 63 | 63 |
| 64 // Argument passing for _mulAdd function preventing Mint allocation. |
| 65 static const int MA_MULTIPLIER = 0; // Index of multiplier digit. |
| 66 static const int MA_CARRY_OUT = 1; // Index of carry out digit. |
| 67 static final Uint32List _MulAddArgs = new Uint32List(2); |
| 68 |
| 64 // Digit conversion table for parsing. | 69 // Digit conversion table for parsing. |
| 65 static final Map<int, int> DIGIT_TABLE = _createDigitTable(); | 70 static final Map<int, int> DIGIT_TABLE = _createDigitTable(); |
| 66 | 71 |
| 67 // Internal data structure. | 72 // Internal data structure. |
| 68 bool get _neg native "Bigint_getNeg"; | 73 bool get _neg native "Bigint_getNeg"; |
| 69 void set _neg(bool neg) native "Bigint_setNeg"; | 74 void set _neg(bool neg) native "Bigint_setNeg"; |
| 70 int get _used native "Bigint_getUsed"; | 75 int get _used native "Bigint_getUsed"; |
| 71 void set _used(int used) native "Bigint_setUsed"; | 76 void set _used(int used) native "Bigint_setUsed"; |
| 72 Uint32List get _digits native "Bigint_getDigits"; | 77 Uint32List get _digits native "Bigint_getDigits"; |
| 73 void set _digits(Uint32List digits) { | 78 void set _digits(Uint32List digits) { |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 _absSubTo(a, r); | 775 _absSubTo(a, r); |
| 771 } else { | 776 } else { |
| 772 r_neg = !r_neg; | 777 r_neg = !r_neg; |
| 773 a._absSubTo(this, r); | 778 a._absSubTo(this, r); |
| 774 } | 779 } |
| 775 } | 780 } |
| 776 r._neg = r_neg; | 781 r._neg = r_neg; |
| 777 return r; | 782 return r; |
| 778 } | 783 } |
| 779 | 784 |
| 780 // Accumulate multiply. | 785 // Multiply and accumulate. |
| 781 // this[i..i+n-1]: bigint multiplicand. | 786 // Input: |
| 782 // x: digit multiplier, 0 <= x < DIGIT_BASE (i.e. 32-bit multiplier). | 787 // args[MA_MULTIPLIER]: multiplier digit, 0 <= x < DIGIT_BASE (i.e. 32-bit). |
| 783 // w[j..j+n-1]: bigint accumulator. | 788 // m_digits[i..i+n-1]: multiplicand digits. |
| 784 // Returns carry out. | 789 // a_digits[j..j+n-1]: accumulator digits. |
| 785 // w[j..j+n-1] += this[i..i+n-1] * x. | 790 // Operation: |
| 786 // Returns carry out. | 791 // a_digits[j..j+n-1] += x*m_digits[i..i+n-1]. |
| 787 int _am(int i, int x, _Bigint w, int j, int n) { | 792 // Output: |
| 793 // args[MA_CARRY_OUT]. |
| 794 // Note: Passing single digits as elements of args prevents Mint allocation. |
| 795 static void _mulAdd(Uint32List args, |
| 796 Uint32List m_digits, int i, |
| 797 Uint32List a_digits, int j, int n) { |
| 798 int x = args[MA_MULTIPLIER]; |
| 788 if (x == 0) { | 799 if (x == 0) { |
| 789 // No-op if x is 0. | 800 // No-op if x is 0. |
| 790 return 0; | 801 args[MA_CARRY_OUT] = 0; |
| 802 return; |
| 791 } | 803 } |
| 792 int c = 0; | 804 int c = 0; |
| 793 int xl = x & DIGIT2_MASK; | 805 int xl = x & DIGIT2_MASK; |
| 794 int xh = x >> DIGIT2_BITS; | 806 int xh = x >> DIGIT2_BITS; |
| 795 var digits = _digits; | |
| 796 var w_digits = w._digits; | |
| 797 while (--n >= 0) { | 807 while (--n >= 0) { |
| 798 int l = digits[i] & DIGIT2_MASK; | 808 int l = m_digits[i] & DIGIT2_MASK; |
| 799 int h = digits[i++] >> DIGIT2_BITS; | 809 int h = m_digits[i++] >> DIGIT2_BITS; |
| 800 int m = xh*l + h*xl; | 810 int m = xh*l + h*xl; |
| 801 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w_digits[j] + c; | 811 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 802 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 812 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 803 w_digits[j++] = l & DIGIT_MASK; | 813 a_digits[j++] = l & DIGIT_MASK; |
| 804 } | 814 } |
| 805 return c; | 815 args[MA_CARRY_OUT] = c; |
| 806 } | 816 } |
| 807 | 817 |
| 808 // Accumulate multiply with carry. | 818 // Multiply and accumulate with carry in. |
| 809 // this[i..i+n-1]: bigint multiplicand. | 819 // Input: |
| 810 // x: digit multiplier, 0 <= x < 2*DIGIT_BASE (i.e. 33-bit multiplier). | 820 // x: multiplier digit, 0 <= x < 2*DIGIT_BASE (i.e. 33-bit multiplier). |
| 811 // w[j..j+n-1]: bigint accumulator. | 821 // m_digits[i..i+n-1]: multiplicand digits. |
| 812 // c: int carry in. | 822 // a_digits[j..j+n-1]: accumulator digits. |
| 813 // Returns carry out. | 823 // c: carry in. |
| 814 // w[j..j+n-1] += this[i..i+n-1] * x + c. | 824 // Operation: |
| 815 // Returns carry out. | 825 // a_digits[j..j+n-1] += x*m_digits[i..i+n-1] + c. |
| 816 int _amc(int i, int x, _Bigint w, int j, int c, int n) { | 826 // Output: |
| 827 // carry out. |
| 828 // TODO(regis): Use an argument buffer as in _mulAdd. |
| 829 static int _mulAddc(int x, Uint32List m_digits, int i, |
| 830 Uint32List a_digits, int j, int c, int n) { |
| 817 if (x == 0 && c == 0) { | 831 if (x == 0 && c == 0) { |
| 818 // No-op if both x and c are 0. | 832 // No-op if both x and c are 0. |
| 819 return 0; | 833 return 0; |
| 820 } | 834 } |
| 821 int xl = x & DIGIT2_MASK; | 835 int xl = x & DIGIT2_MASK; |
| 822 int xh = x >> DIGIT2_BITS; | 836 int xh = x >> DIGIT2_BITS; |
| 823 var digits = _digits; | |
| 824 var w_digits = w._digits; | |
| 825 while (--n >= 0) { | 837 while (--n >= 0) { |
| 826 int l = digits[i] & DIGIT2_MASK; | 838 int l = m_digits[i] & DIGIT2_MASK; |
| 827 int h = digits[i++] >> DIGIT2_BITS; | 839 int h = m_digits[i++] >> DIGIT2_BITS; |
| 828 int m = xh*l + h*xl; | 840 int m = xh*l + h*xl; |
| 829 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w_digits[j] + c; | 841 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 830 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 842 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 831 w_digits[j++] = l & DIGIT_MASK; | 843 a_digits[j++] = l & DIGIT_MASK; |
| 832 } | 844 } |
| 833 return c; | 845 return c; |
| 834 } | 846 } |
| 835 | 847 |
| 836 // r = this * a. | 848 // r = this * a. |
| 837 void _mulTo(_Bigint a, _Bigint r) { | 849 void _mulTo(_Bigint a, _Bigint r) { |
| 838 // TODO(regis): Use karatsuba multiplication when appropriate. | 850 // TODO(regis): Use karatsuba multiplication when appropriate. |
| 839 var used = _used; | 851 var used = _used; |
| 840 var a_used = a._used; | 852 var a_used = a._used; |
| 841 var i = used; | 853 var i = used; |
| 842 r._ensureLength(i + a_used); | 854 r._ensureLength(i + a_used); |
| 855 var digits = _digits; |
| 843 var a_digits = a._digits; | 856 var a_digits = a._digits; |
| 844 var r_digits = r._digits; | 857 var r_digits = r._digits; |
| 845 r._used = i + a_used; | 858 r._used = i + a_used; |
| 846 while (--i >= 0) { | 859 while (--i >= 0) { |
| 847 r_digits[i] = 0; | 860 r_digits[i] = 0; |
| 848 } | 861 } |
| 849 for (i = 0; i < a_used; ++i) { | 862 for (i = 0; i < a_used; ++i) { |
| 850 r_digits[i + used] = _am(0, a_digits[i], r, i, used); | 863 _MulAddArgs[MA_MULTIPLIER] = a_digits[i]; |
| 864 _mulAdd(_MulAddArgs, digits, 0, r_digits, i, used); |
| 865 r_digits[i + used] = _MulAddArgs[MA_CARRY_OUT]; |
| 851 } | 866 } |
| 852 r._clamp(); | 867 r._clamp(); |
| 853 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. | 868 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. |
| 854 } | 869 } |
| 855 | 870 |
| 856 // r = this^2, r != this. | 871 // r = this^2, r != this. |
| 857 void _sqrTo(_Bigint r) { | 872 void _sqrTo(_Bigint r) { |
| 858 var used = _used; | 873 var used = _used; |
| 859 var r_used = 2 * used; | 874 var r_used = 2 * used; |
| 860 r._ensureLength(r_used); | 875 r._ensureLength(r_used); |
| 861 var digits = _digits; | 876 var digits = _digits; |
| 862 var r_digits = r._digits; | 877 var r_digits = r._digits; |
| 863 var i = r_used; | 878 var i = r_used; |
| 864 while (--i >= 0) { | 879 while (--i >= 0) { |
| 865 r_digits[i] = 0; | 880 r_digits[i] = 0; |
| 866 } | 881 } |
| 867 for (i = 0; i < used - 1; ++i) { | 882 for (i = 0; i < used - 1; ++i) { |
| 868 var c = _am(i, digits[i], r, 2*i, 1); | 883 _MulAddArgs[MA_MULTIPLIER] = digits[i]; |
| 884 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); |
| 885 var c = _MulAddArgs[MA_CARRY_OUT]; |
| 869 var d = r_digits[i + used]; | 886 var d = r_digits[i + used]; |
| 870 d += _amc(i + 1, digits[i] << 1, r, 2*i + 1, c, used - i - 1); | 887 d += _mulAddc(digits[i] << 1, digits, i + 1, |
| 888 r_digits, 2*i + 1, c, used - i - 1); |
| 871 if (d >= DIGIT_BASE) { | 889 if (d >= DIGIT_BASE) { |
| 872 r_digits[i + used] = d - DIGIT_BASE; | 890 r_digits[i + used] = d - DIGIT_BASE; |
| 873 r_digits[i + used + 1] = 1; | 891 r_digits[i + used + 1] = 1; |
| 874 } else { | 892 } else { |
| 875 r_digits[i + used] = d; | 893 r_digits[i + used] = d; |
| 876 } | 894 } |
| 877 } | 895 } |
| 878 if (r_used > 0) { | 896 if (r_used > 0) { |
| 879 r_digits[r_used - 1] += _am(i, digits[i], r, 2*i, 1); | 897 _MulAddArgs[MA_MULTIPLIER] = digits[i]; |
| 898 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); |
| 899 r_digits[r_used - 1] += _MulAddArgs[MA_CARRY_OUT]; |
| 880 } | 900 } |
| 881 r._used = r_used; | 901 r._used = r_used; |
| 882 r._neg = false; | 902 r._neg = false; |
| 883 r._clamp(); | 903 r._clamp(); |
| 884 } | 904 } |
| 885 | 905 |
| 886 // Truncating division and remainder. | 906 // Truncating division and remainder. |
| 887 // If q != null, q = trunc(this / a). | 907 // If q != null, q = trunc(this / a). |
| 888 // If r != null, r = this - a * trunc(this / a). | 908 // If r != null, r = this - a * trunc(this / a). |
| 889 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { | 909 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 var i = r._used; | 943 var i = r._used; |
| 924 var j = i - y_used; | 944 var j = i - y_used; |
| 925 _Bigint t = (q == null) ? new _Bigint() : q; | 945 _Bigint t = (q == null) ? new _Bigint() : q; |
| 926 y._dlShiftTo(j, t); | 946 y._dlShiftTo(j, t); |
| 927 var r_digits = r._digits; | 947 var r_digits = r._digits; |
| 928 if (r._compareTo(t) >= 0) { | 948 if (r._compareTo(t) >= 0) { |
| 929 r_digits[r._used++] = 1; | 949 r_digits[r._used++] = 1; |
| 930 r._subTo(t, r); | 950 r._subTo(t, r); |
| 931 } | 951 } |
| 932 ONE._dlShiftTo(y_used, t); | 952 ONE._dlShiftTo(y_used, t); |
| 933 t._subTo(y, y); // Negate y so we can replace sub with _am later. | 953 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. |
| 934 while (y._used < y_used) { | 954 while (y._used < y_used) { |
| 935 y_digits[y._used++] = 0; | 955 y_digits[y._used++] = 0; |
| 936 } | 956 } |
| 937 while (--j >= 0) { | 957 while (--j >= 0) { |
| 938 // Estimate quotient digit. | 958 // Estimate quotient digit. |
| 939 // TODO(regis): Move the expensive mint division below to a function that | 959 // TODO(regis): Move the expensive mint division below to a function that |
| 940 // can be intrinsified using an uint64_t by uint32_t division instruction, | 960 // can be intrinsified using an uint64_t by uint32_t division instruction, |
| 941 // e.g. qd = _estqd(r_digits, --i, y0). | 961 // e.g. qd = _estqd(r_digits, --i, y0). |
| 942 var qd; | 962 var qd; // TODO(regis): Is it more efficient to use |
| 963 //_MulAddArgs[MA_MULTIPLIER] directly instead of qd (Mint)? |
| 943 if (r_digits[--i] == y0) { | 964 if (r_digits[--i] == y0) { |
| 944 qd = DIGIT_MASK; | 965 qd = DIGIT_MASK; |
| 945 } else { | 966 } else { |
| 946 // Chop off one bit, since a Mint cannot hold 2 DIGITs. | 967 // Chop off one bit, since a Mint cannot hold 2 DIGITs. |
| 947 qd = ((r_digits[i] << (DIGIT_BITS - 1)) | (r_digits[i - 1] >> 1)) ~/ yt; | 968 qd = ((r_digits[i] << (DIGIT_BITS - 1)) | (r_digits[i - 1] >> 1)) ~/ yt; |
| 969 if (qd > DIGIT_MASK) { |
| 970 qd = DIGIT_MASK; |
| 971 } |
| 948 } | 972 } |
| 949 if ((r_digits[i] += y._am(0, qd, r, j, y_used)) < qd) { // Try it out. | 973 _MulAddArgs[MA_MULTIPLIER] = qd; |
| 974 _mulAdd(_MulAddArgs, y_digits, 0, r_digits, j, y_used); |
| 975 if ((r_digits[i] += _MulAddArgs[MA_CARRY_OUT]) < qd) { |
| 950 y._dlShiftTo(j, t); | 976 y._dlShiftTo(j, t); |
| 951 r._subTo(t, r); | 977 r._subTo(t, r); |
| 952 while (r_digits[i] < --qd) { | 978 while (r_digits[i] < --qd) { |
| 953 r._subTo(t, r); | 979 r._subTo(t, r); |
| 954 } | 980 } |
| 955 } | 981 } |
| 956 } | 982 } |
| 957 if (q != null) { | 983 if (q != null) { |
| 958 r._drShiftTo(y_used, q); | 984 r._drShiftTo(y_used, q); |
| 959 if (_neg != a._neg) { | 985 if (_neg != a._neg) { |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 var r = new _Bigint(); | 1355 var r = new _Bigint(); |
| 1330 x._copyTo(r); | 1356 x._copyTo(r); |
| 1331 _reduce(r); | 1357 _reduce(r); |
| 1332 return r; | 1358 return r; |
| 1333 } | 1359 } |
| 1334 | 1360 |
| 1335 // x = x/R mod _m | 1361 // x = x/R mod _m |
| 1336 void _reduce(_Bigint x) { | 1362 void _reduce(_Bigint x) { |
| 1337 x._ensureLength(_mused2 + 1); | 1363 x._ensureLength(_mused2 + 1); |
| 1338 var x_digits = x._digits; | 1364 var x_digits = x._digits; |
| 1339 while (x._used <= _mused2) { // Pad x so _am has enough room later. | 1365 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. |
| 1340 x_digits[x._used++] = 0; | 1366 x_digits[x._used++] = 0; |
| 1341 } | 1367 } |
| 1342 var m_used = _m._used; | 1368 var m_used = _m._used; |
| 1369 var m_digits = _m._digits; |
| 1343 for (var i = 0; i < m_used; ++i) { | 1370 for (var i = 0; i < m_used; ++i) { |
| 1344 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE. | 1371 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE. |
| 1345 var j = x_digits[i] & _Bigint.DIGIT2_MASK; | 1372 var j = x_digits[i] & _Bigint.DIGIT2_MASK; |
| 1346 var u0 = (j*_mpl + (((j*_mph + (x_digits[i] >> _Bigint.DIGIT2_BITS) | 1373 var u0 = (j*_mpl + (((j*_mph + (x_digits[i] >> _Bigint.DIGIT2_BITS) |
| 1347 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK; | 1374 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK; |
| 1348 // Use _am to combine the multiply-shift-add into one call. | 1375 // Use _mulAdd to combine the multiply-shift-add into one call. |
| 1349 j = i + m_used; | 1376 j = i + m_used; |
| 1350 var digit = x_digits[j]; | 1377 var digit = x_digits[j]; |
| 1351 digit += _m ._am(0, u0, x, i, m_used); | 1378 _Bigint._MulAddArgs[_Bigint.MA_MULTIPLIER] = u0; |
| 1379 _Bigint._mulAdd(_Bigint._MulAddArgs, m_digits, 0, x_digits, i, m_used); |
| 1380 digit += _Bigint._MulAddArgs[_Bigint.MA_CARRY_OUT]; |
| 1352 // Propagate carry. | 1381 // Propagate carry. |
| 1353 while (digit >= _Bigint.DIGIT_BASE) { | 1382 while (digit >= _Bigint.DIGIT_BASE) { |
| 1354 digit -= _Bigint.DIGIT_BASE; | 1383 digit -= _Bigint.DIGIT_BASE; |
| 1355 x_digits[j++] = digit; | 1384 x_digits[j++] = digit; |
| 1356 digit = x_digits[j]; | 1385 digit = x_digits[j]; |
| 1357 digit++; | 1386 digit++; |
| 1358 } | 1387 } |
| 1359 x_digits[j] = digit; | 1388 x_digits[j] = digit; |
| 1360 } | 1389 } |
| 1361 x._clamp(); | 1390 x._clamp(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 void _sqrTo(_Bigint x, _Bigint r) { | 1438 void _sqrTo(_Bigint x, _Bigint r) { |
| 1410 x._sqrTo(r); | 1439 x._sqrTo(r); |
| 1411 _reduce(r); | 1440 _reduce(r); |
| 1412 } | 1441 } |
| 1413 | 1442 |
| 1414 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1443 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1415 x._mulTo(y, r); | 1444 x._mulTo(y, r); |
| 1416 _reduce(r); | 1445 _reduce(r); |
| 1417 } | 1446 } |
| 1418 } | 1447 } |
| OLD | NEW |