Interleave
using Org.BouncyCastle.Runtime.Intrinsics.X86;
using System;
using System.Runtime.Intrinsics.X86;
namespace Org.BouncyCastle.Math.Raw
{
internal static class Interleave
{
private const ulong M32 = 1431655765;
private const ulong M64 = 6148914691236517205;
private const ulong M64R = 12297829382473034410;
internal static uint Expand8to16(byte x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.IsEnabled)
return System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x, 1431655765);
uint num = (uint)((x | (x << 4)) & 3855);
num = ((num | (num << 2)) & 13107);
return (num | (num << 1)) & 21845;
}
internal static uint Expand16to32(ushort x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.IsEnabled)
return System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x, 1431655765);
uint num = (uint)((x | (x << 8)) & 16711935);
num = ((num | (num << 4)) & 252645135);
num = ((num | (num << 2)) & 858993459);
return (num | (num << 1)) & 1431655765;
}
internal static ulong Expand32to64(uint x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.IsEnabled)
return ((ulong)System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x >> 16, 1431655765) << 32) | System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x, 1431655765);
x = Bits.BitPermuteStep(x, 65280, 8);
x = Bits.BitPermuteStep(x, 15728880, 4);
x = Bits.BitPermuteStep(x, 202116108, 2);
x = Bits.BitPermuteStep(x, 572662306, 1);
return (ulong)((((long)(x >> 1) & 1431655765) << 32) | ((long)x & 1431655765));
}
internal static void Expand64To128(ulong x, ulong[] z, int zOff)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled) {
z[zOff] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x, 6148914691236517205);
z[zOff + 1] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x >> 32, 6148914691236517205);
} else {
x = Bits.BitPermuteStep(x, 4294901760, 16);
x = Bits.BitPermuteStep(x, 280375465148160, 8);
x = Bits.BitPermuteStep(x, 67555025218437360, 4);
x = Bits.BitPermuteStep(x, 868082074056920076, 2);
x = Bits.BitPermuteStep(x, 2459565876494606882, 1);
z[zOff] = (x & 6148914691236517205);
z[zOff + 1] = ((x >> 1) & 6148914691236517205);
}
}
internal static void Expand64To128(ulong x, Span<ulong> z)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled) {
z[0] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x, 6148914691236517205);
z[1] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x >> 32, 6148914691236517205);
} else {
x = Bits.BitPermuteStep(x, 4294901760, 16);
x = Bits.BitPermuteStep(x, 280375465148160, 8);
x = Bits.BitPermuteStep(x, 67555025218437360, 4);
x = Bits.BitPermuteStep(x, 868082074056920076, 2);
x = Bits.BitPermuteStep(x, 2459565876494606882, 1);
z[0] = (x & 6148914691236517205);
z[1] = ((x >> 1) & 6148914691236517205);
}
}
internal static void Expand64To128(ulong[] xs, int xsOff, int xsLen, ulong[] zs, int zsOff)
{
int num = xsLen;
int num2 = zsOff + (xsLen << 1);
while (--num >= 0) {
num2 -= 2;
Expand64To128(xs[xsOff + num], zs, num2);
}
}
internal static void Expand64To128(ReadOnlySpan<ulong> xs, Span<ulong> zs)
{
int num = xs.Length;
int num2 = xs.Length << 1;
while (--num >= 0) {
num2 -= 2;
ulong x = xs[num];
int num3 = num2;
Expand64To128(x, zs.Slice(num3, zs.Length - num3));
}
}
internal static ulong Expand64To128Rev(ulong x, out ulong low)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled) {
low = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x >> 32, 12297829382473034410);
return System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x, 12297829382473034410);
}
x = Bits.BitPermuteStep(x, 4294901760, 16);
x = Bits.BitPermuteStep(x, 280375465148160, 8);
x = Bits.BitPermuteStep(x, 67555025218437360, 4);
x = Bits.BitPermuteStep(x, 868082074056920076, 2);
x = Bits.BitPermuteStep(x, 2459565876494606882, 1);
low = (ulong)((long)x & -6148914691236517206);
return (ulong)((long)(x << 1) & -6148914691236517206);
}
internal static uint Shuffle(uint x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.IsEnabled)
return System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x >> 16, 2863311530) | System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x, 1431655765);
x = Bits.BitPermuteStep(x, 65280, 8);
x = Bits.BitPermuteStep(x, 15728880, 4);
x = Bits.BitPermuteStep(x, 202116108, 2);
x = Bits.BitPermuteStep(x, 572662306, 1);
return x;
}
internal static ulong Shuffle(ulong x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled)
return System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x >> 32, 12297829382473034410) | System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x, 6148914691236517205);
x = Bits.BitPermuteStep(x, 4294901760, 16);
x = Bits.BitPermuteStep(x, 280375465148160, 8);
x = Bits.BitPermuteStep(x, 67555025218437360, 4);
x = Bits.BitPermuteStep(x, 868082074056920076, 2);
x = Bits.BitPermuteStep(x, 2459565876494606882, 1);
return x;
}
internal static uint Shuffle2(uint x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.IsEnabled)
return System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x >> 24, 2290649224) | System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x >> 16, 1145324612) | System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x >> 8, 572662306) | System.Runtime.Intrinsics.X86.Bmi2.ParallelBitDeposit(x, 286331153);
x = Bits.BitPermuteStep(x, 61680, 12);
x = Bits.BitPermuteStep(x, 13369548, 6);
x = Bits.BitPermuteStep(x, 572662306, 1);
x = Bits.BitPermuteStep(x, 202116108, 2);
return x;
}
internal static ulong Shuffle2(ulong x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled)
return System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x >> 48, 9838263505978427528) | System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x >> 32, 4919131752989213764) | System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x >> 16, 2459565876494606882) | System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x, 1229782938247303441);
x = Bits.BitPermuteStep(x, 4278255360, 24);
x = Bits.BitPermuteStep(x, 264913582878960, 12);
x = Bits.BitPermuteStep(x, 57421771435671756, 6);
x = Bits.BitPermuteStep(x, 723401728380766730, 3);
return x;
}
internal static uint Unshuffle(uint x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.IsEnabled)
return (System.Runtime.Intrinsics.X86.Bmi2.ParallelBitExtract(x, 2863311530) << 16) | System.Runtime.Intrinsics.X86.Bmi2.ParallelBitExtract(x, 1431655765);
x = Bits.BitPermuteStep(x, 572662306, 1);
x = Bits.BitPermuteStep(x, 202116108, 2);
x = Bits.BitPermuteStep(x, 15728880, 4);
x = Bits.BitPermuteStep(x, 65280, 8);
return x;
}
internal static ulong Unshuffle(ulong x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled)
return (System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 12297829382473034410) << 32) | System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 6148914691236517205);
x = Bits.BitPermuteStep(x, 2459565876494606882, 1);
x = Bits.BitPermuteStep(x, 868082074056920076, 2);
x = Bits.BitPermuteStep(x, 67555025218437360, 4);
x = Bits.BitPermuteStep(x, 280375465148160, 8);
x = Bits.BitPermuteStep(x, 4294901760, 16);
return x;
}
internal static ulong Unshuffle(ulong x, out ulong even)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled) {
even = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 6148914691236517205);
return System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 12297829382473034410);
}
ulong num = Unshuffle(x);
even = (num & uint.MaxValue);
return num >> 32;
}
internal static ulong Unshuffle(ulong x0, ulong x1, out ulong even)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled) {
even = (System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x0, 6148914691236517205) | (System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x1, 6148914691236517205) << 32));
return System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x0, 12297829382473034410) | (System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x1, 12297829382473034410) << 32);
}
ulong num = Unshuffle(x0);
ulong num2 = Unshuffle(x1);
even = ((num2 << 32) | (num & uint.MaxValue));
return (ulong)((long)(num >> 32) | ((long)num2 & -4294967296));
}
internal static uint Unshuffle2(uint x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.IsEnabled)
return (System.Runtime.Intrinsics.X86.Bmi2.ParallelBitExtract(x, 2290649224) << 24) | (System.Runtime.Intrinsics.X86.Bmi2.ParallelBitExtract(x, 1145324612) << 16) | (System.Runtime.Intrinsics.X86.Bmi2.ParallelBitExtract(x, 572662306) << 8) | System.Runtime.Intrinsics.X86.Bmi2.ParallelBitExtract(x, 286331153);
x = Bits.BitPermuteStep(x, 202116108, 2);
x = Bits.BitPermuteStep(x, 572662306, 1);
x = Bits.BitPermuteStep(x, 61680, 12);
x = Bits.BitPermuteStep(x, 13369548, 6);
return x;
}
internal static ulong Unshuffle2(ulong x)
{
if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled)
return (System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 9838263505978427528) << 48) | (System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 4919131752989213764) << 32) | (System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 2459565876494606882) << 16) | System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitExtract(x, 1229782938247303441);
x = Bits.BitPermuteStep(x, 57421771435671756, 6);
x = Bits.BitPermuteStep(x, 723401728380766730, 3);
x = Bits.BitPermuteStep(x, 4278255360, 24);
x = Bits.BitPermuteStep(x, 264913582878960, 12);
return x;
}
internal static ulong Transpose(ulong x)
{
x = Bits.BitPermuteStep(x, 4042322160, 28);
x = Bits.BitPermuteStep(x, 225176545447116, 14);
x = Bits.BitPermuteStep(x, 47851476196393130, 7);
return x;
}
}
}