Skip to content

Commit

Permalink
Optimize RotateLeft (#2542)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikzhang authored Jul 15, 2021
1 parent 00805f6 commit 2658cd7
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/neo/Cryptography/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static byte[] RIPEMD160(this ReadOnlySpan<byte> value)
/// <returns>The computed hash code.</returns>
public static uint Murmur32(this byte[] value, uint seed)
{
using Murmur3 murmur = new(seed);
using Murmur32 murmur = new(seed);
return BinaryPrimitives.ReadUInt32LittleEndian(murmur.ComputeHash(value));
}

Expand Down
19 changes: 7 additions & 12 deletions src/neo/Cryptography/Murmur128.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Buffers.Binary;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;

Expand Down Expand Up @@ -45,19 +46,19 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
ulong k1 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i));
k1 *= c1;
k1 = RotateLeft(k1, r1);
k1 = BitOperations.RotateLeft(k1, r1);
k1 *= c2;
H1 ^= k1;
H1 = RotateLeft(H1, 27);
H1 = BitOperations.RotateLeft(H1, 27);
H1 += H2;
H1 = H1 * m + n1;

ulong k2 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i + 8));
k2 *= c2;
k2 = RotateLeft(k2, r2);
k2 = BitOperations.RotateLeft(k2, r2);
k2 *= c1;
H2 ^= k2;
H2 = RotateLeft(H2, 31);
H2 = BitOperations.RotateLeft(H2, 31);
H2 += H1;
H2 = H2 * m + n2;
}
Expand All @@ -84,8 +85,8 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize)
case 1: remainingBytesL ^= (ulong)array[alignedLength] << 0; break;
}

H2 ^= RotateLeft(remainingBytesH * c2, r2) * c1;
H1 ^= RotateLeft(remainingBytesL * c1, r1) * c2;
H2 ^= BitOperations.RotateLeft(remainingBytesH * c2, r2) * c1;
H1 ^= BitOperations.RotateLeft(remainingBytesL * c1, r1) * c2;
}
}

Expand Down Expand Up @@ -118,12 +119,6 @@ public override void Initialize()
length = 0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong RotateLeft(ulong x, byte n)
{
return (x << n) | (x >> (64 - n));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong FMix(ulong h)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
using System.Numerics;
using System.Security.Cryptography;

namespace Neo.Cryptography
{
/// <summary>
/// Computes the murmur hash for the input data.
/// </summary>
public sealed class Murmur3 : HashAlgorithm
public sealed class Murmur32 : HashAlgorithm
{
private const uint c1 = 0xcc9e2d51;
private const uint c2 = 0x1b873593;
Expand All @@ -24,10 +24,10 @@ public sealed class Murmur3 : HashAlgorithm
public override int HashSize => 32;

/// <summary>
/// Initializes a new instance of the <see cref="Murmur3"/> class with the specified seed.
/// Initializes a new instance of the <see cref="Murmur32"/> class with the specified seed.
/// </summary>
/// <param name="seed">The seed to be used.</param>
public Murmur3(uint seed)
public Murmur32(uint seed)
{
this.seed = seed;
Initialize();
Expand All @@ -42,10 +42,10 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
uint k = BinaryPrimitives.ReadUInt32LittleEndian(array.AsSpan(i));
k *= c1;
k = RotateLeft(k, r1);
k = BitOperations.RotateLeft(k, r1);
k *= c2;
hash ^= k;
hash = RotateLeft(hash, r2);
hash = BitOperations.RotateLeft(hash, r2);
hash = hash * m + n;
}
if (remainder > 0)
Expand All @@ -58,7 +58,7 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize)
case 1: remainingBytes ^= array[alignedLength]; break;
}
remainingBytes *= c1;
remainingBytes = RotateLeft(remainingBytes, r1);
remainingBytes = BitOperations.RotateLeft(remainingBytes, r1);
remainingBytes *= c2;
hash ^= remainingBytes;
}
Expand All @@ -83,11 +83,5 @@ public override void Initialize()
hash = seed;
length = 0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint RotateLeft(uint x, byte n)
{
return (x << n) | (x >> (32 - n));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
namespace Neo.UnitTests.Cryptography
{
[TestClass]
public class UT_Murmur3
public class UT_Murmur32
{
[TestMethod]
public void TestGetHashSize()
{
Murmur3 murmur3 = new Murmur3(1);
Murmur32 murmur3 = new Murmur32(1);
murmur3.HashSize.Should().Be(32);
}

Expand Down

0 comments on commit 2658cd7

Please sign in to comment.