Added Span api
This commit is contained in:
parent
4b019f5c48
commit
4b35057191
@ -15,7 +15,7 @@
|
||||
<img src="https://codecov.io/gh/uranium62/xxHash/branch/master/graph/badge.svg" alt="coverage"/>
|
||||
</a>
|
||||
<a href="https://www.nuget.org/packages/Standart.Hash.xxHash">
|
||||
<img src="https://img.shields.io/badge/nuget-1.0.4-green.svg?style=flat-square" alt="nuget"/>
|
||||
<img src="https://img.shields.io/badge/nuget-1.0.5-green.svg?style=flat-square" alt="nuget"/>
|
||||
</a>
|
||||
<a href="https://www.nuget.org/packages/Standart.Hash.xxHash">
|
||||
<img src="https://img.shields.io/badge/platform-x64-blue.svg?longCache=true" alt="platform"/>
|
||||
@ -39,16 +39,20 @@ This benchmark was launched on a **Windows 10 (10.0.16299.309)**. The reference
|
||||
|---------------|----------:|
|
||||
| Hash32 Array | 5.05 GB/s |
|
||||
| Hash64 Array | 8.92 GB/s |
|
||||
| Hash32 Span | 5.05 GB/s |
|
||||
| Hash64 Span | 8.92 GB/s |
|
||||
| Hash32 Stream | 3.22 GB/s |
|
||||
| Hash64 Stream | 4.81 GB/s |
|
||||
|
||||
## Api
|
||||
```cs
|
||||
public static uint ComputeHash(byte[] data, int length, uint seed = 0) { throw null; }
|
||||
public static uint ComputeHash(Span<byte> data, int length, uint seed = 0) { throw null; }
|
||||
public static uint ComputeHash(Stream stream, int bufferSize = 4096, uint seed = 0) { throw null; }
|
||||
public static async Task<uint> ComputeHashAsync(Stream stream, int bufferSize = 4096, uint seed = 0) { throw null; }
|
||||
|
||||
public static ulong ComputeHash(byte[] data, int length, ulong seed = 0) { throw null; }
|
||||
public static ulong ComputeHash(Span<byte> data, int length, ulong seed = 0) { throw null; }
|
||||
public static ulong ComputeHash(Stream stream, int bufferSize = 8192, ulong seed = 0) { throw null; }
|
||||
public static async Task<ulong> ComputeHashAsync(Stream stream, int bufferSize = 8192, ulong seed = 0) { throw null; }
|
||||
```
|
||||
|
||||
12
deps.props
12
deps.props
@ -1,11 +1,13 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<SystemBuffers>4.4.0</SystemBuffers>
|
||||
<SystemBuffers>4.5.0</SystemBuffers>
|
||||
<SystemIO>4.3.0</SystemIO>
|
||||
<BenchmarkDotNet>0.10.14</BenchmarkDotNet>
|
||||
<MicrosoftSdk>15.6.0</MicrosoftSdk>
|
||||
<xUnit>2.3.1</xUnit>
|
||||
<xUnitRunner>2.3.1</xUnitRunner>
|
||||
<SystemMemory>4.5.1</SystemMemory>
|
||||
<SystemTasks>4.5.1</SystemTasks>
|
||||
<BenchmarkDotNet>0.11.1</BenchmarkDotNet>
|
||||
<MicrosoftSdk>15.8.0</MicrosoftSdk>
|
||||
<xUnit>2.4.0</xUnit>
|
||||
<xUnitRunner>2.4.0</xUnitRunner>
|
||||
<xUnitTool>2.3.1</xUnitTool>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<PackageId>Standart.Hash.xxHash</PackageId>
|
||||
<VersionPrefix>1.0.4</VersionPrefix>
|
||||
<VersionPrefix>1.0.5</VersionPrefix>
|
||||
<AssemblyName>Standart.Hash.xxHash</AssemblyName>
|
||||
<AssemblyTitle>Standart.Hash.xxHash</AssemblyTitle>
|
||||
<Authors>Alexander Melnik</Authors>
|
||||
|
||||
@ -2,13 +2,11 @@
|
||||
{
|
||||
using System;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Attributes.Columns;
|
||||
using BenchmarkDotNet.Attributes.Exporters;
|
||||
|
||||
[RPlotExporter, RankColumn]
|
||||
[MinColumn, MaxColumn]
|
||||
[MemoryDiagnoser]
|
||||
public class xxBufferBenchmark
|
||||
public class UnsafeBufferBenchmark
|
||||
{
|
||||
private byte[] src;
|
||||
private byte[] des;
|
||||
@ -33,9 +31,9 @@
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void xxBufferCopy()
|
||||
public void UnsafeBufferCopy()
|
||||
{
|
||||
xxBuffer.BlockCopy(src, 0, des, 0, 32);
|
||||
UnsafeBuffer.BlockCopy(src, 0, des, 0, 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,8 +4,6 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Attributes.Columns;
|
||||
using BenchmarkDotNet.Attributes.Exporters;
|
||||
|
||||
[RPlotExporter, RankColumn]
|
||||
[MinColumn, MaxColumn]
|
||||
@ -32,11 +30,18 @@
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public uint Hash32()
|
||||
public uint Hash32_Array()
|
||||
{
|
||||
return xxHash32.ComputeHash(data, data.Length);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public uint Hash32_Span()
|
||||
{
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
return xxHash32.ComputeHash(span, span.Length);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public uint Hash32_Stream()
|
||||
{
|
||||
@ -52,11 +57,18 @@
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public ulong Hash64()
|
||||
public ulong Hash64_Array()
|
||||
{
|
||||
return xxHash64.ComputeHash(data, data.Length);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public ulong Hash64_Span()
|
||||
{
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
return xxHash64.ComputeHash(span, span.Length);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public ulong Hash64_Stream()
|
||||
{
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
public class xxBufferTest
|
||||
public class UnsafeBufferTest
|
||||
{
|
||||
[Fact]
|
||||
public void Copy_different_blocks()
|
||||
@ -27,7 +27,7 @@
|
||||
// Act, Assert
|
||||
foreach (int count in counts)
|
||||
{
|
||||
xxBuffer.BlockCopy(src, 0, dst, 0, count);
|
||||
UnsafeBuffer.BlockCopy(src, 0, dst, 0, count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
@ -12,12 +12,15 @@
|
||||
{
|
||||
// Arrange
|
||||
byte[] data = {0xde};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
uint hash = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (uint) 0x2330eac0);
|
||||
Assert.Equal(hash1, (uint) 0x2330eac0);
|
||||
Assert.Equal(hash2, (uint) 0x2330eac0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -25,12 +28,15 @@
|
||||
{
|
||||
// Arrange
|
||||
byte[] data = {0xde, 0x55, 0x47, 0x7f, 0x14};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
uint hash = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (uint) 0x112348ba);
|
||||
Assert.Equal(hash1, (uint) 0x112348ba);
|
||||
Assert.Equal(hash2, (uint) 0x112348ba);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -42,12 +48,15 @@
|
||||
0xde, 0x55, 0x47, 0x7f, 0x14, 0x8f, 0xf1, 0x48,
|
||||
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb
|
||||
};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
uint hash = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (uint) 0xcdf89609);
|
||||
Assert.Equal(hash1, (uint) 0xcdf89609);
|
||||
Assert.Equal(hash2, (uint) 0xcdf89609);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -60,12 +69,15 @@
|
||||
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb,
|
||||
0x0e
|
||||
};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
uint hash = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (uint) 0xbca8f924);
|
||||
Assert.Equal(hash1, (uint) 0xbca8f924);
|
||||
Assert.Equal(hash2, (uint) 0xbca8f924);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -78,12 +90,15 @@
|
||||
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb,
|
||||
0x0e, 0x59, 0x4d, 0x42, 0xc5
|
||||
};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
uint hash = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (uint) 0xf4518e14);
|
||||
Assert.Equal(hash1, (uint) 0xf4518e14);
|
||||
Assert.Equal(hash2, (uint) 0xf4518e14);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -97,12 +112,15 @@
|
||||
0x0e, 0x59, 0x4d, 0x42, 0xc5, 0x07, 0x21, 0x08,
|
||||
0x1c, 0x2c, 0xc9, 0x38, 0x7d, 0x43, 0x83, 0x11,
|
||||
};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
uint hash = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (uint) 0xf8497daa);
|
||||
Assert.Equal(hash1, (uint) 0xf8497daa);
|
||||
Assert.Equal(hash2, (uint) 0xf8497daa);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@ -12,12 +12,15 @@
|
||||
{
|
||||
// Arrange
|
||||
byte[] data = {0x60};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
ulong hash = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash2 = xxHash64.ComputeHash(span, data.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (ulong) 0xb3e7ca6ca5ba3445);
|
||||
Assert.Equal(hash1, (ulong) 0xb3e7ca6ca5ba3445);
|
||||
Assert.Equal(hash2, (ulong) 0xb3e7ca6ca5ba3445);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -25,12 +28,15 @@
|
||||
{
|
||||
// Arrange
|
||||
byte[] data = {0x60, 0x82, 0x40, 0x77, 0x8a};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
ulong hash = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash2 = xxHash64.ComputeHash(span, data.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (ulong) 0x917b11ed024938fc);
|
||||
Assert.Equal(hash1, (ulong) 0x917b11ed024938fc);
|
||||
Assert.Equal(hash2, (ulong) 0x917b11ed024938fc);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -42,12 +48,15 @@
|
||||
0x60, 0x82, 0x40, 0x77, 0x8a, 0x0e, 0xe4, 0xd5,
|
||||
0x85, 0x1f, 0xa6, 0x86, 0x34,
|
||||
};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
ulong hash = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash2 = xxHash64.ComputeHash(span, data.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (ulong) 0x9d1cb0d181d58bee);
|
||||
Assert.Equal(hash1, (ulong) 0x9d1cb0d181d58bee);
|
||||
Assert.Equal(hash2, (ulong) 0x9d1cb0d181d58bee);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -61,12 +70,15 @@
|
||||
0x30, 0x5d, 0x84, 0x54, 0x15, 0xf9, 0xbd, 0x03,
|
||||
0x4b, 0x0f, 0x90, 0x4e, 0xf5, 0x57, 0x21, 0x21,
|
||||
};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
ulong hash = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash2 = xxHash64.ComputeHash(span, data.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (ulong) 0x9233096b7804e12c);
|
||||
Assert.Equal(hash1, (ulong) 0x9233096b7804e12c);
|
||||
Assert.Equal(hash2, (ulong) 0x9233096b7804e12c);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -84,12 +96,15 @@
|
||||
0x27, 0x6d, 0xb3, 0x5c, 0xc7, 0xc0, 0xd0, 0xa0,
|
||||
0x7e, 0x28, 0xce, 0x46, 0x85, 0xb7, 0x2b, 0x16,
|
||||
};
|
||||
Span<byte> span = new Span<byte>(data);
|
||||
|
||||
// Act
|
||||
ulong hash = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||
ulong hash2 = xxHash64.ComputeHash(span, data.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash, (ulong) 0x4c0a65b1ef9ea060);
|
||||
Assert.Equal(hash1, (ulong) 0x4c0a65b1ef9ea060);
|
||||
Assert.Equal(hash2, (ulong) 0x4c0a65b1ef9ea060);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
4
src/Standart.Hash.xxHash/AssemblyInfo.cs
Normal file
4
src/Standart.Hash.xxHash/AssemblyInfo.cs
Normal file
@ -0,0 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Standart.Hash.xxHash.Perf")]
|
||||
[assembly: InternalsVisibleTo("Standart.Hash.xxHash.Test")]
|
||||
@ -14,5 +14,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Buffers" Version="$(SystemBuffers)" />
|
||||
<PackageReference Include="System.IO" Version="$(SystemIO)" />
|
||||
<PackageReference Include="System.Memory" Version="$(SystemMemory)" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemTasks)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
235
src/Standart.Hash.xxHash/UnsafeBuffer.cs
Normal file
235
src/Standart.Hash.xxHash/UnsafeBuffer.cs
Normal file
@ -0,0 +1,235 @@
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
internal static class UnsafeBuffer
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe void BlockCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
||||
{
|
||||
Debug.Assert(src != null);
|
||||
Debug.Assert(dst != null);
|
||||
Debug.Assert(srcOffset >= 0 && srcOffset < src.Length);
|
||||
Debug.Assert(dstOffset >= 0 && dstOffset < dst.Length);
|
||||
Debug.Assert(count >= 0);
|
||||
Debug.Assert(count + srcOffset <= src.Length);
|
||||
Debug.Assert(count + dstOffset <= dst.Length);
|
||||
|
||||
fixed (byte* pSrc = &src[srcOffset])
|
||||
fixed (byte* pDst = &dst[dstOffset])
|
||||
{
|
||||
byte* ptrSrc = pSrc;
|
||||
byte* ptrDst = pDst;
|
||||
|
||||
SMALLTABLE:
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
*ptrDst = *ptrSrc;
|
||||
return;
|
||||
case 2:
|
||||
*(short*)ptrDst = *(short*)ptrSrc;
|
||||
return;
|
||||
case 3:
|
||||
*(short*)(ptrDst + 0) = *(short*)(ptrSrc + 0);
|
||||
*(ptrDst + 2) = *(ptrSrc + 2);
|
||||
return;
|
||||
case 4:
|
||||
*(int*)ptrDst = *(int*)ptrSrc;
|
||||
return;
|
||||
case 5:
|
||||
*(int*)(ptrDst + 0) = *(int*)(ptrSrc + 0);
|
||||
*(ptrDst + 4) = *(ptrSrc + 4);
|
||||
return;
|
||||
case 6:
|
||||
*(int*)(ptrDst + 0) = *(int*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 4) = *(short*)(ptrSrc + 4);
|
||||
return;
|
||||
case 7:
|
||||
*(int*)(ptrDst + 0) = *(int*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 4) = *(short*)(ptrSrc + 4);
|
||||
*(ptrDst + 6) = *(ptrSrc + 6);
|
||||
return;
|
||||
case 8:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
return;
|
||||
case 9:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(ptrDst + 8) = *(ptrSrc + 8);
|
||||
return;
|
||||
case 10:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 8) = *(short*)(ptrSrc + 8);
|
||||
return;
|
||||
case 11:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 8) = *(short*)(ptrSrc + 8);
|
||||
*(ptrDst + 10) = *(ptrSrc + 10);
|
||||
return;
|
||||
case 12:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
return;
|
||||
case 13:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
*(ptrDst + 12) = *(ptrSrc + 12);
|
||||
return;
|
||||
case 14:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 12) = *(short*)(ptrSrc + 12);
|
||||
return;
|
||||
case 15:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 12) = *(short*)(ptrSrc + 12);
|
||||
*(ptrDst + 14) = *(ptrSrc + 14);
|
||||
return;
|
||||
case 16:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
return;
|
||||
case 17:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(ptrDst + 16) = *(ptrSrc + 16);
|
||||
return;
|
||||
case 18:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 16) = *(short*)(ptrSrc + 16);
|
||||
return;
|
||||
case 19:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 16) = *(short*)(ptrSrc + 16);
|
||||
*(ptrDst + 18) = *(ptrSrc + 18);
|
||||
return;
|
||||
case 20:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
return;
|
||||
|
||||
case 21:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
*(ptrDst + 20) = *(ptrSrc + 20);
|
||||
return;
|
||||
case 22:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 20) = *(short*)(ptrSrc + 20);
|
||||
return;
|
||||
case 23:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 20) = *(short*)(ptrSrc + 20);
|
||||
*(ptrDst + 22) = *(ptrSrc + 22);
|
||||
return;
|
||||
case 24:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
return;
|
||||
case 25:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(ptrDst + 24) = *(ptrSrc + 24);
|
||||
return;
|
||||
case 26:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 24) = *(short*)(ptrSrc + 24);
|
||||
return;
|
||||
case 27:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 24) = *(short*)(ptrSrc + 24);
|
||||
*(ptrDst + 26) = *(ptrSrc + 26);
|
||||
return;
|
||||
case 28:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
return;
|
||||
case 29:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
*(ptrDst + 28) = *(ptrSrc + 28);
|
||||
return;
|
||||
case 30:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
*(short*)(ptrDst + 28) = *(short*)(ptrSrc + 28);
|
||||
return;
|
||||
case 31:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
*(short*)(ptrDst + 28) = *(short*)(ptrSrc + 28);
|
||||
*(ptrDst + 30) = *(ptrSrc + 30);
|
||||
return;
|
||||
case 32:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(long*)(ptrDst + 24) = *(long*)(ptrSrc + 24);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
long* lpSrc = (long*)ptrSrc;
|
||||
long* ldSrc = (long*)ptrDst;
|
||||
while (count >= 64)
|
||||
{
|
||||
*(ldSrc + 0) = *(lpSrc + 0);
|
||||
*(ldSrc + 1) = *(lpSrc + 1);
|
||||
*(ldSrc + 2) = *(lpSrc + 2);
|
||||
*(ldSrc + 3) = *(lpSrc + 3);
|
||||
*(ldSrc + 4) = *(lpSrc + 4);
|
||||
*(ldSrc + 5) = *(lpSrc + 5);
|
||||
*(ldSrc + 6) = *(lpSrc + 6);
|
||||
*(ldSrc + 7) = *(lpSrc + 7);
|
||||
if (count == 64)
|
||||
return;
|
||||
count -= 64;
|
||||
lpSrc += 8;
|
||||
ldSrc += 8;
|
||||
}
|
||||
if (count > 32)
|
||||
{
|
||||
*(ldSrc + 0) = *(lpSrc + 0);
|
||||
*(ldSrc + 1) = *(lpSrc + 1);
|
||||
*(ldSrc + 2) = *(lpSrc + 2);
|
||||
*(ldSrc + 3) = *(lpSrc + 3);
|
||||
count -= 32;
|
||||
lpSrc += 4;
|
||||
ldSrc += 4;
|
||||
}
|
||||
|
||||
ptrSrc = (byte*)lpSrc;
|
||||
ptrDst = (byte*)ldSrc;
|
||||
goto SMALLTABLE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,228 +0,0 @@
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
public static class xxBuffer
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe void BlockCopy(this byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
||||
{
|
||||
fixed (byte* ptrSrc = &src[srcOffset])
|
||||
fixed (byte* ptrDst = &dst[dstOffset])
|
||||
{
|
||||
UnsafeBlockCopy(ptrSrc, ptrDst, count);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void UnsafeBlockCopy(byte* src, byte* dst, int count)
|
||||
{
|
||||
SMALLTABLE:
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
*dst = *src;
|
||||
return;
|
||||
case 2:
|
||||
*(short*)dst = *(short*)src;
|
||||
return;
|
||||
case 3:
|
||||
*(short*)(dst + 0) = *(short*)(src + 0);
|
||||
*(dst + 2) = *(src + 2);
|
||||
return;
|
||||
case 4:
|
||||
*(int*)dst = *(int*)src;
|
||||
return;
|
||||
case 5:
|
||||
*(int*)(dst + 0) = *(int*)(src + 0);
|
||||
*(dst + 4) = *(src + 4);
|
||||
return;
|
||||
case 6:
|
||||
*(int*)(dst + 0) = *(int*)(src + 0);
|
||||
*(short*)(dst + 4) = *(short*)(src + 4);
|
||||
return;
|
||||
case 7:
|
||||
*(int*)(dst + 0) = *(int*)(src + 0);
|
||||
*(short*)(dst + 4) = *(short*)(src + 4);
|
||||
*(dst + 6) = *(src + 6);
|
||||
return;
|
||||
case 8:
|
||||
*(long*)dst = *(long*)src;
|
||||
return;
|
||||
case 9:
|
||||
*(long*)(dst + 0) = *(long*)(src + 0);
|
||||
*(dst + 8) = *(src + 8);
|
||||
return;
|
||||
case 10:
|
||||
*(long*)(dst + 0) = *(long*)(src + 0);
|
||||
*(short*)(dst + 8) = *(short*)(src + 8);
|
||||
return;
|
||||
case 11:
|
||||
*(long*)(dst + 0) = *(long*)(src + 0);
|
||||
*(short*)(dst + 8) = *(short*)(src + 8);
|
||||
*(dst + 10) = *(src + 10);
|
||||
return;
|
||||
case 12:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(int*)(dst + 8) = *(int*)(src + 8);
|
||||
return;
|
||||
case 13:
|
||||
*(long*)(dst + 0) = *(long*)(src + 0);
|
||||
*(int*)(dst + 8) = *(int*)(src + 8);
|
||||
*(dst + 12) = *(src + 12);
|
||||
return;
|
||||
case 14:
|
||||
*(long*)(dst + 0) = *(long*)(src + 0);
|
||||
*(int*)(dst + 8) = *(int*)(src + 8);
|
||||
*(short*)(dst + 12) = *(short*)(src + 12);
|
||||
return;
|
||||
case 15:
|
||||
*(long*)(dst + 0) = *(long*)(src + 0);
|
||||
*(int*)(dst + 8) = *(int*)(src + 8);
|
||||
*(short*)(dst + 12) = *(short*)(src + 12);
|
||||
*(dst + 14) = *(src + 14);
|
||||
return;
|
||||
case 16:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
return;
|
||||
case 17:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(dst + 16) = *(src + 16);
|
||||
return;
|
||||
case 18:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(short*)(dst + 16) = *(short*)(src + 16);
|
||||
return;
|
||||
case 19:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(short*)(dst + 16) = *(short*)(src + 16);
|
||||
*(dst + 18) = *(src + 18);
|
||||
return;
|
||||
case 20:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(int*)(dst + 16) = *(int*)(src + 16);
|
||||
return;
|
||||
|
||||
case 21:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(int*)(dst + 16) = *(int*)(src + 16);
|
||||
*(dst + 20) = *(src + 20);
|
||||
return;
|
||||
case 22:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(int*)(dst + 16) = *(int*)(src + 16);
|
||||
*(short*)(dst + 20) = *(short*)(src + 20);
|
||||
return;
|
||||
case 23:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(int*)(dst + 16) = *(int*)(src + 16);
|
||||
*(short*)(dst + 20) = *(short*)(src + 20);
|
||||
*(dst + 22) = *(src + 22);
|
||||
return;
|
||||
case 24:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
return;
|
||||
case 25:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(dst + 24) = *(src + 24);
|
||||
return;
|
||||
case 26:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(short*)(dst + 24) = *(short*)(src + 24);
|
||||
return;
|
||||
case 27:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(short*)(dst + 24) = *(short*)(src + 24);
|
||||
*(dst + 26) = *(src + 26);
|
||||
return;
|
||||
case 28:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(int*)(dst + 24) = *(int*)(src + 24);
|
||||
return;
|
||||
case 29:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(int*)(dst + 24) = *(int*)(src + 24);
|
||||
*(dst + 28) = *(src + 28);
|
||||
return;
|
||||
case 30:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(int*)(dst + 24) = *(int*)(src + 24);
|
||||
*(short*)(dst + 28) = *(short*)(src + 28);
|
||||
return;
|
||||
case 31:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(int*)(dst + 24) = *(int*)(src + 24);
|
||||
*(short*)(dst + 28) = *(short*)(src + 28);
|
||||
*(dst + 30) = *(src + 30);
|
||||
return;
|
||||
case 32:
|
||||
*(long*)dst = *(long*)src;
|
||||
*(long*)(dst + 8) = *(long*)(src + 8);
|
||||
*(long*)(dst + 16) = *(long*)(src + 16);
|
||||
*(long*)(dst + 24) = *(long*)(src + 24);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
long* lpSrc = (long*)src;
|
||||
long* ldSrc = (long*)dst;
|
||||
while (count >= 64)
|
||||
{
|
||||
*(ldSrc + 0) = *(lpSrc + 0);
|
||||
*(ldSrc + 1) = *(lpSrc + 1);
|
||||
*(ldSrc + 2) = *(lpSrc + 2);
|
||||
*(ldSrc + 3) = *(lpSrc + 3);
|
||||
*(ldSrc + 4) = *(lpSrc + 4);
|
||||
*(ldSrc + 5) = *(lpSrc + 5);
|
||||
*(ldSrc + 6) = *(lpSrc + 6);
|
||||
*(ldSrc + 7) = *(lpSrc + 7);
|
||||
if (count == 64)
|
||||
return;
|
||||
count -= 64;
|
||||
lpSrc += 8;
|
||||
ldSrc += 8;
|
||||
}
|
||||
if (count > 32)
|
||||
{
|
||||
*(ldSrc + 0) = *(lpSrc + 0);
|
||||
*(ldSrc + 1) = *(lpSrc + 1);
|
||||
*(ldSrc + 2) = *(lpSrc + 2);
|
||||
*(ldSrc + 3) = *(lpSrc + 3);
|
||||
count -= 32;
|
||||
lpSrc += 4;
|
||||
ldSrc += 4;
|
||||
}
|
||||
|
||||
src = (byte*)lpSrc;
|
||||
dst = (byte*)ldSrc;
|
||||
goto SMALLTABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
@ -101,6 +101,9 @@
|
||||
/// <returns>The hash</returns>
|
||||
public static uint ComputeHash(Stream stream, int bufferSize = 4096, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 16);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 16);
|
||||
|
||||
@ -131,7 +134,7 @@
|
||||
Shift(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
xxBuffer.BlockCopy(buffer, l, buffer, 0, r);
|
||||
UnsafeBuffer.BlockCopy(buffer, l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
@ -154,8 +157,11 @@
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static async Task<uint> ComputeHashAsync(Stream stream, int bufferSize = 4096, uint seed = 0)
|
||||
public static async ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize = 4096, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 16);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 16);
|
||||
|
||||
@ -186,7 +192,7 @@
|
||||
Shift(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
xxBuffer.BlockCopy(buffer, l, buffer, 0, r);
|
||||
UnsafeBuffer.BlockCopy(buffer,l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
public static partial class xxHash32
|
||||
{
|
||||
private const uint p1 = 2654435761U;
|
||||
@ -8,7 +12,7 @@
|
||||
private const uint p4 = 668265263U;
|
||||
private const uint p5 = 374761393U;
|
||||
|
||||
/// <summary>d
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
@ -17,10 +21,39 @@
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint ComputeHash(byte[] data, int length, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &data[0])
|
||||
{
|
||||
byte* ptr = pData;
|
||||
byte* end = pData + length;
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint ComputeHash(Span<byte> data, int length, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint UnsafeComputeHash(byte* ptr, int length, uint seed)
|
||||
{
|
||||
byte* end = ptr + length;
|
||||
uint h32;
|
||||
|
||||
if (length >= 16)
|
||||
@ -93,5 +126,4 @@
|
||||
return h32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
@ -52,7 +52,7 @@
|
||||
byte* end = pData + l;
|
||||
ulong h64;
|
||||
|
||||
if (length >= 16)
|
||||
if (length >= 32)
|
||||
{
|
||||
h64 = ((v1 << 1) | (v1 >> (64 - 1))) + // rotl 1
|
||||
((v2 << 7) | (v2 >> (64 - 7))) + // rotl 7
|
||||
@ -140,6 +140,9 @@
|
||||
/// <returns>The hash</returns>
|
||||
public static ulong ComputeHash(Stream stream, int bufferSize = 8192, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 32);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 32);
|
||||
|
||||
@ -170,7 +173,7 @@
|
||||
Shift(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
xxBuffer.BlockCopy(buffer, l, buffer, 0, r);
|
||||
UnsafeBuffer.BlockCopy(buffer, l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
@ -193,8 +196,11 @@
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static async Task<ulong> ComputeHashAsync(Stream stream, int bufferSize = 8192, ulong seed = 0)
|
||||
public static async ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize = 8192, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 32);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 32);
|
||||
|
||||
@ -225,7 +231,7 @@
|
||||
Shift(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
xxBuffer.BlockCopy(buffer, l, buffer, 0, r);
|
||||
UnsafeBuffer.BlockCopy(buffer, l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
public static partial class xxHash64
|
||||
{
|
||||
private const ulong p1 = 11400714785074694791UL;
|
||||
@ -17,10 +21,39 @@
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(byte[] data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &data[0])
|
||||
{
|
||||
byte* ptr = pData;
|
||||
byte* end = pData + length;
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(Span<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong UnsafeComputeHash(byte* ptr, int length, ulong seed)
|
||||
{
|
||||
byte* end = ptr + length;
|
||||
ulong h64;
|
||||
|
||||
if (length >= 32)
|
||||
@ -131,5 +164,4 @@
|
||||
return h64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user