| 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 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 int l = m_digits[i] & DIGIT2_MASK; | 808 int l = m_digits[i] & DIGIT2_MASK; |
| 809 int h = m_digits[i++] >> DIGIT2_BITS; | 809 int h = m_digits[i++] >> DIGIT2_BITS; |
| 810 int m = xh*l + h*xl; | 810 int m = xh*l + h*xl; |
| 811 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; | 811 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 812 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 812 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 813 a_digits[j++] = l & DIGIT_MASK; | 813 a_digits[j++] = l & DIGIT_MASK; |
| 814 } | 814 } |
| 815 args[MA_CARRY_OUT] = c; | 815 args[MA_CARRY_OUT] = c; |
| 816 } | 816 } |
| 817 | 817 |
| 818 // Multiply and accumulate with carry in. | 818 // Square and accumulate. |
| 819 // Input: | 819 // Input: |
| 820 // x: multiplier digit, 0 <= x < 2*DIGIT_BASE (i.e. 33-bit multiplier). | 820 // x_digits[i..used-1]: digits of operand being squared. |
| 821 // m_digits[i..i+n-1]: multiplicand digits. | 821 // a_digits[2*i..i+used-1]: accumulator digits. |
| 822 // a_digits[j..j+n-1]: accumulator digits. | |
| 823 // c: carry in. | |
| 824 // Operation: | 822 // Operation: |
| 825 // a_digits[j..j+n-1] += x*m_digits[i..i+n-1] + c. | 823 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + |
| 826 // Output: | 824 // 2*x_digits[i]*x_digits[i+1..used-1]. |
| 827 // carry out. | 825 static void _sqrAdd(Uint32List x_digits, int i, |
| 828 // TODO(regis): Use an argument buffer as in _mulAdd. | 826 Uint32List a_digits, int used) { |
| 829 static int _mulAddc(int x, Uint32List m_digits, int i, | 827 int x = x_digits[i]; |
| 830 Uint32List a_digits, int j, int c, int n) { | 828 if (x == 0) return; |
| 831 if (x == 0 && c == 0) { | 829 int j = 2*i; |
| 832 // No-op if both x and c are 0. | 830 int c = 0; |
| 833 return 0; | |
| 834 } | |
| 835 int xl = x & DIGIT2_MASK; | 831 int xl = x & DIGIT2_MASK; |
| 836 int xh = x >> DIGIT2_BITS; | 832 int xh = x >> DIGIT2_BITS; |
| 833 int m = 2*xh*xl; |
| 834 int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j]; |
| 835 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh; |
| 836 a_digits[j] = l & DIGIT_MASK; |
| 837 x <<= 1; |
| 838 xl = x & DIGIT2_MASK; |
| 839 xh = x >> DIGIT2_BITS; |
| 840 int n = used - i - 1; |
| 841 int k = i + 1; |
| 842 j++; |
| 837 while (--n >= 0) { | 843 while (--n >= 0) { |
| 838 int l = m_digits[i] & DIGIT2_MASK; | 844 int l = x_digits[k] & DIGIT2_MASK; |
| 839 int h = m_digits[i++] >> DIGIT2_BITS; | 845 int h = x_digits[k++] >> DIGIT2_BITS; |
| 840 int m = xh*l + h*xl; | 846 int m = xh*l + h*xl; |
| 841 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; | 847 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 842 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 848 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 843 a_digits[j++] = l & DIGIT_MASK; | 849 a_digits[j++] = l & DIGIT_MASK; |
| 844 } | 850 } |
| 845 return c; | 851 c += a_digits[i + used]; |
| 852 if (c >= DIGIT_BASE) { |
| 853 a_digits[i + used] = c - DIGIT_BASE; |
| 854 a_digits[i + used + 1] = 1; |
| 855 } else { |
| 856 a_digits[i + used] = c; |
| 857 } |
| 846 } | 858 } |
| 847 | 859 |
| 848 // r = this * a. | 860 // r = this * a. |
| 849 void _mulTo(_Bigint a, _Bigint r) { | 861 void _mulTo(_Bigint a, _Bigint r) { |
| 850 // TODO(regis): Use karatsuba multiplication when appropriate. | 862 // TODO(regis): Use karatsuba multiplication when appropriate. |
| 851 var used = _used; | 863 var used = _used; |
| 852 var a_used = a._used; | 864 var a_used = a._used; |
| 853 var i = used; | 865 var i = used; |
| 854 r._ensureLength(i + a_used); | 866 r._ensureLength(i + a_used); |
| 855 var digits = _digits; | 867 var digits = _digits; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 873 var used = _used; | 885 var used = _used; |
| 874 var r_used = 2 * used; | 886 var r_used = 2 * used; |
| 875 r._ensureLength(r_used); | 887 r._ensureLength(r_used); |
| 876 var digits = _digits; | 888 var digits = _digits; |
| 877 var r_digits = r._digits; | 889 var r_digits = r._digits; |
| 878 var i = r_used; | 890 var i = r_used; |
| 879 while (--i >= 0) { | 891 while (--i >= 0) { |
| 880 r_digits[i] = 0; | 892 r_digits[i] = 0; |
| 881 } | 893 } |
| 882 for (i = 0; i < used - 1; ++i) { | 894 for (i = 0; i < used - 1; ++i) { |
| 883 _MulAddArgs[MA_MULTIPLIER] = digits[i]; | 895 _sqrAdd(digits, i, r_digits, used); |
| 884 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); | |
| 885 var c = _MulAddArgs[MA_CARRY_OUT]; | |
| 886 var d = r_digits[i + used]; | |
| 887 d += _mulAddc(digits[i] << 1, digits, i + 1, | |
| 888 r_digits, 2*i + 1, c, used - i - 1); | |
| 889 if (d >= DIGIT_BASE) { | |
| 890 r_digits[i + used] = d - DIGIT_BASE; | |
| 891 r_digits[i + used + 1] = 1; | |
| 892 } else { | |
| 893 r_digits[i + used] = d; | |
| 894 } | |
| 895 } | 896 } |
| 896 if (r_used > 0) { | 897 if (r_used > 0) { |
| 897 _MulAddArgs[MA_MULTIPLIER] = digits[i]; | 898 _MulAddArgs[MA_MULTIPLIER] = digits[i]; |
| 898 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); | 899 _mulAdd(_MulAddArgs, digits, i, r_digits, 2*i, 1); |
| 899 r_digits[r_used - 1] += _MulAddArgs[MA_CARRY_OUT]; | 900 r_digits[r_used - 1] += _MulAddArgs[MA_CARRY_OUT]; |
| 900 } | 901 } |
| 901 r._used = r_used; | 902 r._used = r_used; |
| 902 r._neg = false; | 903 r._neg = false; |
| 903 r._clamp(); | 904 r._clamp(); |
| 904 } | 905 } |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 void _sqrTo(_Bigint x, _Bigint r) { | 1439 void _sqrTo(_Bigint x, _Bigint r) { |
| 1439 x._sqrTo(r); | 1440 x._sqrTo(r); |
| 1440 _reduce(r); | 1441 _reduce(r); |
| 1441 } | 1442 } |
| 1442 | 1443 |
| 1443 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1444 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1444 x._mulTo(y, r); | 1445 x._mulTo(y, r); |
| 1445 _reduce(r); | 1446 _reduce(r); |
| 1446 } | 1447 } |
| 1447 } | 1448 } |
| OLD | NEW |