| 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 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 r._neg = r_neg; | 825 r._neg = r_neg; |
| 826 return r; | 826 return r; |
| 827 } | 827 } |
| 828 | 828 |
| 829 // Multiply and accumulate. | 829 // Multiply and accumulate. |
| 830 // Input: | 830 // Input: |
| 831 // x_digits[xi]: multiplier digit x. | 831 // x_digits[xi]: multiplier digit x. |
| 832 // m_digits[i..i+n-1]: multiplicand digits. | 832 // m_digits[i..i+n-1]: multiplicand digits. |
| 833 // a_digits[j..j+n-1]: accumulator digits. | 833 // a_digits[j..j+n-1]: accumulator digits. |
| 834 // Operation: | 834 // Operation: |
| 835 // a_digits[j..j+n] += x*m_digits[i..i+n-1]. | 835 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. |
| 836 static void _mulAdd(Uint32List x_digits, int xi, | 836 // return 1. |
| 837 Uint32List m_digits, int i, | 837 // Note: intrinsics on 64-bit platform may process a digit pair: |
| 838 Uint32List a_digits, int j, int n) { | 838 // a_digits[j..j+n] += x_digits[xi..xi+1]*m_digits[i..i+n-1]. |
| 839 // return 2. |
| 840 static int _mulAdd(Uint32List x_digits, int xi, |
| 841 Uint32List m_digits, int i, |
| 842 Uint32List a_digits, int j, int n) { |
| 839 int x = x_digits[xi]; | 843 int x = x_digits[xi]; |
| 840 if (x == 0) { | 844 if (x == 0) { |
| 841 // No-op if x is 0. | 845 // No-op if x is 0. |
| 842 return; | 846 return 1; |
| 843 } | 847 } |
| 844 int c = 0; | 848 int c = 0; |
| 845 int xl = x & DIGIT2_MASK; | 849 int xl = x & DIGIT2_MASK; |
| 846 int xh = x >> DIGIT2_BITS; | 850 int xh = x >> DIGIT2_BITS; |
| 847 while (--n >= 0) { | 851 while (--n >= 0) { |
| 848 int l = m_digits[i] & DIGIT2_MASK; | 852 int l = m_digits[i] & DIGIT2_MASK; |
| 849 int h = m_digits[i++] >> DIGIT2_BITS; | 853 int h = m_digits[i++] >> DIGIT2_BITS; |
| 850 int m = xh*l + h*xl; | 854 int m = xh*l + h*xl; |
| 851 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; | 855 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 852 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 856 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 853 a_digits[j++] = l & DIGIT_MASK; | 857 a_digits[j++] = l & DIGIT_MASK; |
| 854 } | 858 } |
| 855 while (c != 0) { | 859 while (c != 0) { |
| 856 int l = a_digits[j] + c; | 860 int l = a_digits[j] + c; |
| 857 c = l >> DIGIT_BITS; | 861 c = l >> DIGIT_BITS; |
| 858 a_digits[j++] = l & DIGIT_MASK; | 862 a_digits[j++] = l & DIGIT_MASK; |
| 859 } | 863 } |
| 864 return 1; |
| 860 } | 865 } |
| 861 | 866 |
| 862 // Square and accumulate. | 867 // Square and accumulate. |
| 863 // Input: | 868 // Input: |
| 864 // x_digits[i..used-1]: digits of operand being squared. | 869 // x_digits[i..used-1]: digits of operand being squared. |
| 865 // a_digits[2*i..i+used-1]: accumulator digits. | 870 // a_digits[2*i..i+used-1]: accumulator digits. |
| 866 // Operation: | 871 // Operation: |
| 867 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + | 872 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + |
| 868 // 2*x_digits[i]*x_digits[i+1..used-1]. | 873 // 2*x_digits[i]*x_digits[i+1..used-1]. |
| 869 static void _sqrAdd(Uint32List x_digits, int i, | 874 // return 1. |
| 870 Uint32List a_digits, int used) { | 875 // Note: intrinsics on 64-bit platform may process a digit pair: |
| 876 // a_digits[2*i..i+used-1] += x_digits[i..i+1]*x_digits[i..i+1] + |
| 877 // 2*x_digits[i..i+1]*x_digits[i+2..used-1]. |
| 878 // return 2. |
| 879 static int _sqrAdd(Uint32List x_digits, int i, |
| 880 Uint32List a_digits, int used) { |
| 871 int x = x_digits[i]; | 881 int x = x_digits[i]; |
| 872 if (x == 0) return; | 882 if (x == 0) return 1; |
| 873 int j = 2*i; | 883 int j = 2*i; |
| 874 int c = 0; | 884 int c = 0; |
| 875 int xl = x & DIGIT2_MASK; | 885 int xl = x & DIGIT2_MASK; |
| 876 int xh = x >> DIGIT2_BITS; | 886 int xh = x >> DIGIT2_BITS; |
| 877 int m = 2*xh*xl; | 887 int m = 2*xh*xl; |
| 878 int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j]; | 888 int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j]; |
| 879 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh; | 889 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh; |
| 880 a_digits[j] = l & DIGIT_MASK; | 890 a_digits[j] = l & DIGIT_MASK; |
| 881 x <<= 1; | 891 x <<= 1; |
| 882 xl = x & DIGIT2_MASK; | 892 xl = x & DIGIT2_MASK; |
| 883 xh = x >> DIGIT2_BITS; | 893 xh = x >> DIGIT2_BITS; |
| 884 int n = used - i - 1; | 894 int n = used - i - 1; |
| 885 int k = i + 1; | 895 int k = i + 1; |
| 886 j++; | 896 j++; |
| 887 while (--n >= 0) { | 897 while (--n >= 0) { |
| 888 int l = x_digits[k] & DIGIT2_MASK; | 898 int l = x_digits[k] & DIGIT2_MASK; |
| 889 int h = x_digits[k++] >> DIGIT2_BITS; | 899 int h = x_digits[k++] >> DIGIT2_BITS; |
| 890 int m = xh*l + h*xl; | 900 int m = xh*l + h*xl; |
| 891 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; | 901 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c; |
| 892 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; | 902 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; |
| 893 a_digits[j++] = l & DIGIT_MASK; | 903 a_digits[j++] = l & DIGIT_MASK; |
| 894 } | 904 } |
| 895 c += a_digits[i + used]; | 905 c += a_digits[i + used]; |
| 896 if (c >= DIGIT_BASE) { | 906 if (c >= DIGIT_BASE) { |
| 897 a_digits[i + used] = c - DIGIT_BASE; | 907 a_digits[i + used] = c - DIGIT_BASE; |
| 898 a_digits[i + used + 1] = 1; | 908 a_digits[i + used + 1] = 1; |
| 899 } else { | 909 } else { |
| 900 a_digits[i + used] = c; | 910 a_digits[i + used] = c; |
| 901 } | 911 } |
| 912 return 1; |
| 902 } | 913 } |
| 903 | 914 |
| 904 // r = this * a. | 915 // r = this * a. |
| 905 void _mulTo(_Bigint a, _Bigint r) { | 916 void _mulTo(_Bigint a, _Bigint r) { |
| 906 // TODO(regis): Use karatsuba multiplication when appropriate. | 917 // TODO(regis): Use karatsuba multiplication when appropriate. |
| 907 var used = _used; | 918 var used = _used; |
| 908 var a_used = a._used; | 919 var a_used = a._used; |
| 909 if (used == 0 || a_used == 0) { | 920 if (used == 0 || a_used == 0) { |
| 910 r._used = 0; | 921 r._used = 0; |
| 911 r._neg = false; | 922 r._neg = false; |
| 912 return; | 923 return; |
| 913 } | 924 } |
| 914 var r_used = used + a_used; | 925 var r_used = used + a_used; |
| 915 r._ensureLength(r_used); | 926 r._ensureLength(r_used); |
| 916 var digits = _digits; | 927 var digits = _digits; |
| 917 var a_digits = a._digits; | 928 var a_digits = a._digits; |
| 918 var r_digits = r._digits; | 929 var r_digits = r._digits; |
| 919 r._used = r_used; | 930 r._used = r_used; |
| 920 var i = r_used + 1; // Set leading zero for 64-bit processing. | 931 var i = r_used + 1; // Set leading zero for 64-bit processing. |
| 921 while (--i >= 0) { | 932 while (--i >= 0) { |
| 922 r_digits[i] = 0; | 933 r_digits[i] = 0; |
| 923 } | 934 } |
| 924 for (i = 0; i < a_used; ++i) { | 935 i = 0; |
| 925 _mulAdd(a_digits, i, digits, 0, r_digits, i, used); | 936 while (i < a_used) { |
| 937 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); |
| 926 } | 938 } |
| 927 r._clamp(); | 939 r._clamp(); |
| 928 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. | 940 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. |
| 929 } | 941 } |
| 930 | 942 |
| 931 // r = this^2, r != this. | 943 // r = this^2, r != this. |
| 932 void _sqrTo(_Bigint r) { | 944 void _sqrTo(_Bigint r) { |
| 933 var used = _used; | 945 var used = _used; |
| 934 if (used == 0) { | 946 if (used == 0) { |
| 935 r._used = 0; | 947 r._used = 0; |
| 936 r._neg = false; | 948 r._neg = false; |
| 937 return; | 949 return; |
| 938 } | 950 } |
| 939 var r_used = 2 * used; | 951 var r_used = 2 * used; |
| 940 r._ensureLength(r_used); | 952 r._ensureLength(r_used); |
| 941 var digits = _digits; | 953 var digits = _digits; |
| 942 var r_digits = r._digits; | 954 var r_digits = r._digits; |
| 943 var i = r_used + 1; // Set leading zero for 64-bit processing. | 955 var i = r_used + 1; // Set leading zero for 64-bit processing. |
| 944 while (--i >= 0) { | 956 while (--i >= 0) { |
| 945 r_digits[i] = 0; | 957 r_digits[i] = 0; |
| 946 } | 958 } |
| 947 for (i = 0; i < used - 1; ++i) { | 959 i = 0; |
| 948 _sqrAdd(digits, i, r_digits, used); | 960 while (i < used - 1) { |
| 961 i += _sqrAdd(digits, i, r_digits, used); |
| 949 } | 962 } |
| 950 if (r_used > 0) { | 963 if (r_used > 0) { |
| 951 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); | 964 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); |
| 952 } | 965 } |
| 953 r._used = r_used; | 966 r._used = r_used; |
| 954 r._neg = false; | 967 r._neg = false; |
| 955 r._clamp(); | 968 r._clamp(); |
| 956 } | 969 } |
| 957 | 970 |
| 958 // Indices of the arguments of _estQuotientDigit. | 971 // Indices of the arguments of _estQuotientDigit. |
| 959 static const int _YT = 0; // Index of top digit of divisor y in args array. | 972 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair |
| 960 static const int _QD = 1; // Index of estimated quotient digit in args array. | 973 // of divisor y is provided in the args array, and a 64-bit estimated quotient |
| 974 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored |
| 975 // and only one 32-bit digit is returned as the estimated quotient. |
| 976 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. |
| 977 static const int _YT = 1; // Top digit of divisor y. |
| 978 static const int _QD = 2; // Estimated quotient. |
| 979 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. |
| 961 | 980 |
| 962 // Estimate args[_QD] = digits[i]:digits[i-1] ~/ args[_YT]. | 981 // Operation: |
| 963 static void _estQuotientDigit(Uint32List args, Uint32List digits, int i) { | 982 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] |
| 983 // return 1 |
| 984 // Note: intrinsics on 64-bit platform may process a digit pair: |
| 985 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] |
| 986 // return 2 |
| 987 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
| 964 if (digits[i] == args[_YT]) { | 988 if (digits[i] == args[_YT]) { |
| 965 args[_QD] = DIGIT_MASK; | 989 args[_QD] = DIGIT_MASK; |
| 966 } else { | 990 } else { |
| 967 // Chop off one bit, since a Mint cannot hold 2 DIGITs. | 991 // Chop off one bit, since a Mint cannot hold 2 DIGITs. |
| 968 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) | 992 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) |
| 969 ~/ (args[_YT] >> 1); | 993 ~/ (args[_YT] >> 1); |
| 970 if (qd > DIGIT_MASK) { | 994 if (qd > DIGIT_MASK) { |
| 971 args[_QD] = DIGIT_MASK; | 995 args[_QD] = DIGIT_MASK; |
| 972 } else { | 996 } else { |
| 973 args[_QD] = qd; | 997 args[_QD] = qd; |
| 974 } | 998 } |
| 975 } | 999 } |
| 1000 return 1; |
| 976 } | 1001 } |
| 977 | 1002 |
| 978 | 1003 |
| 979 // Truncating division and remainder. | 1004 // Truncating division and remainder. |
| 980 // If q != null, q = trunc(this / a). | 1005 // If q != null, q = trunc(this / a). |
| 981 // If r != null, r = this - a * trunc(this / a). | 1006 // If r != null, r = this - a * trunc(this / a). |
| 982 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { | 1007 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { |
| 983 if (a._used == 0) return; | 1008 if (a._used == 0) return; |
| 984 if (_used < a._used) { | 1009 if (_used < a._used) { |
| 985 if (q != null) { | 1010 if (q != null) { |
| 986 // Set q to 0. | 1011 // Set q to 0. |
| 987 q._neg = false; | 1012 q._neg = false; |
| 988 q._used = 0; | 1013 q._used = 0; |
| 989 } | 1014 } |
| 990 if (r != null) { | 1015 if (r != null) { |
| 991 _copyTo(r); | 1016 _copyTo(r); |
| 992 } | 1017 } |
| 993 return; | 1018 return; |
| 994 } | 1019 } |
| 995 if (r == null) { | 1020 if (r == null) { |
| 996 r = new _Bigint(); | 1021 r = new _Bigint(); |
| 997 } | 1022 } |
| 998 var y = new _Bigint(); // Normalized modulus. | 1023 var y = new _Bigint(); // Normalized modulus. |
| 999 var nsh = DIGIT_BITS - _nbits(a._digits[a._used - 1]); | 1024 var nsh = DIGIT_BITS - _nbits(a._digits[a._used - 1]); |
| 1025 // For 64-bit processing, make sure y has an even number of digits. |
| 1026 if ((a._used & 1) == 1) { |
| 1027 nsh += DIGIT_BITS; |
| 1028 } |
| 1000 if (nsh > 0) { | 1029 if (nsh > 0) { |
| 1001 a._lShiftTo(nsh, y); | 1030 a._lShiftTo(nsh, y); |
| 1002 _lShiftTo(nsh, r); | 1031 _lShiftTo(nsh, r); |
| 1003 } | 1032 } |
| 1004 else { | 1033 else { |
| 1005 a._copyTo(y); | 1034 a._copyTo(y); |
| 1006 _copyTo(r); | 1035 _copyTo(r); |
| 1007 } | 1036 } |
| 1008 // We consider this and a positive. Ignore the copied sign. | 1037 // We consider this and a positive. Ignore the copied sign. |
| 1009 y._neg = false; | 1038 y._neg = false; |
| 1010 r._neg = false; | 1039 r._neg = false; |
| 1011 var y_used = y._used; | 1040 var y_used = y._used; |
| 1012 var y_digits = y._digits; | 1041 var y_digits = y._digits; |
| 1013 var yt = y_digits[y_used - 1]; | 1042 Uint32List args = new Uint32List(4); |
| 1014 if (yt == 0) return; | 1043 args[_YT_LO] = y_digits[y_used - 2]; |
| 1044 args[_YT] = y_digits[y_used - 1]; |
| 1015 var i = r._used; | 1045 var i = r._used; |
| 1016 var j = i - y_used; | 1046 var j = i - y_used; |
| 1017 _Bigint t = (q == null) ? new _Bigint() : q; | 1047 _Bigint t = (q == null) ? new _Bigint() : q; |
| 1018 y._dlShiftTo(j, t); | 1048 y._dlShiftTo(j, t); |
| 1019 var r_digits = r._digits; | 1049 var r_digits = r._digits; |
| 1020 if (r._compareTo(t) >= 0) { | 1050 if (r._compareTo(t) >= 0) { |
| 1021 r_digits[r._used++] = 1; | 1051 r_digits[r._used++] = 1; |
| 1022 r_digits[r._used] = 0; // Set leading zero for 64-bit processing. | 1052 r_digits[r._used] = 0; // Set leading zero for 64-bit processing. |
| 1023 r._subTo(t, r); | 1053 r._subTo(t, r); |
| 1024 } | 1054 } |
| 1025 ONE._dlShiftTo(y_used, t); | 1055 ONE._dlShiftTo(y_used, t); |
| 1026 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. | 1056 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. |
| 1027 while (y._used < y_used) { | 1057 while (y._used < y_used) { |
| 1028 y_digits[y._used++] = 0; | 1058 y_digits[y._used++] = 0; |
| 1029 } | 1059 } |
| 1030 y_digits[y._used] = 0; // Set leading zero for 64-bit processing. | 1060 y_digits[y._used] = 0; // Set leading zero for 64-bit processing. |
| 1031 Uint32List args = new Uint32List(2); | |
| 1032 args[_YT] = yt; | |
| 1033 while (--j >= 0) { | 1061 while (--j >= 0) { |
| 1034 _estQuotientDigit(args, r_digits, --i); | 1062 var d0 = _estQuotientDigit(args, r_digits, --i); |
| 1035 _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); | 1063 var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); |
| 1036 if (r_digits[i] < args[_QD]) { | 1064 // _estQuotientDigit and _mulAdd must agree on the number of digits to |
| 1037 y._dlShiftTo(j, t); | 1065 // process. |
| 1038 r._subTo(t, r); | 1066 assert(d0 == d1); |
| 1039 while (r_digits[i] < --args[_QD]) { | 1067 if (d0 == 1) { |
| 1068 if (r_digits[i] < args[_QD]) { |
| 1069 y._dlShiftTo(j, t); |
| 1040 r._subTo(t, r); | 1070 r._subTo(t, r); |
| 1071 while (r_digits[i] < --args[_QD]) { |
| 1072 r._subTo(t, r); |
| 1073 } |
| 1074 } |
| 1075 } else { |
| 1076 // TODO(regis): Is this necessary, since intrinsified estimation is more |
| 1077 // accurate? |
| 1078 if ((r_digits[i] < args[_QD_HI]) || |
| 1079 ((r_digits[i] == args[_QD_HI]) && (r_digits[i-1] < args[_QD]))) { |
| 1080 y._dlShiftTo(j, t); |
| 1081 r._subTo(t, r); |
| 1082 assert(args[_QD] > 0); |
| 1083 while (r_digits[i] < --args[_QD]) { |
| 1084 r._subTo(t, r); |
| 1085 } |
| 1041 } | 1086 } |
| 1042 } | 1087 } |
| 1043 } | 1088 } |
| 1044 if (q != null) { | 1089 if (q != null) { |
| 1045 r._drShiftTo(y_used, q); | 1090 r._drShiftTo(y_used, q); |
| 1046 if (_neg != a._neg && q._used > 0) { | 1091 if (_neg != a._neg && q._used > 0) { |
| 1047 q._neg = !q._neg; | 1092 q._neg = !q._neg; |
| 1048 } | 1093 } |
| 1049 } | 1094 } |
| 1050 r._used = y_used; | 1095 r._used = y_used; |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1267 other._toBigint()._divRemTo(this, null, result); | 1312 other._toBigint()._divRemTo(this, null, result); |
| 1268 return result._toValidInt(); | 1313 return result._toValidInt(); |
| 1269 } | 1314 } |
| 1270 bool _greaterThanFromInteger(int other) { | 1315 bool _greaterThanFromInteger(int other) { |
| 1271 return other._toBigint()._compareTo(this) > 0; | 1316 return other._toBigint()._compareTo(this) > 0; |
| 1272 } | 1317 } |
| 1273 bool _equalToInteger(int other) { | 1318 bool _equalToInteger(int other) { |
| 1274 return other._toBigint()._compareTo(this) == 0; | 1319 return other._toBigint()._compareTo(this) == 0; |
| 1275 } | 1320 } |
| 1276 | 1321 |
| 1277 // Return -1/this % DIGIT_BASE, useful for Montgomery reduction. | |
| 1278 // | |
| 1279 // xy == 1 (mod m) | |
| 1280 // xy = 1+km | |
| 1281 // xy(2-xy) = (1+km)(1-km) | |
| 1282 // x(y(2-xy)) = 1-k^2 m^2 | |
| 1283 // x(y(2-xy)) == 1 (mod m^2) | |
| 1284 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 | |
| 1285 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded. | |
| 1286 int _invDigit() { | |
| 1287 if (_used == 0) return 0; | |
| 1288 var x = _digits[0]; | |
| 1289 if ((x & 1) == 0) return 0; | |
| 1290 var y = x & 3; // y == 1/x mod 2^2 | |
| 1291 y = (y*(2 - (x & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 | |
| 1292 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 | |
| 1293 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 | |
| 1294 // Last step - calculate inverse mod DIGIT_BASE directly; | |
| 1295 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. | |
| 1296 y = (y*(2 - x*y % DIGIT_BASE)) % DIGIT_BASE; // y == 1/x mod DIGIT_BASE | |
| 1297 // We really want the negative inverse, and - DIGIT_BASE < y < DIGIT_BASE. | |
| 1298 return (y > 0) ? DIGIT_BASE - y : -y; | |
| 1299 } | |
| 1300 | |
| 1301 // TODO(regis): Make this method private once the plumbing to invoke it from | 1322 // TODO(regis): Make this method private once the plumbing to invoke it from |
| 1302 // dart:math is in place. Move the argument checking to dart:math. | 1323 // dart:math is in place. Move the argument checking to dart:math. |
| 1303 // Return pow(this, e) % m. | 1324 // Return pow(this, e) % m. |
| 1304 int modPow(int e, int m) { | 1325 int modPow(int e, int m) { |
| 1305 if (e is! int) throw new ArgumentError(e); | 1326 if (e is! int) throw new ArgumentError(e); |
| 1306 if (m is! int) throw new ArgumentError(m); | 1327 if (m is! int) throw new ArgumentError(m); |
| 1307 int i = e.bitLength; | 1328 int i = e.bitLength; |
| 1308 if (i <= 0) return 1; | 1329 if (i <= 0) return 1; |
| 1309 if ((e is! _Bigint) || m.isEven) { | 1330 if ((e is! _Bigint) || m.isEven) { |
| 1310 _Reduction z = (i < 8 || m.isEven) ? new _Classic(m) : new _Montgomery(m); | 1331 _Reduction z = (i < 8 || m.isEven) ? new _Classic(m) : new _Montgomery(m); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 _Bigint _convert(_Bigint x); | 1435 _Bigint _convert(_Bigint x); |
| 1415 _Bigint _revert(_Bigint x); | 1436 _Bigint _revert(_Bigint x); |
| 1416 void _mulTo(_Bigint x, _Bigint y, _Bigint r); | 1437 void _mulTo(_Bigint x, _Bigint y, _Bigint r); |
| 1417 void _sqrTo(_Bigint x, _Bigint r); | 1438 void _sqrTo(_Bigint x, _Bigint r); |
| 1418 } | 1439 } |
| 1419 | 1440 |
| 1420 // Montgomery reduction on _Bigint. | 1441 // Montgomery reduction on _Bigint. |
| 1421 class _Montgomery implements _Reduction { | 1442 class _Montgomery implements _Reduction { |
| 1422 _Bigint _m; | 1443 _Bigint _m; |
| 1423 int _mused2; | 1444 int _mused2; |
| 1424 Uint32List _rho_mu; | 1445 Uint32List _args; |
| 1425 static const int _RHO = 0; // Index of rho in _rho_mu array. | 1446 int _digits_per_step; // Number of digits processed in one step. 1 or 2. |
| 1426 static const int _MU = 1; // Index of mu in _rho_mu array. | 1447 static const int _X = 0; // Index of x. |
| 1448 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). |
| 1449 static const int _RHO = 2; // Index of rho. |
| 1450 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). |
| 1451 static const int _MU = 4; // Index of mu. |
| 1452 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). |
| 1427 | 1453 |
| 1428 _Montgomery(m) { | 1454 _Montgomery(m) { |
| 1429 _m = m._toBigint(); | 1455 _m = m._toBigint(); |
| 1430 _mused2 = 2*_m._used; | 1456 _mused2 = 2*_m._used; |
| 1431 _rho_mu = new Uint32List(2); | 1457 _args = new Uint32List(6); |
| 1432 _rho_mu[_RHO] = _m._invDigit(); | 1458 _args[_X] = _m._digits[0]; |
| 1459 _args[_X_HI] = _m._digits[1]; |
| 1460 _digits_per_step = _invDigit(_args); |
| 1433 } | 1461 } |
| 1434 | 1462 |
| 1435 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE. | 1463 // Return -1/this % DIGIT_BASE, useful for Montgomery reduction. |
| 1436 static void _mulMod(Uint32List args, Uint32List digits, int i) { | 1464 // |
| 1465 // xy == 1 (mod m) |
| 1466 // xy = 1+km |
| 1467 // xy(2-xy) = (1+km)(1-km) |
| 1468 // x(y(2-xy)) = 1-k^2 m^2 |
| 1469 // x(y(2-xy)) == 1 (mod m^2) |
| 1470 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 |
| 1471 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded. |
| 1472 // |
| 1473 // TODO(regis): Intrinsify this method and provide a 64-bit inverse digit pair |
| 1474 // on 64-bit platforms. |
| 1475 // |
| 1476 // Operation: |
| 1477 // args[_RHO] = 1/args[_X] mod DIGIT_BASE. |
| 1478 // return 1. |
| 1479 // Note: intrinsics on 64-bit platform process a digit pair: |
| 1480 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2. |
| 1481 // return 2. |
| 1482 static int _invDigit(Uint32List args) { |
| 1483 var x = args[_X]; |
| 1484 var y = x & 3; // y == 1/x mod 2^2 |
| 1485 y = (y*(2 - (x & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 |
| 1486 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 |
| 1487 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 |
| 1488 // Last step - calculate inverse mod DIGIT_BASE directly; |
| 1489 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. |
| 1490 y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE; |
| 1491 // y == 1/x mod DIGIT_BASE |
| 1492 // We really want the negative inverse, and - DIGIT_BASE < y < DIGIT_BASE. |
| 1493 args[_RHO] = (y > 0) ? _Bigint.DIGIT_BASE - y : -y; |
| 1494 return 1; |
| 1495 } |
| 1496 |
| 1497 // Operation: |
| 1498 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE. |
| 1499 // return 1. |
| 1500 // Note: intrinsics on 64-bit platform may process a digit pair: |
| 1501 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2. |
| 1502 // return 2. |
| 1503 static int _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1437 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; | 1504 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; |
| 1438 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK; | 1505 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK; |
| 1439 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS; | 1506 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS; |
| 1440 var dh = digits[i] >> _Bigint.DIGIT2_BITS; | 1507 var dh = digits[i] >> _Bigint.DIGIT2_BITS; |
| 1441 var dl = digits[i] & _Bigint.DIGIT2_MASK; | 1508 var dl = digits[i] & _Bigint.DIGIT2_MASK; |
| 1442 args[_MU] = | 1509 args[_MU] = |
| 1443 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS)) | 1510 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS)) |
| 1444 & _Bigint.DIGIT_MASK; | 1511 & _Bigint.DIGIT_MASK; |
| 1512 return 1; |
| 1445 } | 1513 } |
| 1446 | 1514 |
| 1447 // Return x*R mod _m | 1515 // Return x*R mod _m |
| 1448 _Bigint _convert(_Bigint x) { | 1516 _Bigint _convert(_Bigint x) { |
| 1449 var r = new _Bigint(); | 1517 var r = new _Bigint(); |
| 1450 x.abs()._dlShiftTo(_m._used, r); | 1518 x.abs()._dlShiftTo(_m._used, r); |
| 1451 r._divRemTo(_m, null, r); | 1519 r._divRemTo(_m, null, r); |
| 1452 if (x._neg && !r._neg && r._used > 0) { | 1520 if (x._neg && !r._neg && r._used > 0) { |
| 1453 _m._subTo(r, r); | 1521 _m._subTo(r, r); |
| 1454 } | 1522 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1466 // x = x/R mod _m | 1534 // x = x/R mod _m |
| 1467 void _reduce(_Bigint x) { | 1535 void _reduce(_Bigint x) { |
| 1468 x._ensureLength(_mused2 + 1); | 1536 x._ensureLength(_mused2 + 1); |
| 1469 var x_digits = x._digits; | 1537 var x_digits = x._digits; |
| 1470 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. | 1538 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. |
| 1471 x_digits[x._used++] = 0; | 1539 x_digits[x._used++] = 0; |
| 1472 } | 1540 } |
| 1473 x_digits[x._used] = 0; // Set leading zero for 64-bit processing. | 1541 x_digits[x._used] = 0; // Set leading zero for 64-bit processing. |
| 1474 var m_used = _m._used; | 1542 var m_used = _m._used; |
| 1475 var m_digits = _m._digits; | 1543 var m_digits = _m._digits; |
| 1476 for (var i = 0; i < m_used; i++) { | 1544 var i = 0; |
| 1477 _mulMod(_rho_mu, x_digits, i); | 1545 while (i < m_used) { |
| 1478 _Bigint._mulAdd(_rho_mu, _MU, m_digits, 0, x_digits, i, m_used); | 1546 var d = _mulMod(_args, x_digits, i); |
| 1547 assert(d == _digits_per_step); |
| 1548 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); |
| 1549 assert(d == _digits_per_step); |
| 1550 i += d; |
| 1479 } | 1551 } |
| 1480 x._clamp(); | 1552 x._clamp(); |
| 1481 x._drShiftTo(m_used, x); | 1553 x._drShiftTo(m_used, x); |
| 1482 if (x._compareTo(_m) >= 0) { | 1554 if (x._compareTo(_m) >= 0) { |
| 1483 x._subTo(_m, x); | 1555 x._subTo(_m, x); |
| 1484 } | 1556 } |
| 1485 } | 1557 } |
| 1486 | 1558 |
| 1487 // r = x^2/R mod _m ; x != r | 1559 // r = x^2/R mod _m ; x != r |
| 1488 void _sqrTo(_Bigint x, _Bigint r) { | 1560 void _sqrTo(_Bigint x, _Bigint r) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1528 void _sqrTo(_Bigint x, _Bigint r) { | 1600 void _sqrTo(_Bigint x, _Bigint r) { |
| 1529 x._sqrTo(r); | 1601 x._sqrTo(r); |
| 1530 _reduce(r); | 1602 _reduce(r); |
| 1531 } | 1603 } |
| 1532 | 1604 |
| 1533 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1605 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1534 x._mulTo(y, r); | 1606 x._mulTo(y, r); |
| 1535 _reduce(r); | 1607 _reduce(r); |
| 1536 } | 1608 } |
| 1537 } | 1609 } |
| OLD | NEW |