Chromium Code Reviews| 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 Uint32List _MulAddArgs = new Uint32List(2); | |
|
srdjan
2014/09/19 00:26:08
add final
regis
2014/09/19 02:01:34
Done.
| |
| 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 static void _mulAdd(Uint32List args, | |
| 795 Uint32List m_digits, int i, | |
| 796 Uint32List a_digits, int j, int n) { | |
| 797 int x = args[MA_MULTIPLIER]; | |
| 788 if (x == 0) { | 798 if (x == 0) { |
| 789 // No-op if x is 0. | 799 // No-op if x is 0. |
| 790 return 0; | 800 args[MA_CARRY_OUT] = 0; |
| 801 return; | |
| 791 } | 802 } |
| 792 int c = 0; | 803 int c = 0; |
| 793 int xl = x & DIGIT2_MASK; | 804 int xl = x & DIGIT2_MASK; |
| 794 int xh = x >> DIGIT2_BITS; | 805 int xh = x >> DIGIT2_BITS; |
| 795 var digits = _digits; | |
| 796 var w_digits = w._digits; | |
| 797 while (--n >= 0) { | 806 while (--n >= 0) { |
| 798 int l = digits[i] & DIGIT2_MASK; | 807 int l = m_digits[i] & DIGIT2_MASK; |
| 799 int h = digits[i++] >> DIGIT2_BITS; | 808 int h = m_digits[i++] >> DIGIT2_BITS; |
| 800 int m = xh*l + h*xl; | 809 int m = xh*l + h*xl; |
| 801 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w_digits[j] + c; | 810 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 802 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 811 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 803 w_digits[j++] = l & DIGIT_MASK; | 812 a_digits[j++] = l & DIGIT_MASK; |
| 804 } | 813 } |
| 805 return c; | 814 args[MA_CARRY_OUT] = c; |
| 806 } | 815 } |
| 807 | 816 |
| 808 // Accumulate multiply with carry. | 817 // Multiply and accumulate with carry in. |
| 809 // this[i..i+n-1]: bigint multiplicand. | 818 // Input: |
| 810 // x: digit multiplier, 0 <= x < 2*DIGIT_BASE (i.e. 33-bit multiplier). | 819 // x: multiplier digit, 0 <= x < 2*DIGIT_BASE (i.e. 33-bit multiplier). |
| 811 // w[j..j+n-1]: bigint accumulator. | 820 // m_digits[i..i+n-1]: multiplicand digits. |
| 812 // c: int carry in. | 821 // a_digits[j..j+n-1]: accumulator digits. |
| 813 // Returns carry out. | 822 // c: carry in. |
| 814 // w[j..j+n-1] += this[i..i+n-1] * x + c. | 823 // Operation: |
| 815 // Returns carry out. | 824 // 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) { | 825 // Output: |
| 826 // carry out. | |
| 827 // TODO(regis): Use an argument buffer as in _mulAdd. | |
| 828 static int _mulAddc(int x, Uint32List m_digits, int i, | |
| 829 Uint32List a_digits, int j, int c, int n) { | |
| 817 if (x == 0 && c == 0) { | 830 if (x == 0 && c == 0) { |
| 818 // No-op if both x and c are 0. | 831 // No-op if both x and c are 0. |
| 819 return 0; | 832 return 0; |
| 820 } | 833 } |
| 821 int xl = x & DIGIT2_MASK; | 834 int xl = x & DIGIT2_MASK; |
| 822 int xh = x >> DIGIT2_BITS; | 835 int xh = x >> DIGIT2_BITS; |
| 823 var digits = _digits; | |
| 824 var w_digits = w._digits; | |
| 825 while (--n >= 0) { | 836 while (--n >= 0) { |
| 826 int l = digits[i] & DIGIT2_MASK; | 837 int l = m_digits[i] & DIGIT2_MASK; |
| 827 int h = digits[i++] >> DIGIT2_BITS; | 838 int h = m_digits[i++] >> DIGIT2_BITS; |
| 828 int m = xh*l + h*xl; | 839 int m = xh*l + h*xl; |
| 829 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w_digits[j] + c; | 840 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 830 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 841 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 831 w_digits[j++] = l & DIGIT_MASK; | 842 a_digits[j++] = l & DIGIT_MASK; |
| 832 } | 843 } |
| 833 return c; | 844 return c; |
| 834 } | 845 } |
| 835 | 846 |
| 836 // r = this * a. | 847 // r = this * a. |
| 837 void _mulTo(_Bigint a, _Bigint r) { | 848 void _mulTo(_Bigint a, _Bigint r) { |
| 838 // TODO(regis): Use karatsuba multiplication when appropriate. | 849 // TODO(regis): Use karatsuba multiplication when appropriate. |
| 839 var used = _used; | 850 var used = _used; |
| 840 var a_used = a._used; | 851 var a_used = a._used; |
| 841 var i = used; | 852 var i = used; |
| 842 r._ensureLength(i + a_used); | 853 r._ensureLength(i + a_used); |
| 854 var digits = _digits; | |
| 843 var a_digits = a._digits; | 855 var a_digits = a._digits; |
| 844 var r_digits = r._digits; | 856 var r_digits = r._digits; |
| 845 r._used = i + a_used; | 857 r._used = i + a_used; |
| 846 while (--i >= 0) { | 858 while (--i >= 0) { |
| 847 r_digits[i] = 0; | 859 r_digits[i] = 0; |
| 848 } | 860 } |
| 849 for (i = 0; i < a_used; ++i) { | 861 for (i = 0; i < a_used; ++i) { |
|
srdjan
2014/09/19 00:26:08
Maybe add a comment: Using Uint32List for argument
regis
2014/09/19 02:01:34
I've added a comment at the declaration of _mulAdd
| |
| 850 r_digits[i + used] = _am(0, a_digits[i], r, i, used); | 862 _MulAddArgs[MA_MULTIPLIER] = a_digits[i]; |
| 863 _mulAdd(_MulAddArgs, digits, 0, r_digits, i, used); | |
| 864 r_digits[i + used] = _MulAddArgs[MA_CARRY_OUT]; | |
| 851 } | 865 } |
| 852 r._clamp(); | 866 r._clamp(); |
| 853 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. | 867 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. |
| 854 } | 868 } |
| 855 | 869 |
| 856 // r = this^2, r != this. | 870 // r = this^2, r != this. |
| 857 void _sqrTo(_Bigint r) { | 871 void _sqrTo(_Bigint r) { |
| 858 var used = _used; | 872 var used = _used; |
| 859 var r_used = 2 * used; | 873 var r_used = 2 * used; |
| 860 r._ensureLength(r_used); | 874 r._ensureLength(r_used); |
| 861 var digits = _digits; | 875 var digits = _digits; |
| 862 var r_digits = r._digits; | 876 var r_digits = r._digits; |
| 863 var i = r_used; | 877 var i = r_used; |
| 864 while (--i >= 0) { | 878 while (--i >= 0) { |
| 865 r_digits[i] = 0; | 879 r_digits[i] = 0; |
| 866 } | 880 } |
| 867 for (i = 0; i < used - 1; ++i) { | 881 for (i = 0; i < used - 1; ++i) { |
| 868 var c = _am(i, digits[i], r, 2*i, 1); | 882 _MulAddArgs[MA_MULTIPLIER] = digits[i]; |
| 883 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); | |
| 884 var c = _MulAddArgs[MA_CARRY_OUT]; | |
| 869 var d = r_digits[i + used]; | 885 var d = r_digits[i + used]; |
| 870 d += _amc(i + 1, digits[i] << 1, r, 2*i + 1, c, used - i - 1); | 886 d += _mulAddc(digits[i] << 1, digits, i + 1, |
| 887 r_digits, 2*i + 1, c, used - i - 1); | |
| 871 if (d >= DIGIT_BASE) { | 888 if (d >= DIGIT_BASE) { |
| 872 r_digits[i + used] = d - DIGIT_BASE; | 889 r_digits[i + used] = d - DIGIT_BASE; |
| 873 r_digits[i + used + 1] = 1; | 890 r_digits[i + used + 1] = 1; |
| 874 } else { | 891 } else { |
| 875 r_digits[i + used] = d; | 892 r_digits[i + used] = d; |
| 876 } | 893 } |
| 877 } | 894 } |
| 878 if (r_used > 0) { | 895 if (r_used > 0) { |
| 879 r_digits[r_used - 1] += _am(i, digits[i], r, 2*i, 1); | 896 _MulAddArgs[MA_MULTIPLIER] = digits[i]; |
| 897 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); | |
| 898 r_digits[r_used - 1] += _MulAddArgs[MA_CARRY_OUT]; | |
| 880 } | 899 } |
| 881 r._used = r_used; | 900 r._used = r_used; |
| 882 r._neg = false; | 901 r._neg = false; |
| 883 r._clamp(); | 902 r._clamp(); |
| 884 } | 903 } |
| 885 | 904 |
| 905 | |
|
srdjan
2014/09/19 00:26:08
In Dart file we have most often 1 empty line betwe
regis
2014/09/19 02:01:34
Done.
| |
| 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) { |
| 890 if (a._used == 0) return; | 910 if (a._used == 0) return; |
| 891 if (_used < a._used) { | 911 if (_used < a._used) { |
| 892 if (q != null) { | 912 if (q != null) { |
| 893 // Set q to 0. | 913 // Set q to 0. |
| 894 q._neg = false; | 914 q._neg = false; |
| 895 q._used = 0; | 915 q._used = 0; |
| (...skipping 27 matching lines...) Expand all 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 |