Skip to content

Commit

Permalink
NibblePath different equality (#377)
Browse files Browse the repository at this point in the history
* shorter comparison

* different equals

* format

* better benchmarks
  • Loading branch information
Scooletz committed Jul 26, 2024
1 parent d91122a commit 92dca5d
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 4 deletions.
11 changes: 10 additions & 1 deletion src/Paprika.Benchmarks/NibblePathBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,16 @@ public bool Equals_not_equal_sliced()
}

[Benchmark(OperationsPerInvoke = 2)]
public bool Equals_equal_sliced()
[Arguments(0, 1)]
[Arguments(1, 1)]
[Arguments(0, 16)]
[Arguments(1, 16)]
[Arguments(0, 32)]
[Arguments(1, 32)]
[Arguments(0, 48)]
[Arguments(1, 48)]
[Arguments(0, NibblePath.KeccakNibbleCount)]
public bool Equals(int slice, int length)
{
// hammer odd and not
var a = NibblePath.FromKey(A1);
Expand Down
50 changes: 47 additions & 3 deletions src/Paprika/Data/NibblePath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -646,10 +646,54 @@ public override string ToString()

public bool Equals(in NibblePath other)
{
if (other.Length != Length || (other._odd & OddBit) != (_odd & OddBit))
if (((other.Length ^ Length) | (other._odd ^ _odd)) > 0)
return false;

return FindFirstDifferentNibble(other) == Length;
ref var left = ref _span;
ref var right = ref other._span;
var length = Length;

if (other._odd == OddBit)
{
// This means first byte is not a whole byte
if (((left ^ right) & NibbleMask) > 0)
{
// First nibble differs
return false;
}

// Move beyond first
left = ref Unsafe.Add(ref left, 1);
right = ref Unsafe.Add(ref right, 1);

// One nibble already consumed, reduce the length
length -= 1;
}

if ((length & OddBit) == OddBit)
{
const int highNibbleMask = NibbleMask << NibbleShift;

// Length is odd, which requires checking the last byte but only the first nibble
if (((Unsafe.Add(ref left, length >> 1) ^ Unsafe.Add(ref right, length >> 1))
& highNibbleMask) > 0)
{
return false;
}

// Last nibble already consumed, reduce the length
length -= 1;
}

if (length == 0)
return true;

Debug.Assert(length % 2 == 0);

var leftSpan = MemoryMarshal.CreateReadOnlySpan(ref left, length >> 1);
var rightSpan = MemoryMarshal.CreateReadOnlySpan(ref right, length >> 1);

return leftSpan.SequenceEqual(rightSpan);
}

public override int GetHashCode()
Expand Down Expand Up @@ -760,4 +804,4 @@ static void ThrowNotEnoughMemory()
{
throw new ArgumentException("Not enough memory to append");
}
}
}

0 comments on commit 92dca5d

Please sign in to comment.