using System.Numerics.BitOperations.RotateLeft() for taking advantage of CPU interiniscs for bit rotation

This commit is contained in:
Havij khor 2020-02-15 01:07:38 +03:30
parent d9afd59a93
commit 7b907932cd
4 changed files with 83 additions and 52 deletions

View File

@ -0,0 +1,27 @@
using System.Runtime.CompilerServices;
namespace Standart.Hash.xxHash
{
internal static class BitUtils
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateLeft(uint value, int offset)
{
#if FCL_BITOPS
return System.Numerics.BitOperations.RotateLeft(value, offset);
#else
return (value << offset) | (value >> (32 - offset));
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateLeft(ulong value, int offset) // Taken help from: https://stackoverflow.com/a/48580489/5592276
{
#if FCL_BITOPS
return System.Numerics.BitOperations.RotateLeft(value, offset);
#else
return (value << offset) | (value >> (64 - offset));
#endif
}
}
}

View File

@ -13,4 +13,8 @@
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemTasks)" /> <PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemTasks)" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="$(TargetFramework) == 'netcoreapp3.1'">
<DefineConstants>FCL_BITOPS</DefineConstants>
</PropertyGroup>
</Project> </Project>

View File

@ -35,31 +35,31 @@
do do
{ {
v1 += *((uint*)ptr) * p2; v1 += *((uint*)ptr) * p2;
v1 = (v1 << 13) | (v1 >> (32 - 13)); // rotl 13 v1 = BitUtils.RotateLeft(v1, 13); // rotl 13
v1 *= p1; v1 *= p1;
ptr += 4; ptr += 4;
v2 += *((uint*)ptr) * p2; v2 += *((uint*)ptr) * p2;
v2 = (v2 << 13) | (v2 >> (32 - 13)); // rotl 13 v2 = BitUtils.RotateLeft(v2, 13); // rotl 13
v2 *= p1; v2 *= p1;
ptr += 4; ptr += 4;
v3 += *((uint*)ptr) * p2; v3 += *((uint*)ptr) * p2;
v3 = (v3 << 13) | (v3 >> (32 - 13)); // rotl 13 v3 = BitUtils.RotateLeft(v3, 13); // rotl 13
v3 *= p1; v3 *= p1;
ptr += 4; ptr += 4;
v4 += *((uint*)ptr) * p2; v4 += *((uint*)ptr) * p2;
v4 = (v4 << 13) | (v4 >> (32 - 13)); // rotl 13 v4 = BitUtils.RotateLeft(v4, 13); // rotl 13
v4 *= p1; v4 *= p1;
ptr += 4; ptr += 4;
} while (ptr <= limit); } while (ptr <= limit);
h32 = ((v1 << 1) | (v1 >> (32 - 1))) + // rotl 1 h32 = BitUtils.RotateLeft(v1, 1) + // rotl 1
((v2 << 7) | (v2 >> (32 - 7))) + // rotl 7 BitUtils.RotateLeft(v2, 7) + // rotl 7
((v3 << 12) | (v3 >> (32 - 12))) + // rotl 12 BitUtils.RotateLeft(v3, 12) + // rotl 12
((v4 << 18) | (v4 >> (32 - 18))); // rotl 18 BitUtils.RotateLeft(v4, 18); // rotl 18
} }
else else
{ {
@ -72,14 +72,14 @@
while (ptr <= end - 4) while (ptr <= end - 4)
{ {
h32 += *((uint*)ptr) * p3; h32 += *((uint*)ptr) * p3;
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * p4; // (rotl 17) * p4 h32 = BitUtils.RotateLeft(h32, 17) * p4; // (rotl 17) * p4
ptr += 4; ptr += 4;
} }
while (ptr < end) while (ptr < end)
{ {
h32 += *((byte*)ptr) * p5; h32 += *((byte*)ptr) * p5;
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * p1; // (rotl 11) * p1 h32 = BitUtils.RotateLeft(h32, 11) * p1; // (rotl 11) * p1
ptr += 1; ptr += 1;
} }
@ -113,22 +113,22 @@
do do
{ {
v1 += *((uint*)ptr) * p2; v1 += *((uint*)ptr) * p2;
v1 = (v1 << 13) | (v1 >> (32 - 13)); // rotl 13 v1 = BitUtils.RotateLeft(v1, 13); // rotl 13
v1 *= p1; v1 *= p1;
ptr += 4; ptr += 4;
v2 += *((uint*)ptr) * p2; v2 += *((uint*)ptr) * p2;
v2 = (v2 << 13) | (v2 >> (32 - 13)); // rotl 13 v2 = BitUtils.RotateLeft(v2, 13); // rotl 13
v2 *= p1; v2 *= p1;
ptr += 4; ptr += 4;
v3 += *((uint*)ptr) * p2; v3 += *((uint*)ptr) * p2;
v3 = (v3 << 13) | (v3 >> (32 - 13)); // rotl 13 v3 = BitUtils.RotateLeft(v3, 13); // rotl 13
v3 *= p1; v3 *= p1;
ptr += 4; ptr += 4;
v4 += *((uint*)ptr) * p2; v4 += *((uint*)ptr) * p2;
v4 = (v4 << 13) | (v4 >> (32 - 13)); // rotl 13 v4 = BitUtils.RotateLeft(v4, 13); // rotl 13
v4 *= p1; v4 *= p1;
ptr += 4; ptr += 4;
@ -159,10 +159,10 @@
if (length >= 16) if (length >= 16)
{ {
h32 = ((v1 << 1) | (v1 >> (32 - 1))) + // rotl 1 h32 = BitUtils.RotateLeft(v1, 1) + // rotl 1
((v2 << 7) | (v2 >> (32 - 7))) + // rotl 7 BitUtils.RotateLeft(v2, 7) + // rotl 7
((v3 << 12) | (v3 >> (32 - 12))) + // rotl 12 BitUtils.RotateLeft(v3, 12) + // rotl 12
((v4 << 18) | (v4 >> (32 - 18))); // rotl 18 BitUtils.RotateLeft(v4, 18); // rotl 18
} }
else else
{ {
@ -175,14 +175,14 @@
while (ptr <= end - 4) while (ptr <= end - 4)
{ {
h32 += *((uint*)ptr) * p3; h32 += *((uint*)ptr) * p3;
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * p4; // (rotl 17) * p4 h32 = BitUtils.RotateLeft(h32, 17) * p4; // (rotl 17) * p4
ptr += 4; ptr += 4;
} }
while (ptr < end) while (ptr < end)
{ {
h32 += *((byte*)ptr) * p5; h32 += *((byte*)ptr) * p5;
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * p1; // (rotl 11) * p1 h32 = BitUtils.RotateLeft(h32, 11) * p1; // (rotl 11) * p1
ptr += 1; ptr += 1;
} }

View File

@ -36,56 +36,56 @@
do do
{ {
v1 += *((ulong*)ptr) * p2; v1 += *((ulong*)ptr) * p2;
v1 = (v1 << 31) | (v1 >> (64 - 31)); // rotl 31 v1 = BitUtils.RotateLeft(v1, 31); // rotl 31
v1 *= p1; v1 *= p1;
ptr += 8; ptr += 8;
v2 += *((ulong*)ptr) * p2; v2 += *((ulong*)ptr) * p2;
v2 = (v2 << 31) | (v2 >> (64 - 31)); // rotl 31 v2 = BitUtils.RotateLeft(v2, 31); // rotl 31
v2 *= p1; v2 *= p1;
ptr += 8; ptr += 8;
v3 += *((ulong*)ptr) * p2; v3 += *((ulong*)ptr) * p2;
v3 = (v3 << 31) | (v3 >> (64 - 31)); // rotl 31 v3 = BitUtils.RotateLeft(v3, 31); // rotl 31
v3 *= p1; v3 *= p1;
ptr += 8; ptr += 8;
v4 += *((ulong*)ptr) * p2; v4 += *((ulong*)ptr) * p2;
v4 = (v4 << 31) | (v4 >> (64 - 31)); // rotl 31 v4 = BitUtils.RotateLeft(v4, 31); // rotl 31
v4 *= p1; v4 *= p1;
ptr += 8; ptr += 8;
} while (ptr <= limit); } while (ptr <= limit);
h64 = ((v1 << 1) | (v1 >> (64 - 1))) + // rotl 1 h64 = BitUtils.RotateLeft(v1, 1) + // rotl 1
((v2 << 7) | (v2 >> (64 - 7))) + // rotl 7 BitUtils.RotateLeft(v2, 7) + // rotl 7
((v3 << 12) | (v3 >> (64 - 12))) + // rotl 12 BitUtils.RotateLeft(v3, 12) + // rotl 12
((v4 << 18) | (v4 >> (64 - 18))); // rotl 18 BitUtils.RotateLeft(v4, 18); // rotl 18
// merge round // merge round
v1 *= p2; v1 *= p2;
v1 = (v1 << 31) | (v1 >> (64 - 31)); // rotl 31 v1 = BitUtils.RotateLeft(v1, 31); // rotl 31
v1 *= p1; v1 *= p1;
h64 ^= v1; h64 ^= v1;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
// merge round // merge round
v2 *= p2; v2 *= p2;
v2 = (v2 << 31) | (v2 >> (64 - 31)); // rotl 31 v2 = BitUtils.RotateLeft(v2, 31); // rotl 31
v2 *= p1; v2 *= p1;
h64 ^= v2; h64 ^= v2;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
// merge round // merge round
v3 *= p2; v3 *= p2;
v3 = (v3 << 31) | (v3 >> (64 - 31)); // rotl 31 v3 = BitUtils.RotateLeft(v3, 31); // rotl 31
v3 *= p1; v3 *= p1;
h64 ^= v3; h64 ^= v3;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
// merge round // merge round
v4 *= p2; v4 *= p2;
v4 = (v4 << 31) | (v4 >> (64 - 31)); // rotl 31 v4 = BitUtils.RotateLeft(v4, 31); // rotl 31
v4 *= p1; v4 *= p1;
h64 ^= v4; h64 ^= v4;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
@ -101,24 +101,24 @@
while (ptr <= end - 8) while (ptr <= end - 8)
{ {
ulong t1 = *((ulong*)ptr) * p2; ulong t1 = *((ulong*)ptr) * p2;
t1 = (t1 << 31) | (t1 >> (64 - 31)); // rotl 31 t1 = BitUtils.RotateLeft(t1, 31); // rotl 31
t1 *= p1; t1 *= p1;
h64 ^= t1; h64 ^= t1;
h64 = ((h64 << 27) | (h64 >> (64 - 27))) * p1 + p4; // (rotl 27) * p1 + p4 h64 = BitUtils.RotateLeft(h64, 27) * p1 + p4; // (rotl 27) * p1 + p4
ptr += 8; ptr += 8;
} }
if (ptr <= end - 4) if (ptr <= end - 4)
{ {
h64 ^= *((uint*)ptr) * p1; h64 ^= *((uint*)ptr) * p1;
h64 = ((h64 << 23) | (h64 >> (64 - 23))) * p2 + p3; // (rotl 27) * p2 + p3 h64 = BitUtils.RotateLeft(h64, 23) * p2 + p3; // (rotl 27) * p2 + p3
ptr += 4; ptr += 4;
} }
while (ptr < end) while (ptr < end)
{ {
h64 ^= *((byte*)ptr) * p5; h64 ^= *((byte*)ptr) * p5;
h64 = ((h64 << 11) | (h64 >> (64 - 11))) * p1; // (rotl 11) * p1 h64 = BitUtils.RotateLeft(h64, 11) * p1; // (rotl 11) * p1
ptr += 1; ptr += 1;
} }
@ -152,22 +152,22 @@
do do
{ {
v1 += *((ulong*)ptr) * p2; v1 += *((ulong*)ptr) * p2;
v1 = (v1 << 31) | (v1 >> (64 - 31)); // rotl 31 v1 = BitUtils.RotateLeft(v1, 31); // rotl 31
v1 *= p1; v1 *= p1;
ptr += 8; ptr += 8;
v2 += *((ulong*)ptr) * p2; v2 += *((ulong*)ptr) * p2;
v2 = (v2 << 31) | (v2 >> (64 - 31)); // rotl 31 v2 = BitUtils.RotateLeft(v2, 31); // rotl 31
v2 *= p1; v2 *= p1;
ptr += 8; ptr += 8;
v3 += *((ulong*)ptr) * p2; v3 += *((ulong*)ptr) * p2;
v3 = (v3 << 31) | (v3 >> (64 - 31)); // rotl 31 v3 = BitUtils.RotateLeft(v3, 31); // rotl 31
v3 *= p1; v3 *= p1;
ptr += 8; ptr += 8;
v4 += *((ulong*)ptr) * p2; v4 += *((ulong*)ptr) * p2;
v4 = (v4 << 31) | (v4 >> (64 - 31)); // rotl 31 v4 = BitUtils.RotateLeft(v4, 31); // rotl 31
v4 *= p1; v4 *= p1;
ptr += 8; ptr += 8;
@ -198,35 +198,35 @@
if (length >= 32) if (length >= 32)
{ {
h64 = ((v1 << 1) | (v1 >> (64 - 1))) + // rotl 1 h64 = BitUtils.RotateLeft(v1, 1) + // rotl 1
((v2 << 7) | (v2 >> (64 - 7))) + // rotl 7 BitUtils.RotateLeft(v2, 7) + // rotl 7
((v3 << 12) | (v3 >> (64 - 12))) + // rotl 12 BitUtils.RotateLeft(v3, 12) + // rotl 12
((v4 << 18) | (v4 >> (64 - 18))); // rotl 18 BitUtils.RotateLeft(v4, 18); // rotl 18
// merge round // merge round
v1 *= p2; v1 *= p2;
v1 = (v1 << 31) | (v1 >> (64 - 31)); // rotl 31 v1 = BitUtils.RotateLeft(v1, 31); // rotl 31
v1 *= p1; v1 *= p1;
h64 ^= v1; h64 ^= v1;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
// merge round // merge round
v2 *= p2; v2 *= p2;
v2 = (v2 << 31) | (v2 >> (64 - 31)); // rotl 31 v2 = BitUtils.RotateLeft(v2, 31); // rotl 31
v2 *= p1; v2 *= p1;
h64 ^= v2; h64 ^= v2;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
// merge round // merge round
v3 *= p2; v3 *= p2;
v3 = (v3 << 31) | (v3 >> (64 - 31)); // rotl 31 v3 = BitUtils.RotateLeft(v3, 31); // rotl 31
v3 *= p1; v3 *= p1;
h64 ^= v3; h64 ^= v3;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
// merge round // merge round
v4 *= p2; v4 *= p2;
v4 = (v4 << 31) | (v4 >> (64 - 31)); // rotl 31 v4 = BitUtils.RotateLeft(v4, 31); // rotl 31
v4 *= p1; v4 *= p1;
h64 ^= v4; h64 ^= v4;
h64 = h64 * p1 + p4; h64 = h64 * p1 + p4;
@ -243,24 +243,24 @@
while (ptr <= end - 8) while (ptr <= end - 8)
{ {
ulong t1 = *((ulong*)ptr) * p2; ulong t1 = *((ulong*)ptr) * p2;
t1 = (t1 << 31) | (t1 >> (64 - 31)); // rotl 31 t1 = BitUtils.RotateLeft(t1, 31); // rotl 31
t1 *= p1; t1 *= p1;
h64 ^= t1; h64 ^= t1;
h64 = ((h64 << 27) | (h64 >> (64 - 27))) * p1 + p4; // (rotl 27) * p1 + p4 h64 = BitUtils.RotateLeft(h64, 27) * p1 + p4; // (rotl 27) * p1 + p4
ptr += 8; ptr += 8;
} }
if (ptr <= end - 4) if (ptr <= end - 4)
{ {
h64 ^= *((uint*)ptr) * p1; h64 ^= *((uint*)ptr) * p1;
h64 = ((h64 << 23) | (h64 >> (64 - 23))) * p2 + p3; // (rotl 27) * p2 + p3 h64 = BitUtils.RotateLeft(h64, 23) * p2 + p3; // (rotl 27) * p2 + p3
ptr += 4; ptr += 4;
} }
while (ptr < end) while (ptr < end)
{ {
h64 ^= *((byte*)ptr) * p5; h64 ^= *((byte*)ptr) * p5;
h64 = ((h64 << 11) | (h64 >> (64 - 11))) * p1; // (rotl 11) * p1 h64 = BitUtils.RotateLeft(h64, 11) * p1; // (rotl 11) * p1
ptr += 1; ptr += 1;
} }