| 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 | |
| 69 // Digit conversion table for parsing. | 64 // Digit conversion table for parsing. |
| 70 static final Map<int, int> DIGIT_TABLE = _createDigitTable(); | 65 static final Map<int, int> DIGIT_TABLE = _createDigitTable(); |
| 71 | 66 |
| 72 // Internal data structure. | 67 // Internal data structure. |
| 73 bool get _neg native "Bigint_getNeg"; | 68 bool get _neg native "Bigint_getNeg"; |
| 74 void set _neg(bool neg) native "Bigint_setNeg"; | 69 void set _neg(bool neg) native "Bigint_setNeg"; |
| 75 int get _used native "Bigint_getUsed"; | 70 int get _used native "Bigint_getUsed"; |
| 76 void set _used(int used) native "Bigint_setUsed"; | 71 void set _used(int used) native "Bigint_setUsed"; |
| 77 Uint32List get _digits native "Bigint_getDigits"; | 72 Uint32List get _digits native "Bigint_getDigits"; |
| 78 void set _digits(Uint32List digits) { | 73 void set _digits(Uint32List digits) { |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 r_neg = !r_neg; | 772 r_neg = !r_neg; |
| 778 a._absSubTo(this, r); | 773 a._absSubTo(this, r); |
| 779 } | 774 } |
| 780 } | 775 } |
| 781 r._neg = r_neg; | 776 r._neg = r_neg; |
| 782 return r; | 777 return r; |
| 783 } | 778 } |
| 784 | 779 |
| 785 // Multiply and accumulate. | 780 // Multiply and accumulate. |
| 786 // Input: | 781 // Input: |
| 787 // args[MA_MULTIPLIER]: multiplier digit, 0 <= x < DIGIT_BASE (i.e. 32-bit). | 782 // x_digits[xi]: multiplier digit x. |
| 788 // m_digits[i..i+n-1]: multiplicand digits. | 783 // m_digits[i..i+n-1]: multiplicand digits. |
| 789 // a_digits[j..j+n-1]: accumulator digits. | 784 // a_digits[j..j+n-1]: accumulator digits. |
| 790 // Operation: | 785 // Operation: |
| 791 // a_digits[j..j+n-1] += x*m_digits[i..i+n-1]. | 786 // a_digits[j..j+n] += x*m_digits[i..i+n-1]. |
| 792 // Output: | 787 static void _mulAdd(Uint32List x_digits, int xi, |
| 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, | 788 Uint32List m_digits, int i, |
| 797 Uint32List a_digits, int j, int n) { | 789 Uint32List a_digits, int j, int n) { |
| 798 int x = args[MA_MULTIPLIER]; | 790 int x = x_digits[xi]; |
| 799 if (x == 0) { | 791 if (x == 0) { |
| 800 // No-op if x is 0. | 792 // No-op if x is 0. |
| 801 args[MA_CARRY_OUT] = 0; | |
| 802 return; | 793 return; |
| 803 } | 794 } |
| 804 int c = 0; | 795 int c = 0; |
| 805 int xl = x & DIGIT2_MASK; | 796 int xl = x & DIGIT2_MASK; |
| 806 int xh = x >> DIGIT2_BITS; | 797 int xh = x >> DIGIT2_BITS; |
| 807 while (--n >= 0) { | 798 while (--n >= 0) { |
| 808 int l = m_digits[i] & DIGIT2_MASK; | 799 int l = m_digits[i] & DIGIT2_MASK; |
| 809 int h = m_digits[i++] >> DIGIT2_BITS; | 800 int h = m_digits[i++] >> DIGIT2_BITS; |
| 810 int m = xh*l + h*xl; | 801 int m = xh*l + h*xl; |
| 811 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; | 802 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 812 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 803 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 813 a_digits[j++] = l & DIGIT_MASK; | 804 a_digits[j++] = l & DIGIT_MASK; |
| 814 } | 805 } |
| 815 args[MA_CARRY_OUT] = c; | 806 while (c != 0) { |
| 807 int l = a_digits[j] + c; |
| 808 c = l >> DIGIT_BITS; |
| 809 a_digits[j++] = l & DIGIT_MASK; |
| 810 } |
| 816 } | 811 } |
| 817 | 812 |
| 818 // Square and accumulate. | 813 // Square and accumulate. |
| 819 // Input: | 814 // Input: |
| 820 // x_digits[i..used-1]: digits of operand being squared. | 815 // x_digits[i..used-1]: digits of operand being squared. |
| 821 // a_digits[2*i..i+used-1]: accumulator digits. | 816 // a_digits[2*i..i+used-1]: accumulator digits. |
| 822 // Operation: | 817 // Operation: |
| 823 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + | 818 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + |
| 824 // 2*x_digits[i]*x_digits[i+1..used-1]. | 819 // 2*x_digits[i]*x_digits[i+1..used-1]. |
| 825 static void _sqrAdd(Uint32List x_digits, int i, | 820 static void _sqrAdd(Uint32List x_digits, int i, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 855 } else { | 850 } else { |
| 856 a_digits[i + used] = c; | 851 a_digits[i + used] = c; |
| 857 } | 852 } |
| 858 } | 853 } |
| 859 | 854 |
| 860 // r = this * a. | 855 // r = this * a. |
| 861 void _mulTo(_Bigint a, _Bigint r) { | 856 void _mulTo(_Bigint a, _Bigint r) { |
| 862 // TODO(regis): Use karatsuba multiplication when appropriate. | 857 // TODO(regis): Use karatsuba multiplication when appropriate. |
| 863 var used = _used; | 858 var used = _used; |
| 864 var a_used = a._used; | 859 var a_used = a._used; |
| 865 var i = used; | 860 var r_used = used + a_used; |
| 866 r._ensureLength(i + a_used); | 861 r._ensureLength(r_used); |
| 867 var digits = _digits; | 862 var digits = _digits; |
| 868 var a_digits = a._digits; | 863 var a_digits = a._digits; |
| 869 var r_digits = r._digits; | 864 var r_digits = r._digits; |
| 870 r._used = i + a_used; | 865 r._used = r_used; |
| 866 var i = r_used; |
| 871 while (--i >= 0) { | 867 while (--i >= 0) { |
| 872 r_digits[i] = 0; | 868 r_digits[i] = 0; |
| 873 } | 869 } |
| 874 for (i = 0; i < a_used; ++i) { | 870 for (i = 0; i < a_used; ++i) { |
| 875 _MulAddArgs[MA_MULTIPLIER] = a_digits[i]; | 871 _mulAdd(a_digits, i, digits, 0, r_digits, i, used); |
| 876 _mulAdd(_MulAddArgs, digits, 0, r_digits, i, used); | |
| 877 r_digits[i + used] = _MulAddArgs[MA_CARRY_OUT]; | |
| 878 } | 872 } |
| 879 r._clamp(); | 873 r._clamp(); |
| 880 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. | 874 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. |
| 881 } | 875 } |
| 882 | 876 |
| 883 // r = this^2, r != this. | 877 // r = this^2, r != this. |
| 884 void _sqrTo(_Bigint r) { | 878 void _sqrTo(_Bigint r) { |
| 885 var used = _used; | 879 var used = _used; |
| 886 var r_used = 2 * used; | 880 var r_used = 2 * used; |
| 887 r._ensureLength(r_used); | 881 r._ensureLength(r_used); |
| 888 var digits = _digits; | 882 var digits = _digits; |
| 889 var r_digits = r._digits; | 883 var r_digits = r._digits; |
| 890 var i = r_used; | 884 var i = r_used; |
| 891 while (--i >= 0) { | 885 while (--i >= 0) { |
| 892 r_digits[i] = 0; | 886 r_digits[i] = 0; |
| 893 } | 887 } |
| 894 for (i = 0; i < used - 1; ++i) { | 888 for (i = 0; i < used - 1; ++i) { |
| 895 _sqrAdd(digits, i, r_digits, used); | 889 _sqrAdd(digits, i, r_digits, used); |
| 896 } | 890 } |
| 897 if (r_used > 0) { | 891 if (r_used > 0) { |
| 898 _MulAddArgs[MA_MULTIPLIER] = digits[i]; | 892 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); |
| 899 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); | |
| 900 r_digits[r_used - 1] += _MulAddArgs[MA_CARRY_OUT]; | |
| 901 } | 893 } |
| 902 r._used = r_used; | 894 r._used = r_used; |
| 903 r._neg = false; | 895 r._neg = false; |
| 904 r._clamp(); | 896 r._clamp(); |
| 905 } | 897 } |
| 906 | 898 |
| 907 // Truncating division and remainder. | 899 // Truncating division and remainder. |
| 908 // If q != null, q = trunc(this / a). | 900 // If q != null, q = trunc(this / a). |
| 909 // If r != null, r = this - a * trunc(this / a). | 901 // If r != null, r = this - a * trunc(this / a). |
| 910 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { | 902 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 var r_digits = r._digits; | 940 var r_digits = r._digits; |
| 949 if (r._compareTo(t) >= 0) { | 941 if (r._compareTo(t) >= 0) { |
| 950 r_digits[r._used++] = 1; | 942 r_digits[r._used++] = 1; |
| 951 r._subTo(t, r); | 943 r._subTo(t, r); |
| 952 } | 944 } |
| 953 ONE._dlShiftTo(y_used, t); | 945 ONE._dlShiftTo(y_used, t); |
| 954 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. | 946 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. |
| 955 while (y._used < y_used) { | 947 while (y._used < y_used) { |
| 956 y_digits[y._used++] = 0; | 948 y_digits[y._used++] = 0; |
| 957 } | 949 } |
| 950 var qd_digit = new Uint32List(1); |
| 958 while (--j >= 0) { | 951 while (--j >= 0) { |
| 959 // Estimate quotient digit. | 952 // Estimate quotient digit. |
| 960 // TODO(regis): Move the expensive mint division below to a function that | 953 // TODO(regis): Move the expensive mint division below to a function that |
| 961 // can be intrinsified using an uint64_t by uint32_t division instruction, | 954 // can be intrinsified using an uint64_t by uint32_t division instruction, |
| 962 // e.g. qd = _estqd(r_digits, --i, y0). | 955 // e.g. qd = _estqd(r_digits, --i, y0). |
| 963 var qd; // TODO(regis): Is it more efficient to use | |
| 964 //_MulAddArgs[MA_MULTIPLIER] directly instead of qd (Mint)? | |
| 965 if (r_digits[--i] == y0) { | 956 if (r_digits[--i] == y0) { |
| 966 qd = DIGIT_MASK; | 957 qd_digit[0] = DIGIT_MASK; |
| 967 } else { | 958 } else { |
| 968 // Chop off one bit, since a Mint cannot hold 2 DIGITs. | 959 // Chop off one bit, since a Mint cannot hold 2 DIGITs. |
| 969 qd = ((r_digits[i] << (DIGIT_BITS - 1)) | (r_digits[i - 1] >> 1)) ~/ yt; | 960 var qd = |
| 961 ((r_digits[i] << (DIGIT_BITS - 1)) | (r_digits[i - 1] >> 1)) ~/ yt; |
| 970 if (qd > DIGIT_MASK) { | 962 if (qd > DIGIT_MASK) { |
| 971 qd = DIGIT_MASK; | 963 qd_digit[0] = DIGIT_MASK; |
| 964 } else { |
| 965 qd_digit[0] = qd; |
| 972 } | 966 } |
| 973 } | 967 } |
| 974 _MulAddArgs[MA_MULTIPLIER] = qd; | 968 _mulAdd(qd_digit, 0, y_digits, 0, r_digits, j, y_used); |
| 975 _mulAdd(_MulAddArgs, y_digits, 0, r_digits, j, y_used); | 969 if (r_digits[i] < qd_digit[0]) { |
| 976 if ((r_digits[i] += _MulAddArgs[MA_CARRY_OUT]) < qd) { | |
| 977 y._dlShiftTo(j, t); | 970 y._dlShiftTo(j, t); |
| 978 r._subTo(t, r); | 971 r._subTo(t, r); |
| 979 while (r_digits[i] < --qd) { | 972 while (r_digits[i] < --qd_digit[0]) { |
| 980 r._subTo(t, r); | 973 r._subTo(t, r); |
| 981 } | 974 } |
| 982 } | 975 } |
| 983 } | 976 } |
| 984 if (q != null) { | 977 if (q != null) { |
| 985 r._drShiftTo(y_used, q); | 978 r._drShiftTo(y_used, q); |
| 986 if (_neg != a._neg) { | 979 if (_neg != a._neg) { |
| 987 ZERO._subTo(q, q); | 980 ZERO._subTo(q, q); |
| 988 } | 981 } |
| 989 } | 982 } |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 class _Reduction { | 1311 class _Reduction { |
| 1319 _Bigint _convert(_Bigint x); | 1312 _Bigint _convert(_Bigint x); |
| 1320 _Bigint _revert(_Bigint x); | 1313 _Bigint _revert(_Bigint x); |
| 1321 void _mulTo(_Bigint x, _Bigint y, _Bigint r); | 1314 void _mulTo(_Bigint x, _Bigint y, _Bigint r); |
| 1322 void _sqrTo(_Bigint x, _Bigint r); | 1315 void _sqrTo(_Bigint x, _Bigint r); |
| 1323 } | 1316 } |
| 1324 | 1317 |
| 1325 // Montgomery reduction on _Bigint. | 1318 // Montgomery reduction on _Bigint. |
| 1326 class _Montgomery implements _Reduction { | 1319 class _Montgomery implements _Reduction { |
| 1327 _Bigint _m; | 1320 _Bigint _m; |
| 1328 var _mp; | 1321 int _mp; |
| 1329 var _mpl; | 1322 int _mpl; |
| 1330 var _mph; | 1323 int _mph; |
| 1331 var _um; | 1324 int _um; |
| 1332 var _mused2; | 1325 int _mused2; |
| 1326 Uint32List _u0digit; |
| 1333 | 1327 |
| 1334 _Montgomery(m) { | 1328 _Montgomery(m) { |
| 1335 _m = m._toBigint(); | 1329 _m = m._toBigint(); |
| 1336 _mp = _m._invDigit(); | 1330 _mp = _m._invDigit(); |
| 1337 _mpl = _mp & _Bigint.DIGIT2_MASK; | 1331 _mpl = _mp & _Bigint.DIGIT2_MASK; |
| 1338 _mph = _mp >> _Bigint.DIGIT2_BITS; | 1332 _mph = _mp >> _Bigint.DIGIT2_BITS; |
| 1339 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; | 1333 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; |
| 1340 _mused2 = 2*_m._used; | 1334 _mused2 = 2*_m._used; |
| 1335 _u0digit = new Uint32List(1); |
| 1341 } | 1336 } |
| 1342 | 1337 |
| 1343 // Return x*R mod _m | 1338 // Return x*R mod _m |
| 1344 _Bigint _convert(_Bigint x) { | 1339 _Bigint _convert(_Bigint x) { |
| 1345 var r = new _Bigint(); | 1340 var r = new _Bigint(); |
| 1346 x.abs()._dlShiftTo(_m._used, r); | 1341 x.abs()._dlShiftTo(_m._used, r); |
| 1347 r._divRemTo(_m, null, r); | 1342 r._divRemTo(_m, null, r); |
| 1348 if (x._neg && !r._neg && r._used > 0) { | 1343 if (x._neg && !r._neg && r._used > 0) { |
| 1349 _m._subTo(r, r); | 1344 _m._subTo(r, r); |
| 1350 } | 1345 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1364 x._ensureLength(_mused2 + 1); | 1359 x._ensureLength(_mused2 + 1); |
| 1365 var x_digits = x._digits; | 1360 var x_digits = x._digits; |
| 1366 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. | 1361 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. |
| 1367 x_digits[x._used++] = 0; | 1362 x_digits[x._used++] = 0; |
| 1368 } | 1363 } |
| 1369 var m_used = _m._used; | 1364 var m_used = _m._used; |
| 1370 var m_digits = _m._digits; | 1365 var m_digits = _m._digits; |
| 1371 for (var i = 0; i < m_used; ++i) { | 1366 for (var i = 0; i < m_used; ++i) { |
| 1372 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE. | 1367 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE. |
| 1373 var j = x_digits[i] & _Bigint.DIGIT2_MASK; | 1368 var j = x_digits[i] & _Bigint.DIGIT2_MASK; |
| 1374 var u0 = (j*_mpl + (((j*_mph + (x_digits[i] >> _Bigint.DIGIT2_BITS) | 1369 _u0digit[0] = (j*_mpl + (((j*_mph + (x_digits[i] >> _Bigint.DIGIT2_BITS) |
| 1375 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK; | 1370 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK; |
| 1376 // Use _mulAdd to combine the multiply-shift-add into one call. | 1371 // Use _mulAdd to combine the multiply-shift-add into one call. |
| 1377 j = i + m_used; | 1372 _Bigint._mulAdd(_u0digit, 0, m_digits, 0, x_digits, i, m_used); |
| 1378 var digit = x_digits[j]; | |
| 1379 _Bigint._MulAddArgs[_Bigint.MA_MULTIPLIER] = u0; | |
| 1380 _Bigint._mulAdd(_Bigint._MulAddArgs, m_digits, 0, x_digits, i, m_used); | |
| 1381 digit += _Bigint._MulAddArgs[_Bigint.MA_CARRY_OUT]; | |
| 1382 // Propagate carry. | |
| 1383 while (digit >= _Bigint.DIGIT_BASE) { | |
| 1384 digit -= _Bigint.DIGIT_BASE; | |
| 1385 x_digits[j++] = digit; | |
| 1386 digit = x_digits[j]; | |
| 1387 digit++; | |
| 1388 } | |
| 1389 x_digits[j] = digit; | |
| 1390 } | 1373 } |
| 1391 x._clamp(); | 1374 x._clamp(); |
| 1392 x._drShiftTo(m_used, x); | 1375 x._drShiftTo(m_used, x); |
| 1393 if (x._compareTo(_m) >= 0) { | 1376 if (x._compareTo(_m) >= 0) { |
| 1394 x._subTo(_m, x); | 1377 x._subTo(_m, x); |
| 1395 } | 1378 } |
| 1396 } | 1379 } |
| 1397 | 1380 |
| 1398 // r = x^2/R mod _m ; x != r | 1381 // r = x^2/R mod _m ; x != r |
| 1399 void _sqrTo(_Bigint x, _Bigint r) { | 1382 void _sqrTo(_Bigint x, _Bigint r) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 void _sqrTo(_Bigint x, _Bigint r) { | 1422 void _sqrTo(_Bigint x, _Bigint r) { |
| 1440 x._sqrTo(r); | 1423 x._sqrTo(r); |
| 1441 _reduce(r); | 1424 _reduce(r); |
| 1442 } | 1425 } |
| 1443 | 1426 |
| 1444 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1427 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1445 x._mulTo(y, r); | 1428 x._mulTo(y, r); |
| 1446 _reduce(r); | 1429 _reduce(r); |
| 1447 } | 1430 } |
| 1448 } | 1431 } |
| OLD | NEW |