summary refs log tree commit diff
path: root/crypto/src/math
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-11-20 14:41:31 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-11-20 14:41:31 +0700
commitfc3fa1f342ac19fbe7ee27b3a20a6a246ef0a1e9 (patch)
treeaa9da31e1414c355521356e6e7a84225813191f3 /crypto/src/math
parentFactor Codec out of EdDSA (diff)
downloadBouncyCastle.NET-ed25519-fc3fa1f342ac19fbe7ee27b3a20a6a246ef0a1e9.tar.xz
Intrinsics for shuffles
Diffstat (limited to 'crypto/src/math')
-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);