summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/math/raw/Interleave.cs44
1 files changed, 44 insertions, 0 deletions
diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs
index 3e994a43c..196f7c9b5 100644
--- a/crypto/src/math/raw/Interleave.cs
+++ b/crypto/src/math/raw/Interleave.cs
@@ -156,6 +156,14 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static uint Shuffle(uint x)
         {
+#if NETCOREAPP3_0_OR_GREATER
+            if (Bmi2.IsSupported)
+            {
+                return Bmi2.ParallelBitDeposit(x >> 16, 0xAAAAAAAAU)
+                    |  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);
@@ -166,6 +174,14 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static ulong Shuffle(ulong x)
         {
+#if NETCOREAPP3_0_OR_GREATER
+            if (Bmi2.IsSupported)
+            {
+                return Bmi2.X64.ParallelBitDeposit(x >> 32, 0xAAAAAAAAAAAAAAAAUL)
+                    |  Bmi2.X64.ParallelBitDeposit(x      , 0x5555555555555555UL);
+            }
+#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);
@@ -177,6 +193,16 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static uint Shuffle2(uint x)
         {
+#if NETCOREAPP3_0_OR_GREATER
+            if (Bmi2.IsSupported)
+            {
+                return Bmi2.ParallelBitDeposit(x >> 24, 0x88888888U)
+                    |  Bmi2.ParallelBitDeposit(x >> 16, 0x44444444U)
+                    |  Bmi2.ParallelBitDeposit(x >>  8, 0x22222222U)
+                    |  Bmi2.ParallelBitDeposit(x      , 0x11111111U);
+            }
+#endif
+
             // "shuffle" (twice) low half to even bits and high half to odd bits
             x = Bits.BitPermuteStep(x, 0x00AA00AAU, 7);
             x = Bits.BitPermuteStep(x, 0x0000CCCCU, 14);
@@ -187,6 +213,14 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static uint Unshuffle(uint x)
         {
+#if NETCOREAPP3_0_OR_GREATER
+            if (Bmi2.IsSupported)
+            {
+                return Bmi2.ParallelBitExtract(x, 0xAAAAAAAAU) << 16
+                    |  Bmi2.ParallelBitExtract(x, 0x55555555U);
+            }
+#endif
+
             // "unshuffle" even bits to low half and odd bits to high half
             x = Bits.BitPermuteStep(x, 0x22222222U, 1);
             x = Bits.BitPermuteStep(x, 0x0C0C0C0CU, 2);
@@ -249,6 +283,16 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static uint Unshuffle2(uint x)
         {
+#if NETCOREAPP3_0_OR_GREATER
+            if (Bmi2.IsSupported)
+            {
+                return Bmi2.ParallelBitExtract(x, 0x88888888U) << 24
+                    |  Bmi2.ParallelBitExtract(x, 0x44444444U) << 16
+                    |  Bmi2.ParallelBitExtract(x, 0x22222222U) <<  8
+                    |  Bmi2.ParallelBitExtract(x, 0x11111111U);
+            }
+#endif
+
             // "unshuffle" (twice) even bits to low half and odd bits to high half
             x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
             x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);