@@ -18,24 +18,33 @@ namespace Neo.Extensions
1818{
1919 public static class BigIntegerExtensions
2020 {
21+ internal static int TrailingZeroCount ( byte [ ] b )
22+ {
23+ var w = 0 ;
24+ while ( b [ w ] == 0 ) w ++ ;
25+ for ( var x = 0 ; x < 8 ; x ++ )
26+ {
27+ if ( ( b [ w ] & 1 << x ) > 0 )
28+ return x + w * 8 ; // cannot greater than 2Gib
29+ }
30+ return - 1 ; // unreachable, because returned earlier if value is zero
31+ }
32+
2133 /// <summary>
22- /// Finds the lowest set bit in the specified value.
34+ /// Finds the lowest set bit in the specified value. If value is zero, returns -1.
2335 /// </summary>
24- /// <param name="value">The value to find the lowest set bit in.</param>
36+ /// <param name="value">The value to find the lowest set bit in. The value.GetBitLength cannot greater than 2Gib. </param>
2537 /// <returns>The lowest set bit in the specified value.</returns>
26- /// <exception cref="Exception">Thrown when the value is zero.</exception>
38+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
2739 public static int GetLowestSetBit ( this BigInteger value )
2840 {
29- if ( value . Sign == 0 )
30- return - 1 ;
31- var b = value . ToByteArray ( ) ;
32- var w = 0 ;
33- while ( b [ w ] == 0 )
34- w ++ ;
35- for ( var x = 0 ; x < 8 ; x ++ )
36- if ( ( b [ w ] & 1 << x ) > 0 )
37- return x + w * 8 ;
38- throw new Exception ( "The value is zero." ) ;
41+ if ( value . Sign == 0 ) return - 1 ; // special case for zero. TrailingZeroCount returns 32 in standard library.
42+
43+ #if NET7_0_OR_GREATER
44+ return ( int ) BigInteger . TrailingZeroCount ( value ) ;
45+ #else
46+ return TrailingZeroCount ( value . ToByteArray ( ) ) ;
47+ #endif
3948 }
4049
4150 /// <summary>
@@ -97,7 +106,6 @@ public static BigInteger ModInverse(this BigInteger value, BigInteger modulus)
97106 /// <param name="value">The value to test.</param>
98107 /// <param name="index">The index of the bit to test.</param>
99108 /// <returns>True if the specified bit is set in the specified value, otherwise false.</returns>
100-
101109 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
102110 public static bool TestBit ( this BigInteger value , int index )
103111 {
@@ -117,7 +125,7 @@ public static BigInteger Sum(this IEnumerable<BigInteger> source)
117125 }
118126
119127 /// <summary>
120- /// Converts a <see cref="BigInteger"/> to byte array and eliminates all the leading zeros.
128+ /// Converts a <see cref="BigInteger"/> to byte array in little-endian and eliminates all the leading zeros.
121129 /// If the value is zero, it returns an empty byte array.
122130 /// </summary>
123131 /// <param name="value">The <see cref="BigInteger"/> to convert.</param>
0 commit comments