diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs
index 2b1ff3354..8aab88353 100644
--- a/crypto/src/asn1/DerBitString.cs
+++ b/crypto/src/asn1/DerBitString.cs
@@ -125,7 +125,7 @@ namespace Org.BouncyCastle.Asn1
return;
}
- int bits = BigInteger.BitLen(namedBits);
+ int bits = 32 - Integers.NumberOfLeadingZeros(namedBits);
int bytes = (bits + 7) / 8;
Debug.Assert(0 < bytes && bytes <= 4);
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index 50229e2db..f915beafc 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -2,6 +2,9 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
using System.Runtime.Serialization;
using System.Text;
@@ -136,26 +139,6 @@ namespace Org.BouncyCastle.Math
public static readonly BigInteger Four;
public static readonly BigInteger Ten;
- //private readonly static byte[] BitCountTable =
- //{
- // 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- // 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
- //};
-
private readonly static byte[] BitLengthTable =
{
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
@@ -911,6 +894,13 @@ namespace Org.BouncyCastle.Math
public static int BitCnt(int i)
{
+#if NET5_0_OR_GREATER
+ if (Popcnt.IsSupported)
+ {
+ return (int)Popcnt.PopCount((uint)i);
+ }
+#endif
+
uint u = (uint)i;
u = u - ((u >> 1) & 0x55555555);
u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
@@ -976,8 +966,15 @@ namespace Org.BouncyCastle.Math
//
// BitLen(value) is the number of bits in value.
//
- internal static int BitLen(int w)
+ private static int BitLen(int w)
{
+#if NET5_0_OR_GREATER
+ if (Lzcnt.IsSupported)
+ {
+ return 32 - (int)Lzcnt.LeadingZeroCount((uint)w);
+ }
+#endif
+
uint v = (uint)w;
uint t = v >> 24;
if (t != 0)
diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs
index 4d3f715fa..97bc08d67 100644
--- a/crypto/src/math/ec/custom/sec/SecT571Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs
@@ -1,5 +1,9 @@
using System;
using System.Diagnostics;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+#endif
using Org.BouncyCastle.Math.Raw;
@@ -399,6 +403,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
protected static void ImplMulwAcc(ulong[] u, ulong x, ulong y, ulong[] z, int zOff)
{
+#if NET5_0_OR_GREATER
+ if (Pclmulqdq.IsSupported)
+ {
+ var X = Vector128.CreateScalar(x);
+ var Y = Vector128.CreateScalar(y);
+ var Z = Pclmulqdq.CarrylessMultiply(X, Y, 0x00);
+ z[zOff ] ^= Z.GetElement(0);
+ z[zOff + 1] ^= Z.GetElement(1);
+ return;
+ }
+#endif
+
//u[0] = 0;
u[1] = y;
for (int i = 2; i < 16; i += 2)
diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs
index 409ab83e8..560fd76fb 100644
--- a/crypto/src/math/raw/Interleave.cs
+++ b/crypto/src/math/raw/Interleave.cs
@@ -1,4 +1,7 @@
using System;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
namespace Org.BouncyCastle.Math.Raw
{
@@ -29,6 +32,14 @@ namespace Org.BouncyCastle.Math.Raw
internal static ulong Expand32to64(uint x)
{
+#if NET5_0_OR_GREATER
+ if (Bmi2.IsSupported)
+ {
+ return (ulong)Bmi2.ParallelBitDeposit(x >> 16, 0x55555555U) << 32
+ | Bmi2.ParallelBitDeposit(x , 0x55555555U);
+ }
+#endif
+
// "shuffle" low half to even bits and high half to odd bits
x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);
@@ -40,6 +51,15 @@ namespace Org.BouncyCastle.Math.Raw
internal static void Expand64To128(ulong x, ulong[] z, int zOff)
{
+#if NET5_0_OR_GREATER
+ if (Bmi2.X64.IsSupported)
+ {
+ z[zOff ] = Bmi2.X64.ParallelBitDeposit(x , 0x5555555555555555UL);
+ z[zOff + 1] = Bmi2.X64.ParallelBitDeposit(x >> 32, 0x5555555555555555UL);
+ return;
+ }
+#endif
+
// "shuffle" low half to even bits and high half to odd bits
x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
@@ -72,6 +92,15 @@ namespace Org.BouncyCastle.Math.Raw
internal static void Expand64To128Rev(ulong x, ulong[] z, int zOff)
{
+#if NET5_0_OR_GREATER
+ if (Bmi2.X64.IsSupported)
+ {
+ z[zOff ] = Bmi2.X64.ParallelBitDeposit(x >> 32, 0xAAAAAAAAAAAAAAAAUL);
+ z[zOff + 1] = Bmi2.X64.ParallelBitDeposit(x , 0xAAAAAAAAAAAAAAAAUL);
+ return;
+ }
+#endif
+
// "shuffle" low half to even bits and high half to odd bits
x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
@@ -126,6 +155,14 @@ namespace Org.BouncyCastle.Math.Raw
internal static ulong Unshuffle(ulong x)
{
+#if NET5_0_OR_GREATER
+ if (Bmi2.X64.IsSupported)
+ {
+ return Bmi2.X64.ParallelBitExtract(x, 0xAAAAAAAAAAAAAAAAUL) << 32
+ | Bmi2.X64.ParallelBitExtract(x, 0x5555555555555555UL);
+ }
+#endif
+
// "unshuffle" even bits to low half and odd bits to high half
x = Bits.BitPermuteStep(x, 0x2222222222222222UL, 1);
x = Bits.BitPermuteStep(x, 0x0C0C0C0C0C0C0C0CUL, 2);
@@ -137,6 +174,14 @@ namespace Org.BouncyCastle.Math.Raw
internal static ulong Unshuffle(ulong x, out ulong even)
{
+#if NET5_0_OR_GREATER
+ if (Bmi2.X64.IsSupported)
+ {
+ even = Bmi2.X64.ParallelBitExtract(x, 0x5555555555555555UL);
+ return Bmi2.X64.ParallelBitExtract(x, 0xAAAAAAAAAAAAAAAAUL);
+ }
+#endif
+
ulong u0 = Unshuffle(x);
even = u0 & 0x00000000FFFFFFFFUL;
return u0 >> 32;
@@ -144,6 +189,16 @@ namespace Org.BouncyCastle.Math.Raw
internal static ulong Unshuffle(ulong x0, ulong x1, out ulong even)
{
+#if NET5_0_OR_GREATER
+ if (Bmi2.X64.IsSupported)
+ {
+ even = Bmi2.X64.ParallelBitExtract(x0, 0x5555555555555555UL)
+ | Bmi2.X64.ParallelBitExtract(x1, 0x5555555555555555UL) << 32;
+ return Bmi2.X64.ParallelBitExtract(x0, 0xAAAAAAAAAAAAAAAAUL)
+ | Bmi2.X64.ParallelBitExtract(x1, 0xAAAAAAAAAAAAAAAAUL) << 32;
+ }
+#endif
+
ulong u0 = Unshuffle(x0);
ulong u1 = Unshuffle(x1);
even = (u1 << 32) | (u0 & 0x00000000FFFFFFFFUL);
diff --git a/crypto/src/util/Integers.cs b/crypto/src/util/Integers.cs
index 116250375..b32cdfc30 100644
--- a/crypto/src/util/Integers.cs
+++ b/crypto/src/util/Integers.cs
@@ -1,4 +1,7 @@
using System;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
using Org.BouncyCastle.Math.Raw;
@@ -42,6 +45,13 @@ namespace Org.BouncyCastle.Utilities
public static int NumberOfLeadingZeros(int i)
{
+#if NET5_0_OR_GREATER
+ if (Lzcnt.IsSupported)
+ {
+ return (int)Lzcnt.LeadingZeroCount((uint)i);
+ }
+#endif
+
if (i <= 0)
return (~i >> (31 - 5)) & (1 << 5);
@@ -57,6 +67,13 @@ namespace Org.BouncyCastle.Utilities
public static int NumberOfTrailingZeros(int i)
{
+#if NET5_0_OR_GREATER
+ if (Bmi1.IsSupported)
+ {
+ return (int)Bmi1.TrailingZeroCount((uint)i);
+ }
+#endif
+
int n = DeBruijnTZ[(uint)((i & -i) * 0x0EF96A62) >> 27];
int m = (((i & 0xFFFF) | (int)((uint)i >> 16)) - 1) >> 31;
return n - m;
diff --git a/crypto/src/util/Longs.cs b/crypto/src/util/Longs.cs
index e6ff2ea39..ff45a8143 100644
--- a/crypto/src/util/Longs.cs
+++ b/crypto/src/util/Longs.cs
@@ -1,4 +1,7 @@
using System;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
using Org.BouncyCastle.Math.Raw;
@@ -45,6 +48,13 @@ namespace Org.BouncyCastle.Utilities
public static int NumberOfLeadingZeros(long i)
{
+#if NET5_0_OR_GREATER
+ if (Lzcnt.X64.IsSupported)
+ {
+ return (int)Lzcnt.X64.LeadingZeroCount((ulong)i);
+ }
+#endif
+
int x = (int)(i >> 32), n = 0;
if (x == 0)
{
@@ -56,6 +66,13 @@ namespace Org.BouncyCastle.Utilities
public static int NumberOfTrailingZeros(long i)
{
+#if NET5_0_OR_GREATER
+ if (Bmi1.X64.IsSupported)
+ {
+ return (int)Bmi1.X64.TrailingZeroCount((ulong)i);
+ }
+#endif
+
int n = DeBruijnTZ[(uint)((ulong)((i & -i) * 0x045FBAC7992A70DAL) >> 58)];
long m = (((i & 0xFFFFFFFFL) | (long)((ulong)i >> 32)) - 1L) >> 63;
return n - (int)m;
|