@@ -1049,45 +1049,6 @@ public static BigInteger Min(BigInteger left, BigInteger right)
1049
1049
return right ;
1050
1050
}
1051
1051
1052
-
1053
- private static void ModPowUpdateResult ( ref BigIntegerBuilder regRes , ref BigIntegerBuilder regVal , ref BigIntegerBuilder regMod , ref BigIntegerBuilder regTmp )
1054
- {
1055
- NumericsHelpers . Swap ( ref regRes , ref regTmp ) ;
1056
- regRes . Mul ( ref regTmp , ref regVal ) ; // result = result * value;
1057
- regRes . Mod ( ref regMod ) ; // result = result % modulus;
1058
- }
1059
-
1060
- private static void ModPowSquareModValue ( ref BigIntegerBuilder regVal , ref BigIntegerBuilder regMod , ref BigIntegerBuilder regTmp )
1061
- {
1062
- NumericsHelpers . Swap ( ref regVal , ref regTmp ) ;
1063
- regVal . Mul ( ref regTmp , ref regTmp ) ; // value = value * value;
1064
- regVal . Mod ( ref regMod ) ; // value = value % modulus;
1065
- }
1066
-
1067
- private static void ModPowInner ( uint exp , ref BigIntegerBuilder regRes , ref BigIntegerBuilder regVal , ref BigIntegerBuilder regMod , ref BigIntegerBuilder regTmp )
1068
- {
1069
- while ( exp != 0 ) // !(Exponent.IsZero)
1070
- {
1071
- if ( ( exp & 1 ) == 1 ) // !(Exponent.IsEven)
1072
- ModPowUpdateResult ( ref regRes , ref regVal , ref regMod , ref regTmp ) ;
1073
- if ( exp == 1 ) // Exponent.IsOne - we can exit early
1074
- break ;
1075
- ModPowSquareModValue ( ref regVal , ref regMod , ref regTmp ) ;
1076
- exp >>= 1 ;
1077
- }
1078
- }
1079
-
1080
- private static void ModPowInner32 ( uint exp , ref BigIntegerBuilder regRes , ref BigIntegerBuilder regVal , ref BigIntegerBuilder regMod , ref BigIntegerBuilder regTmp )
1081
- {
1082
- for ( int i = 0 ; i < 32 ; i ++ )
1083
- {
1084
- if ( ( exp & 1 ) == 1 ) // !(Exponent.IsEven)
1085
- ModPowUpdateResult ( ref regRes , ref regVal , ref regMod , ref regTmp ) ;
1086
- ModPowSquareModValue ( ref regVal , ref regMod , ref regTmp ) ;
1087
- exp >>= 1 ;
1088
- }
1089
- }
1090
-
1091
1052
public static BigInteger ModPow ( BigInteger value , BigInteger exponent , BigInteger modulus )
1092
1053
{
1093
1054
if ( exponent . Sign < 0 )
@@ -1098,36 +1059,31 @@ public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigIntege
1098
1059
exponent . AssertValid ( ) ;
1099
1060
modulus . AssertValid ( ) ;
1100
1061
1101
- int signRes = + 1 ;
1102
- int signVal = + 1 ;
1103
- int signMod = + 1 ;
1104
- bool expIsEven = exponent . IsEven ;
1105
- BigIntegerBuilder regRes = new BigIntegerBuilder ( BigInteger . One , ref signRes ) ;
1106
- BigIntegerBuilder regVal = new BigIntegerBuilder ( value , ref signVal ) ;
1107
- BigIntegerBuilder regMod = new BigIntegerBuilder ( modulus , ref signMod ) ;
1108
- BigIntegerBuilder regTmp = new BigIntegerBuilder ( regVal . Size ) ;
1062
+ bool trivialValue = value . _bits == null ;
1063
+ bool trivialExponent = exponent . _bits == null ;
1064
+ bool trivialModulus = modulus . _bits == null ;
1109
1065
1110
- regRes . Mod ( ref regMod ) ; // Handle special case of exponent=0, modulus=1
1066
+ if ( trivialModulus )
1067
+ {
1068
+ long bits = trivialValue && trivialExponent ? BigIntegerCalculator . Pow ( NumericsHelpers . Abs ( value . _sign ) , NumericsHelpers . Abs ( exponent . _sign ) , NumericsHelpers . Abs ( modulus . _sign ) ) :
1069
+ trivialValue ? BigIntegerCalculator . Pow ( NumericsHelpers . Abs ( value . _sign ) , exponent . _bits , NumericsHelpers . Abs ( modulus . _sign ) ) :
1070
+ trivialExponent ? BigIntegerCalculator . Pow ( value . _bits , NumericsHelpers . Abs ( exponent . _sign ) , NumericsHelpers . Abs ( modulus . _sign ) ) :
1071
+ BigIntegerCalculator . Pow ( value . _bits , exponent . _bits , NumericsHelpers . Abs ( modulus . _sign ) ) ;
1111
1072
1112
- if ( exponent . _bits == null )
1113
- { // exponent fits into an Int32
1114
- ModPowInner ( ( uint ) exponent . _sign , ref regRes , ref regVal , ref regMod , ref regTmp ) ;
1073
+ return value . _sign < 0 && ! exponent . IsEven ? - 1 * bits : bits ;
1115
1074
}
1116
1075
else
1117
- { // very large exponent
1118
- int len = Length ( exponent . _bits ) ;
1119
- for ( int i = 0 ; i < len - 1 ; i ++ )
1120
- {
1121
- uint exp = exponent . _bits [ i ] ;
1122
- ModPowInner32 ( exp , ref regRes , ref regVal , ref regMod , ref regTmp ) ;
1123
- }
1124
- ModPowInner ( exponent . _bits [ len - 1 ] , ref regRes , ref regVal , ref regMod , ref regTmp ) ;
1125
- }
1076
+ {
1077
+ uint [ ] bits = trivialValue && trivialExponent ? BigIntegerCalculator . Pow ( NumericsHelpers . Abs ( value . _sign ) , NumericsHelpers . Abs ( exponent . _sign ) , modulus . _bits ) :
1078
+ trivialValue ? BigIntegerCalculator . Pow ( NumericsHelpers . Abs ( value . _sign ) , exponent . _bits , modulus . _bits ) :
1079
+ trivialExponent ? BigIntegerCalculator . Pow ( value . _bits , NumericsHelpers . Abs ( exponent . _sign ) , modulus . _bits ) :
1080
+ BigIntegerCalculator . Pow ( value . _bits , exponent . _bits , modulus . _bits ) ;
1126
1081
1127
- return regRes . GetInteger ( value . _sign > 0 ? + 1 : expIsEven ? + 1 : - 1 ) ;
1082
+ return new BigInteger ( bits , value . _sign < 0 && ! exponent . IsEven ) ;
1083
+ }
1128
1084
}
1129
1085
1130
- public static BigInteger Pow ( BigInteger value , Int32 exponent )
1086
+ public static BigInteger Pow ( BigInteger value , int exponent )
1131
1087
{
1132
1088
if ( exponent < 0 )
1133
1089
throw new ArgumentOutOfRangeException ( "exponent" , SR . ArgumentOutOfRange_MustBeNonNeg ) ;
@@ -1136,75 +1092,27 @@ public static BigInteger Pow(BigInteger value, Int32 exponent)
1136
1092
value . AssertValid ( ) ;
1137
1093
1138
1094
if ( exponent == 0 )
1139
- return BigInteger . One ;
1095
+ return s_bnOneInt ;
1140
1096
if ( exponent == 1 )
1141
1097
return value ;
1142
- if ( value . _bits == null )
1098
+
1099
+ bool trivialValue = value . _bits == null ;
1100
+
1101
+ if ( trivialValue )
1143
1102
{
1144
1103
if ( value . _sign == 1 )
1145
1104
return value ;
1146
1105
if ( value . _sign == - 1 )
1147
- return ( exponent & 1 ) != 0 ? value : 1 ;
1106
+ return ( exponent & 1 ) != 0 ? value : s_bnOneInt ;
1148
1107
if ( value . _sign == 0 )
1149
1108
return value ;
1150
1109
}
1151
1110
1152
- int sign = + 1 ;
1153
- BigIntegerBuilder regSquare = new BigIntegerBuilder ( value , ref sign ) ;
1154
-
1155
- // Get an estimate of the size needed for regSquare and regRes, so we can minimize allocations.
1156
- int cuSquareMin = regSquare . Size ;
1157
- int cuSquareMax = cuSquareMin ;
1158
- uint uSquareMin = regSquare . High ;
1159
- uint uSquareMax = uSquareMin + 1 ;
1160
- if ( uSquareMax == 0 )
1161
- {
1162
- cuSquareMax ++ ;
1163
- uSquareMax = 1 ;
1164
- }
1165
- int cuResMin = 1 ;
1166
- int cuResMax = 1 ;
1167
- uint uResMin = 1 ;
1168
- uint uResMax = 1 ;
1169
-
1170
- for ( int expTmp = exponent ; ; )
1171
- {
1172
- if ( ( expTmp & 1 ) != 0 )
1173
- {
1174
- MulUpper ( ref uResMax , ref cuResMax , uSquareMax , cuSquareMax ) ;
1175
- MulLower ( ref uResMin , ref cuResMin , uSquareMin , cuSquareMin ) ;
1176
- }
1177
-
1178
- if ( ( expTmp >>= 1 ) == 0 )
1179
- break ;
1180
-
1181
- MulUpper ( ref uSquareMax , ref cuSquareMax , uSquareMax , cuSquareMax ) ;
1182
- MulLower ( ref uSquareMin , ref cuSquareMin , uSquareMin , cuSquareMin ) ;
1183
- }
1184
-
1185
- if ( cuResMax > 1 )
1186
- regSquare . EnsureWritable ( cuResMax , 0 ) ;
1187
- BigIntegerBuilder regTmp = new BigIntegerBuilder ( cuResMax ) ;
1188
- BigIntegerBuilder regRes = new BigIntegerBuilder ( cuResMax ) ;
1189
- regRes . Set ( 1 ) ;
1190
-
1191
- if ( ( exponent & 1 ) == 0 )
1192
- sign = + 1 ;
1193
-
1194
- for ( int expTmp = exponent ; ; )
1195
- {
1196
- if ( ( expTmp & 1 ) != 0 )
1197
- {
1198
- NumericsHelpers . Swap ( ref regRes , ref regTmp ) ;
1199
- regRes . Mul ( ref regSquare , ref regTmp ) ;
1200
- }
1201
- if ( ( expTmp >>= 1 ) == 0 )
1202
- break ;
1203
- NumericsHelpers . Swap ( ref regSquare , ref regTmp ) ;
1204
- regSquare . Mul ( ref regTmp , ref regTmp ) ;
1205
- }
1111
+ uint [ ] bits = trivialValue
1112
+ ? BigIntegerCalculator . Pow ( NumericsHelpers . Abs ( value . _sign ) , NumericsHelpers . Abs ( exponent ) )
1113
+ : BigIntegerCalculator . Pow ( value . _bits , NumericsHelpers . Abs ( exponent ) ) ;
1206
1114
1207
- return regRes . GetInteger ( sign ) ;
1115
+ return new BigInteger ( bits , value . _sign < 0 && ( exponent & 1 ) != 0 ) ;
1208
1116
}
1209
1117
1210
1118
#endregion public static methods
@@ -1810,8 +1718,8 @@ private static BigInteger Subtract(uint[] leftBits, int leftSign, uint[] rightBi
1810
1718
1811
1719
if ( trivialDivisor )
1812
1720
{
1813
- uint [ ] bits = BigIntegerCalculator . Remainder ( dividend . _bits , NumericsHelpers . Abs ( divisor . _sign ) ) ;
1814
- return new BigInteger ( bits , dividend . _sign < 0 ) ;
1721
+ long bits = BigIntegerCalculator . Remainder ( dividend . _bits , NumericsHelpers . Abs ( divisor . _sign ) ) ;
1722
+ return dividend . _sign < 0 ? - 1 * bits : bits ;
1815
1723
}
1816
1724
1817
1725
if ( dividend . _bits . Length < divisor . _bits . Length )
@@ -2032,11 +1940,10 @@ private void SetBitsFromDouble(Double value)
2032
1940
[ Pure ]
2033
1941
internal static int Length ( uint [ ] rgu )
2034
1942
{
2035
- int cu = rgu . Length ;
2036
- if ( rgu [ cu - 1 ] != 0 )
2037
- return cu ;
2038
- Debug . Assert ( cu >= 2 && rgu [ cu - 2 ] != 0 ) ;
2039
- return cu - 1 ;
1943
+ Debug . Assert ( rgu [ rgu . Length - 1 ] != 0 ) ;
1944
+
1945
+ // no leading zeros
1946
+ return rgu . Length ;
2040
1947
}
2041
1948
2042
1949
internal int _Sign { get { return _sign ; } }
@@ -2088,47 +1995,6 @@ private static bool GetPartsForBitManipulation(ref BigInteger x, out uint[] xd,
2088
1995
return x . _sign < 0 ;
2089
1996
}
2090
1997
2091
- // Gets an upper bound on the product of uHiRes * (2^32)^(cuRes-1) and uHiMul * (2^32)^(cuMul-1).
2092
- // The result is put int uHiRes and cuRes.
2093
- private static void MulUpper ( ref uint uHiRes , ref int cuRes , uint uHiMul , int cuMul )
2094
- {
2095
- ulong uu = ( ulong ) uHiRes * uHiMul ;
2096
- uint uHi = NumericsHelpers . GetHi ( uu ) ;
2097
- if ( uHi != 0 )
2098
- {
2099
- if ( NumericsHelpers . GetLo ( uu ) != 0 && ++ uHi == 0 )
2100
- {
2101
- uHi = 1 ;
2102
- cuRes ++ ;
2103
- }
2104
- uHiRes = uHi ;
2105
- cuRes += cuMul ;
2106
- }
2107
- else
2108
- {
2109
- uHiRes = NumericsHelpers . GetLo ( uu ) ;
2110
- cuRes += cuMul - 1 ;
2111
- }
2112
- }
2113
-
2114
- // Gets a lower bound on the product of uHiRes * (2^32)^(cuRes-1) and uHiMul * (2^32)^(cuMul-1).
2115
- // The result is put int uHiRes and cuRes.
2116
- private static void MulLower ( ref uint uHiRes , ref int cuRes , uint uHiMul , int cuMul )
2117
- {
2118
- ulong uu = ( ulong ) uHiRes * uHiMul ;
2119
- uint uHi = NumericsHelpers . GetHi ( uu ) ;
2120
- if ( uHi != 0 )
2121
- {
2122
- uHiRes = uHi ;
2123
- cuRes += cuMul ;
2124
- }
2125
- else
2126
- {
2127
- uHiRes = NumericsHelpers . GetLo ( uu ) ;
2128
- cuRes += cuMul - 1 ;
2129
- }
2130
- }
2131
-
2132
1998
internal static int GetDiffLength ( uint [ ] rgu1 , uint [ ] rgu2 , int cu )
2133
1999
{
2134
2000
for ( int iv = cu ; -- iv >= 0 ; )
0 commit comments