Compare commits
15 Commits
9ab0dd4290
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e1a2c00e6 | |||
| 9360dfe305 | |||
| b14ddd8a23 | |||
| dc1326ffec | |||
| 895d53d362 | |||
| ea7471d09e | |||
| bcaa7a9411 | |||
| 676d59bf80 | |||
| bec532f6d9 | |||
| b806cf6e18 | |||
| 90ad0a9f5a | |||
|
|
6b20e7f7b3 | ||
|
|
62d648b6c3 | ||
|
|
f97a238e61 | ||
|
|
91b72f21db |
25
.github/workflows/dotnet.yml
vendored
25
.github/workflows/dotnet.yml
vendored
@@ -1,25 +0,0 @@
|
|||||||
name: .NET
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v2
|
|
||||||
with:
|
|
||||||
dotnet-version: 6.0.x
|
|
||||||
- name: Restore dependencies
|
|
||||||
run: dotnet restore ./src
|
|
||||||
- name: Build
|
|
||||||
run: dotnet build ./src --no-restore
|
|
||||||
- name: Test
|
|
||||||
run: dotnet test ./src --no-build --verbosity normal
|
|
||||||
31
.github/workflows/release.yml
vendored
31
.github/workflows/release.yml
vendored
@@ -1,31 +0,0 @@
|
|||||||
name: Release to NuGet
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: Bump Version
|
|
||||||
default: v1.0.0
|
|
||||||
required: true
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v2
|
|
||||||
with:
|
|
||||||
dotnet-version: 6.0.x
|
|
||||||
- name: Build
|
|
||||||
run: dotnet build ./src -c Release
|
|
||||||
- name: Test
|
|
||||||
run: dotnet test ./src -c Release --no-build
|
|
||||||
- name: Pack nugets
|
|
||||||
run: dotnet pack ./src/Standart.Hash.xxHash -c Release --no-build --output .
|
|
||||||
- name: Push to NuGet
|
|
||||||
run: dotnet nuget push "*.nupkg" --api-key ${{secrets.nuget_api_key}} --source https://api.nuget.org/v3/index.json
|
|
||||||
292
.gitignore
vendored
292
.gitignore
vendored
@@ -1,288 +1,24 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
|
||||||
## files generated by popular Visual Studio add-ons.
|
|
||||||
##
|
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
|
||||||
|
|
||||||
# User-specific files
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.userosscache
|
|
||||||
*.sln.docstates
|
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
|
||||||
*.userprefs
|
|
||||||
|
|
||||||
# Build results
|
# Build results
|
||||||
|
[Bb]in/
|
||||||
|
.bin/
|
||||||
[Dd]ebug/
|
[Dd]ebug/
|
||||||
[Dd]ebugPublic/
|
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
|
||||||
x86/
|
|
||||||
bld/
|
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
nuget/
|
||||||
|
*[-_]tmp/
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# IDE files
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
.vscode/
|
||||||
#wwwroot/
|
.vshistory/
|
||||||
|
|
||||||
# MSTest test Results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
[Bb]uild[Ll]og.*
|
|
||||||
|
|
||||||
# NUNIT
|
|
||||||
*.VisualState.xml
|
|
||||||
TestResult.xml
|
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
# .NET Core
|
|
||||||
project.lock.json
|
|
||||||
project.fragment.lock.json
|
|
||||||
artifacts/
|
|
||||||
**/Properties/launchSettings.json
|
|
||||||
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*_i.h
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
|
||||||
*.log
|
|
||||||
*.vspscc
|
|
||||||
*.vssscc
|
|
||||||
.builds
|
|
||||||
*.pidb
|
|
||||||
*.svclog
|
|
||||||
*.scc
|
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opendb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
*.VC.db
|
|
||||||
*.VC.VC.opendb
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.vspx
|
|
||||||
*.sap
|
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
|
||||||
*.DotSettings.user
|
|
||||||
|
|
||||||
# JustCode is a .NET coding add-in
|
|
||||||
.JustCode
|
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
|
||||||
|
|
||||||
# Visual Studio code coverage results
|
|
||||||
*.coverage
|
|
||||||
*.coveragexml
|
|
||||||
|
|
||||||
# NCrunch
|
|
||||||
_NCrunch_*
|
|
||||||
.*crunch*.local.xml
|
|
||||||
nCrunchTemp_*
|
|
||||||
|
|
||||||
# MightyMoose
|
|
||||||
*.mm.*
|
|
||||||
AutoTest.Net/
|
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
|
||||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
|
||||||
# in these scripts will be unencrypted
|
|
||||||
PublishScripts/
|
|
||||||
|
|
||||||
# NuGet Packages
|
|
||||||
*.nupkg
|
|
||||||
# The packages folder can be ignored because of Package Restore
|
|
||||||
**/packages/*
|
|
||||||
# except build/, which is used as an MSBuild target.
|
|
||||||
!**/packages/build/
|
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
|
||||||
#!**/packages/repositories.config
|
|
||||||
# NuGet v3's project.json files produces more ignorable files
|
|
||||||
*.nuget.props
|
|
||||||
*.nuget.targets
|
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
|
||||||
ecf/
|
|
||||||
rcf/
|
|
||||||
|
|
||||||
# Windows Store app package directories and files
|
|
||||||
AppPackages/
|
|
||||||
BundleArtifacts/
|
|
||||||
Package.StoreAssociation.xml
|
|
||||||
_pkginfo.txt
|
|
||||||
|
|
||||||
# Visual Studio cache files
|
|
||||||
# files ending in .cache can be ignored
|
|
||||||
*.[Cc]ache
|
|
||||||
# but keep track of directories ending in .cache
|
|
||||||
!*.[Cc]ache/
|
|
||||||
|
|
||||||
# Others
|
|
||||||
ClientBin/
|
|
||||||
~$*
|
|
||||||
*~
|
|
||||||
*.dbmdl
|
|
||||||
*.dbproj.schemaview
|
|
||||||
*.jfm
|
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
|
||||||
orleans.codegen.cs
|
|
||||||
|
|
||||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
|
||||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
|
||||||
#bower_components/
|
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
|
||||||
# because we have git ;-)
|
|
||||||
_UpgradeReport_Files/
|
|
||||||
Backup*/
|
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
*.ndf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
|
||||||
*.GhostDoc.xml
|
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
|
||||||
.ntvs_analysis.dat
|
|
||||||
node_modules/
|
|
||||||
|
|
||||||
# Typescript v1 declaration files
|
|
||||||
typings/
|
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
|
||||||
*.plg
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
|
||||||
*.opt
|
|
||||||
|
|
||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
|
||||||
*.vbw
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
|
||||||
**/*.Server/GeneratedArtifacts
|
|
||||||
**/*.Server/ModelManifest.xml
|
|
||||||
_Pvt_Extensions
|
|
||||||
|
|
||||||
# Paket dependency manager
|
|
||||||
.paket/paket.exe
|
|
||||||
paket-files/
|
|
||||||
|
|
||||||
# FAKE - F# Make
|
|
||||||
.fake/
|
|
||||||
|
|
||||||
# JetBrains Rider
|
|
||||||
.idea/
|
.idea/
|
||||||
*.sln.iml
|
.editorconfig
|
||||||
|
*.user
|
||||||
|
|
||||||
# CodeRush
|
#backups
|
||||||
.cr/
|
.old*/
|
||||||
|
*[-_]old/
|
||||||
# Python Tools for Visual Studio (PTVS)
|
|
||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
# Cake - Uncomment if you are using it
|
|
||||||
# tools/**
|
|
||||||
# !tools/packages.config
|
|
||||||
|
|
||||||
# Telerik's JustMock configuration file
|
|
||||||
*.jmconfig
|
|
||||||
|
|
||||||
# BizTalk build output
|
|
||||||
*.btp.cs
|
|
||||||
*.btm.cs
|
|
||||||
*.odx.cs
|
|
||||||
*.xsd.cs
|
|
||||||
|
|||||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,16 +0,0 @@
|
|||||||
# 2022-06-13
|
|
||||||
- Added xxHash3
|
|
||||||
# 2022-06-05
|
|
||||||
- Added SIMD support for xxHash128
|
|
||||||
- Inlined all method calls for xxHash128
|
|
||||||
# 2022-06-03
|
|
||||||
- Added xxHash128
|
|
||||||
- Migrated to net6
|
|
||||||
# 2019-02-16
|
|
||||||
- Migrated to net core v.3.1
|
|
||||||
- Added bit operation utils
|
|
||||||
# 2019-12-15
|
|
||||||
- Added support for ArraySegment (thanks ksmith3036)
|
|
||||||
# 2018-03-11
|
|
||||||
- Added API for ReadOnlySpan
|
|
||||||
- Added support for the async calls with cancelation tokens
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFrameworks>net48;net6.0;net8.0</TargetFrameworks>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<BenchmarkDotNet>0.13.1</BenchmarkDotNet>
|
||||||
|
<MicrosoftSdk>17.2.0</MicrosoftSdk>
|
||||||
|
<xUnit>2.4.1</xUnit>
|
||||||
|
<xUnitRunner>2.4.5</xUnitRunner>
|
||||||
|
<xUnitTool>2.3.1</xUnitTool>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNet)" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DTLib.XXHash\DTLib.XXHash.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Standart.Hash.xxHash.Perf
|
namespace DTLib.XXHash.PerformanceTest
|
||||||
{
|
{
|
||||||
using BenchmarkDotNet.Running;
|
using BenchmarkDotNet.Running;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Standart.Hash.xxHash.Perf
|
namespace DTLib.XXHash.PerformanceTest
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Standart.Hash.xxHash.Perf
|
namespace DTLib.XXHash.PerformanceTest
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
{
|
{
|
||||||
return xxHash32.ComputeHash(data, data.Length);
|
return xxHash32.ComputeHash(data, data.Length);
|
||||||
}
|
}
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public uint Hash32_Span()
|
public uint Hash32_Span()
|
||||||
{
|
{
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
ReadOnlySpan<byte> span = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> span = new ReadOnlySpan<byte>(data);
|
||||||
return xxHash32.ComputeHash(span, span.Length);
|
return xxHash32.ComputeHash(span, span.Length);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public uint Hash32_Stream()
|
public uint Hash32_Stream()
|
||||||
{
|
{
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
{
|
{
|
||||||
return xxHash64.ComputeHash(data, data.Length);
|
return xxHash64.ComputeHash(data, data.Length);
|
||||||
}
|
}
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public ulong Hash64_Span()
|
public ulong Hash64_Span()
|
||||||
{
|
{
|
||||||
@@ -84,6 +84,7 @@
|
|||||||
ReadOnlySpan<byte> span = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> span = new ReadOnlySpan<byte>(data);
|
||||||
return xxHash64.ComputeHash(span, span.Length);
|
return xxHash64.ComputeHash(span, span.Length);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public ulong Hash64_Stream()
|
public ulong Hash64_Stream()
|
||||||
24
DTLib.XXHash.Tests/DTLib.XXHash.Tests.csproj
Normal file
24
DTLib.XXHash.Tests/DTLib.XXHash.Tests.csproj
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<TargetFrameworks>net48;net6.0;net8.0</TargetFrameworks>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<BenchmarkDotNet>0.13.1</BenchmarkDotNet>
|
||||||
|
<MicrosoftSdk>17.2.0</MicrosoftSdk>
|
||||||
|
<xUnit>2.4.1</xUnit>
|
||||||
|
<xUnitRunner>2.4.5</xUnitRunner>
|
||||||
|
<xUnitTool>2.3.1</xUnitTool>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftSdk)" />
|
||||||
|
<PackageReference Include="xunit" Version="$(xUnit)" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="$(xUnitRunner)" />
|
||||||
|
<DotNetCliToolReference Include="dotnet-xunit" Version="$(xUnitTool)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DTLib.XXHash\DTLib.XXHash.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Standart.Hash.xxHash.Test
|
namespace DTLib.XXHash.Tests
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Should_convert_to_bytes()
|
public void Should_convert_to_bytes()
|
||||||
{
|
{
|
||||||
@@ -80,5 +80,6 @@
|
|||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(guid1, guid2);
|
Assert.Equal(guid1, guid2);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
116
DTLib.XXHash.Tests/xxHash128Test.cs
Normal file
116
DTLib.XXHash.Tests/xxHash128Test.cs
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace DTLib.XXHash.Tests
|
||||||
|
{
|
||||||
|
public class xxHash128Test
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Compute_hash128_for_bytes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var bytes = new byte[]
|
||||||
|
{
|
||||||
|
0xd2, 0x94, 0x29, 0xc9, 0x4c, 0xc5, 0x0f, 0xbb,
|
||||||
|
0xaa, 0xf4, 0x7c, 0xd5, 0x69, 0x5a, 0xa9, 0xbd,
|
||||||
|
0xaf, 0xd8, 0x3f, 0xfb, 0xca, 0x6a, 0xd4, 0x2c,
|
||||||
|
0x6c, 0x69, 0x7a, 0x5b, 0x0d, 0xe8, 0xd2, 0xb1,
|
||||||
|
0x41, 0xb3, 0x1b, 0x23, 0xdb, 0x8c, 0x25, 0xb4,
|
||||||
|
0x6c, 0xfb
|
||||||
|
};
|
||||||
|
|
||||||
|
ulong expectedH = 3466251221427321594;
|
||||||
|
ulong expectedL = 2862260537881727713;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var hash = xxHash128.ComputeHash(bytes, bytes.Length);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedH, hash.high64);
|
||||||
|
Assert.Equal(expectedL, hash.low64);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compute_hash128_for_span()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var bytes = new byte[]
|
||||||
|
{
|
||||||
|
0xd2, 0x94, 0x29, 0xc9, 0x4c, 0xc5, 0x0f, 0xbb,
|
||||||
|
0xaa, 0xf4, 0x7c, 0xd5, 0x69, 0x5a, 0xa9, 0xbd,
|
||||||
|
0xaf, 0xd8, 0x3f, 0xfb, 0xca, 0x6a, 0xd4, 0x2c,
|
||||||
|
0x6c, 0x69, 0x7a, 0x5b, 0x0d, 0xe8, 0xd2, 0xb1,
|
||||||
|
0x41, 0xb3, 0x1b, 0x23, 0xdb, 0x8c, 0x25, 0xb4,
|
||||||
|
0x6c, 0xfb
|
||||||
|
};
|
||||||
|
var span = bytes.AsSpan();
|
||||||
|
|
||||||
|
ulong expectedH = 3466251221427321594;
|
||||||
|
ulong expectedL = 2862260537881727713;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var hash = xxHash128.ComputeHash(span, span.Length);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedH, hash.high64);
|
||||||
|
Assert.Equal(expectedL, hash.low64);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compute_hash128_for_string()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var str = "veni vidi vici";
|
||||||
|
var bytes = Encoding.Unicode.GetBytes(str);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var hash1 = xxHash128.ComputeHash(str);
|
||||||
|
var hash2 = xxHash128.ComputeHash(bytes, bytes.Length);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(hash1.high64, hash2.high64);
|
||||||
|
Assert.Equal(hash1.low64, hash2.low64);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Compute_hash128_bytes_for_bytes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var bytes = new byte[]
|
||||||
|
{
|
||||||
|
0xd2, 0x94, 0x29, 0xc9, 0x4c, 0xc5, 0x0f, 0xbb,
|
||||||
|
0xaa, 0xf4, 0x7c, 0xd5, 0x69, 0x5a, 0xa9, 0xbd,
|
||||||
|
0xaf, 0xd8, 0x3f, 0xfb, 0xca, 0x6a, 0xd4, 0x2c,
|
||||||
|
0x6c, 0x69, 0x7a, 0x5b, 0x0d, 0xe8, 0xd2, 0xb1,
|
||||||
|
0x41, 0xb3, 0x1b, 0x23, 0xdb, 0x8c, 0x25, 0xb4,
|
||||||
|
0x6c, 0xfb
|
||||||
|
};
|
||||||
|
|
||||||
|
// ulong expectedH = 3466251221427321594;
|
||||||
|
// ulong expectedL = 2862260537881727713;
|
||||||
|
|
||||||
|
// (hBits * 18446744073709551616) + lBits
|
||||||
|
// (3466251221427321594 * 18446744073709551616) + 2862260537881727713
|
||||||
|
|
||||||
|
// dec: 63941049176852939372872402763456123617
|
||||||
|
// hex: 301A991EF3707AFA27B8CACB570F12E1
|
||||||
|
var expected = new byte[]
|
||||||
|
{
|
||||||
|
0xe1, 0x12, 0x0F, 0x57, 0xcb, 0xca, 0xb8, 0x27,
|
||||||
|
0xfa, 0x7a, 0x70, 0xf3, 0x1e, 0x99, 0x1a, 0x30
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var hash = xxHash128.ComputeHashBytes(bytes, bytes.Length);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
Assert.Equal(expected[i], hash[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash.Test
|
namespace DTLib.XXHash.Tests
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -10,23 +10,29 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
|
|
||||||
public class xxHash32Test
|
public class xxHash32Test
|
||||||
{
|
{
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Compute_hash32_for_the_length_1()
|
public void Compute_hash32_for_the_length_1()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
byte[] data = {0xde};
|
byte[] data = {0xde};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
// Act
|
// Act
|
||||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||||
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (uint) 0x2330eac0);
|
Assert.Equal(hash1, (uint) 0x2330eac0);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (uint) 0x2330eac0);
|
Assert.Equal(hash2, (uint) 0x2330eac0);
|
||||||
Assert.Equal(hash3, (uint) 0x2330eac0);
|
Assert.Equal(hash3, (uint) 0x2330eac0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -34,18 +40,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
byte[] data = {0xde, 0x55, 0x47, 0x7f, 0x14};
|
byte[] data = {0xde, 0x55, 0x47, 0x7f, 0x14};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||||
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (uint) 0x112348ba);
|
Assert.Equal(hash1, (uint) 0x112348ba);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (uint) 0x112348ba);
|
Assert.Equal(hash2, (uint) 0x112348ba);
|
||||||
Assert.Equal(hash3, (uint) 0x112348ba);
|
Assert.Equal(hash3, (uint) 0x112348ba);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -57,18 +69,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
0xde, 0x55, 0x47, 0x7f, 0x14, 0x8f, 0xf1, 0x48,
|
0xde, 0x55, 0x47, 0x7f, 0x14, 0x8f, 0xf1, 0x48,
|
||||||
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb
|
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb
|
||||||
};
|
};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||||
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (uint) 0xcdf89609);
|
Assert.Equal(hash1, (uint) 0xcdf89609);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (uint) 0xcdf89609);
|
Assert.Equal(hash2, (uint) 0xcdf89609);
|
||||||
Assert.Equal(hash3, (uint) 0xcdf89609);
|
Assert.Equal(hash3, (uint) 0xcdf89609);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -81,18 +99,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb,
|
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb,
|
||||||
0x0e
|
0x0e
|
||||||
};
|
};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||||
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (uint) 0xbca8f924);
|
Assert.Equal(hash1, (uint) 0xbca8f924);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (uint) 0xbca8f924);
|
Assert.Equal(hash2, (uint) 0xbca8f924);
|
||||||
Assert.Equal(hash3, (uint) 0xbca8f924);
|
Assert.Equal(hash3, (uint) 0xbca8f924);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -105,18 +129,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb,
|
0x22, 0x3a, 0x40, 0x96, 0x56, 0xc5, 0xdc, 0xbb,
|
||||||
0x0e, 0x59, 0x4d, 0x42, 0xc5
|
0x0e, 0x59, 0x4d, 0x42, 0xc5
|
||||||
};
|
};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||||
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (uint) 0xf4518e14);
|
Assert.Equal(hash1, (uint) 0xf4518e14);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (uint) 0xf4518e14);
|
Assert.Equal(hash2, (uint) 0xf4518e14);
|
||||||
Assert.Equal(hash3, (uint) 0xf4518e14);
|
Assert.Equal(hash3, (uint) 0xf4518e14);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -130,18 +160,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
0x0e, 0x59, 0x4d, 0x42, 0xc5, 0x07, 0x21, 0x08,
|
0x0e, 0x59, 0x4d, 0x42, 0xc5, 0x07, 0x21, 0x08,
|
||||||
0x1c, 0x2c, 0xc9, 0x38, 0x7d, 0x43, 0x83, 0x11,
|
0x1c, 0x2c, 0xc9, 0x38, 0x7d, 0x43, 0x83, 0x11,
|
||||||
};
|
};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
uint hash1 = xxHash32.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
uint hash2 = xxHash32.ComputeHash(span, span.Length);
|
||||||
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
uint hash3 = xxHash32.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (uint) 0xf8497daa);
|
Assert.Equal(hash1, (uint) 0xf8497daa);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (uint) 0xf8497daa);
|
Assert.Equal(hash2, (uint) 0xf8497daa);
|
||||||
Assert.Equal(hash3, (uint) 0xf8497daa);
|
Assert.Equal(hash3, (uint) 0xf8497daa);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
using System;
|
#if NET6_0_OR_GREATER
|
||||||
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash.Test
|
namespace DTLib.XXHash.Tests
|
||||||
{
|
{
|
||||||
public class xxHash3Test
|
public class xxHash3Test
|
||||||
{
|
{
|
||||||
@@ -68,3 +69,4 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash.Test
|
namespace DTLib.XXHash.Tests
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -15,18 +15,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
byte[] data = {0x60};
|
byte[] data = {0x60};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
||||||
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (ulong) 0xb3e7ca6ca5ba3445);
|
Assert.Equal(hash1, (ulong) 0xb3e7ca6ca5ba3445);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (ulong) 0xb3e7ca6ca5ba3445);
|
Assert.Equal(hash2, (ulong) 0xb3e7ca6ca5ba3445);
|
||||||
Assert.Equal(hash3, (ulong) 0xb3e7ca6ca5ba3445);
|
Assert.Equal(hash3, (ulong) 0xb3e7ca6ca5ba3445);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -34,18 +40,23 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
byte[] data = {0x60, 0x82, 0x40, 0x77, 0x8a};
|
byte[] data = {0x60, 0x82, 0x40, 0x77, 0x8a};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
// Act
|
// Act
|
||||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
||||||
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (ulong) 0x917b11ed024938fc);
|
Assert.Equal(hash1, (ulong) 0x917b11ed024938fc);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (ulong) 0x917b11ed024938fc);
|
Assert.Equal(hash2, (ulong) 0x917b11ed024938fc);
|
||||||
Assert.Equal(hash3, (ulong) 0x917b11ed024938fc);
|
Assert.Equal(hash3, (ulong) 0x917b11ed024938fc);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -57,18 +68,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
0x60, 0x82, 0x40, 0x77, 0x8a, 0x0e, 0xe4, 0xd5,
|
0x60, 0x82, 0x40, 0x77, 0x8a, 0x0e, 0xe4, 0xd5,
|
||||||
0x85, 0x1f, 0xa6, 0x86, 0x34,
|
0x85, 0x1f, 0xa6, 0x86, 0x34,
|
||||||
};
|
};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
||||||
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (ulong) 0x9d1cb0d181d58bee);
|
Assert.Equal(hash1, (ulong) 0x9d1cb0d181d58bee);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (ulong) 0x9d1cb0d181d58bee);
|
Assert.Equal(hash2, (ulong) 0x9d1cb0d181d58bee);
|
||||||
Assert.Equal(hash3, (ulong) 0x9d1cb0d181d58bee);
|
Assert.Equal(hash3, (ulong) 0x9d1cb0d181d58bee);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -82,18 +99,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
0x30, 0x5d, 0x84, 0x54, 0x15, 0xf9, 0xbd, 0x03,
|
0x30, 0x5d, 0x84, 0x54, 0x15, 0xf9, 0xbd, 0x03,
|
||||||
0x4b, 0x0f, 0x90, 0x4e, 0xf5, 0x57, 0x21, 0x21,
|
0x4b, 0x0f, 0x90, 0x4e, 0xf5, 0x57, 0x21, 0x21,
|
||||||
};
|
};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
||||||
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (ulong) 0x9233096b7804e12c);
|
Assert.Equal(hash1, (ulong) 0x9233096b7804e12c);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (ulong) 0x9233096b7804e12c);
|
Assert.Equal(hash2, (ulong) 0x9233096b7804e12c);
|
||||||
Assert.Equal(hash3, (ulong) 0x9233096b7804e12c);
|
Assert.Equal(hash3, (ulong) 0x9233096b7804e12c);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -111,18 +134,24 @@ namespace Standart.Hash.xxHash.Test
|
|||||||
0x27, 0x6d, 0xb3, 0x5c, 0xc7, 0xc0, 0xd0, 0xa0,
|
0x27, 0x6d, 0xb3, 0x5c, 0xc7, 0xc0, 0xd0, 0xa0,
|
||||||
0x7e, 0x28, 0xce, 0x46, 0x85, 0xb7, 0x2b, 0x16,
|
0x7e, 0x28, 0xce, 0x46, 0x85, 0xb7, 0x2b, 0x16,
|
||||||
};
|
};
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Span<byte> span = new Span<byte>(data);
|
Span<byte> span = new Span<byte>(data);
|
||||||
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
ReadOnlySpan<byte> rspan = new ReadOnlySpan<byte>(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
ulong hash1 = xxHash64.ComputeHash(data, data.Length);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
ulong hash2 = xxHash64.ComputeHash(span, span.Length);
|
||||||
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
ulong hash3 = xxHash64.ComputeHash(rspan, rspan.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(hash1, (ulong) 0x4c0a65b1ef9ea060);
|
Assert.Equal(hash1, (ulong) 0x4c0a65b1ef9ea060);
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
Assert.Equal(hash2, (ulong) 0x4c0a65b1ef9ea060);
|
Assert.Equal(hash2, (ulong) 0x4c0a65b1ef9ea060);
|
||||||
Assert.Equal(hash3, (ulong) 0x4c0a65b1ef9ea060);
|
Assert.Equal(hash3, (ulong) 0x4c0a65b1ef9ea060);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
28
DTLib.XXHash.sln
Normal file
28
DTLib.XXHash.sln
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTLib.XXHash", "DTLib.XXHash\DTLib.XXHash.csproj", "{7462108E-0FAE-49B1-9DDE-2996E09DFFD2}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTLib.XXHash.PerformanceTest", "DTLib.XXHash.PerformanceTest\DTLib.XXHash.PerformanceTest.csproj", "{E5EFBB2E-ABC7-4FE8-AA2E-B62B4D6B9B5D}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTLib.XXHash.Tests", "DTLib.XXHash.Tests\DTLib.XXHash.Tests.csproj", "{F3CC0F6B-D5BC-40FD-94EC-AF1A9534177F}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{7462108E-0FAE-49B1-9DDE-2996E09DFFD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7462108E-0FAE-49B1-9DDE-2996E09DFFD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7462108E-0FAE-49B1-9DDE-2996E09DFFD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7462108E-0FAE-49B1-9DDE-2996E09DFFD2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E5EFBB2E-ABC7-4FE8-AA2E-B62B4D6B9B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E5EFBB2E-ABC7-4FE8-AA2E-B62B4D6B9B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E5EFBB2E-ABC7-4FE8-AA2E-B62B4D6B9B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E5EFBB2E-ABC7-4FE8-AA2E-B62B4D6B9B5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F3CC0F6B-D5BC-40FD-94EC-AF1A9534177F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F3CC0F6B-D5BC-40FD-94EC-AF1A9534177F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F3CC0F6B-D5BC-40FD-94EC-AF1A9534177F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F3CC0F6B-D5BC-40FD-94EC-AF1A9534177F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
29
DTLib.XXHash/DTLib.XXHash.csproj
Normal file
29
DTLib.XXHash/DTLib.XXHash.csproj
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PackageId>DTLib.XXHash</PackageId>
|
||||||
|
<VersionPrefix>1.0.4</VersionPrefix>
|
||||||
|
<Authors>Oleksandr Melnyk</Authors>
|
||||||
|
<PackageTags>hash;xxHash;DTLib</PackageTags>
|
||||||
|
<Description>XXHash implementation in C# using intrinsics</Description>
|
||||||
|
<RepositoryType>GIT</RepositoryType>
|
||||||
|
<RepositoryUrl>https://timerix.ddns.net:3322/Timerix/DTLib.XXHash</RepositoryUrl>
|
||||||
|
<PackageProjectUrl>https://timerix.ddns.net:3322/Timerix/DTLib.XXHash</PackageProjectUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<InternalsVisibleTo Include="DTLib.XXHash.Tests" />
|
||||||
|
<InternalsVisibleTo Include="DTLib.XXHash.PerformanceTest" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup >
|
||||||
|
<PackageReference Include="System.Buffers" Version="4.6.1" />
|
||||||
|
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
|
||||||
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
|
#if NET6_0_OR_GREATER
|
||||||
using System;
|
using System;
|
||||||
|
#endif
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static class Utils
|
public static class Utils
|
||||||
{
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
public static Guid ToGuid(this uint128 value)
|
public static Guid ToGuid(this uint128 value)
|
||||||
{
|
{
|
||||||
var a = (Int32) (value.low64);
|
var a = (Int32) (value.low64);
|
||||||
@@ -32,6 +35,7 @@ namespace Standart.Hash.xxHash
|
|||||||
Unsafe.As<byte, ulong>(ref bytes[8]) = value.high64;
|
Unsafe.As<byte, ulong>(ref bytes[8]) = value.high64;
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static unsafe void BlockCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
internal static unsafe void BlockCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
||||||
191
DTLib.XXHash/__inline__xxHash32.cs
Normal file
191
DTLib.XXHash/__inline__xxHash32.cs
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
* This is the auto generated code.
|
||||||
|
* All function calls are inlined in XXH32
|
||||||
|
* Please don't try to analyze it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DTLib.XXHash
|
||||||
|
{
|
||||||
|
public partial class xxHash32
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe uint __inline__XXH32(byte* input, int len, uint seed)
|
||||||
|
{
|
||||||
|
uint h32;
|
||||||
|
|
||||||
|
if (len >= 16)
|
||||||
|
{
|
||||||
|
byte* end = input + len;
|
||||||
|
byte* limit = end - 15;
|
||||||
|
|
||||||
|
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||||
|
uint v2 = seed + XXH_PRIME32_2;
|
||||||
|
uint v3 = seed + 0;
|
||||||
|
uint v4 = seed - XXH_PRIME32_1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var reg1 = *((uint*)(input + 0));
|
||||||
|
var reg2 = *((uint*)(input + 4));
|
||||||
|
var reg3 = *((uint*)(input + 8));
|
||||||
|
var reg4 = *((uint*)(input + 12));
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v1 += reg1 * XXH_PRIME32_2;
|
||||||
|
v1 = (v1 << 13) | (v1 >> (32 - 13));
|
||||||
|
v1 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v2 += reg2 * XXH_PRIME32_2;
|
||||||
|
v2 = (v2 << 13) | (v2 >> (32 - 13));
|
||||||
|
v2 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v3 += reg3 * XXH_PRIME32_2;
|
||||||
|
v3 = (v3 << 13) | (v3 >> (32 - 13));
|
||||||
|
v3 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v4 += reg4 * XXH_PRIME32_2;
|
||||||
|
v4 = (v4 << 13) | (v4 >> (32 - 13));
|
||||||
|
v4 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
input += 16;
|
||||||
|
} while (input < limit);
|
||||||
|
|
||||||
|
h32 = ((v1 << 1) | (v1 >> (32 - 1))) +
|
||||||
|
((v2 << 7) | (v2 >> (32 - 7))) +
|
||||||
|
((v3 << 12) | (v3 >> (32 - 12))) +
|
||||||
|
((v4 << 18) | (v4 >> (32 - 18)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
h32 = seed + XXH_PRIME32_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
h32 += (uint) len;
|
||||||
|
|
||||||
|
// XXH32_finalize
|
||||||
|
len &= 15;
|
||||||
|
while (len >= 4)
|
||||||
|
{
|
||||||
|
h32 += *((uint*) input) * XXH_PRIME32_3;
|
||||||
|
input += 4;
|
||||||
|
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * XXH_PRIME32_4;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
h32 += *((byte*) input) * XXH_PRIME32_5;
|
||||||
|
++input;
|
||||||
|
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * XXH_PRIME32_1;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXH32_avalanche
|
||||||
|
h32 ^= h32 >> 15;
|
||||||
|
h32 *= XXH_PRIME32_2;
|
||||||
|
h32 ^= h32 >> 13;
|
||||||
|
h32 *= XXH_PRIME32_3;
|
||||||
|
h32 ^= h32 >> 16;
|
||||||
|
|
||||||
|
return h32;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe void __inline__XXH32_stream_process(byte[] input, int len, ref uint v1, ref uint v2, ref uint v3, ref uint v4)
|
||||||
|
{
|
||||||
|
fixed (byte* pData = &input[0])
|
||||||
|
{
|
||||||
|
byte* ptr = pData;
|
||||||
|
byte* limit = ptr + len;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var reg1 = *((uint*)(ptr + 0));
|
||||||
|
var reg2 = *((uint*)(ptr + 4));
|
||||||
|
var reg3 = *((uint*)(ptr + 8));
|
||||||
|
var reg4 = *((uint*)(ptr + 12));
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v1 += reg1 * XXH_PRIME32_2;
|
||||||
|
v1 = (v1 << 13) | (v1 >> (32 - 13));
|
||||||
|
v1 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v2 += reg2 * XXH_PRIME32_2;
|
||||||
|
v2 = (v2 << 13) | (v2 >> (32 - 13));
|
||||||
|
v2 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v3 += reg3 * XXH_PRIME32_2;
|
||||||
|
v3 = (v3 << 13) | (v3 >> (32 - 13));
|
||||||
|
v3 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
// XXH32_round
|
||||||
|
v4 += reg4 * XXH_PRIME32_2;
|
||||||
|
v4 = (v4 << 13) | (v4 >> (32 - 13));
|
||||||
|
v4 *= XXH_PRIME32_1;
|
||||||
|
|
||||||
|
ptr += 16;
|
||||||
|
|
||||||
|
} while (ptr < limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe uint __inline__XXH32_stream_finalize(byte[] input, int len, ref uint v1, ref uint v2, ref uint v3, ref uint v4, long length, uint seed)
|
||||||
|
{
|
||||||
|
fixed (byte* pData = &input[0])
|
||||||
|
{
|
||||||
|
byte* ptr = pData;
|
||||||
|
uint h32;
|
||||||
|
|
||||||
|
if (length >= 16)
|
||||||
|
{
|
||||||
|
h32 = ((v1 << 1) | (v1 >> (32 - 1))) +
|
||||||
|
((v2 << 7) | (v2 >> (32 - 7))) +
|
||||||
|
((v3 << 12) | (v3 >> (32 - 12))) +
|
||||||
|
((v4 << 18) | (v4 >> (32 - 18)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
h32 = seed + XXH_PRIME32_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
h32 += (uint)length;
|
||||||
|
|
||||||
|
// XXH32_finalize
|
||||||
|
len &= 15;
|
||||||
|
while (len >= 4)
|
||||||
|
{
|
||||||
|
h32 += *((uint*)ptr) * XXH_PRIME32_3;
|
||||||
|
ptr += 4;
|
||||||
|
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * XXH_PRIME32_4;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
h32 += *((byte*)ptr) * XXH_PRIME32_5;
|
||||||
|
ptr++;
|
||||||
|
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * XXH_PRIME32_1;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXH32_avalanche
|
||||||
|
h32 ^= h32 >> 15;
|
||||||
|
h32 *= XXH_PRIME32_2;
|
||||||
|
h32 ^= h32 >> 13;
|
||||||
|
h32 *= XXH_PRIME32_3;
|
||||||
|
h32 ^= h32 >> 16;
|
||||||
|
|
||||||
|
return h32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
252
DTLib.XXHash/__inline__xxHash64.cs
Normal file
252
DTLib.XXHash/__inline__xxHash64.cs
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
* This is the auto generated code.
|
||||||
|
* All function calls are inlined in XXH64
|
||||||
|
* Please don't try to analyze it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DTLib.XXHash
|
||||||
|
{
|
||||||
|
public partial class xxHash64
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe ulong __inline__XXH64(byte* input, int len, ulong seed)
|
||||||
|
{
|
||||||
|
ulong h64;
|
||||||
|
|
||||||
|
if (len >= 32)
|
||||||
|
{
|
||||||
|
byte* end = input + len;
|
||||||
|
byte* limit = end - 31;
|
||||||
|
|
||||||
|
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||||
|
ulong v2 = seed + XXH_PRIME64_2;
|
||||||
|
ulong v3 = seed + 0;
|
||||||
|
ulong v4 = seed - XXH_PRIME64_1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var reg1 = *((ulong*)(input + 0));
|
||||||
|
var reg2 = *((ulong*)(input + 8));
|
||||||
|
var reg3 = *((ulong*)(input + 16));
|
||||||
|
var reg4 = *((ulong*)(input + 24));
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v1 += reg1 * XXH_PRIME64_2;
|
||||||
|
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||||
|
v1 *= XXH_PRIME64_1;
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v2 += reg2 * XXH_PRIME64_2;
|
||||||
|
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||||
|
v2 *= XXH_PRIME64_1;
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v3 += reg3 * XXH_PRIME64_2;
|
||||||
|
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||||
|
v3 *= XXH_PRIME64_1;
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v4 += reg4 * XXH_PRIME64_2;
|
||||||
|
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||||
|
v4 *= XXH_PRIME64_1;
|
||||||
|
input += 32;
|
||||||
|
} while (input < limit);
|
||||||
|
|
||||||
|
h64 = ((v1 << 1) | (v1 >> (64 - 1))) +
|
||||||
|
((v2 << 7) | (v2 >> (64 - 7))) +
|
||||||
|
((v3 << 12) | (v3 >> (64 - 12))) +
|
||||||
|
((v4 << 18) | (v4 >> (64 - 18)));
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v1 *= XXH_PRIME64_2;
|
||||||
|
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||||
|
v1 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v1;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v2 *= XXH_PRIME64_2;
|
||||||
|
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||||
|
v2 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v2;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v3 *= XXH_PRIME64_2;
|
||||||
|
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||||
|
v3 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v3;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v4 *= XXH_PRIME64_2;
|
||||||
|
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||||
|
v4 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v4;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
h64 = seed + XXH_PRIME64_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
h64 += (ulong) len;
|
||||||
|
|
||||||
|
// XXH64_finalize
|
||||||
|
len &= 31;
|
||||||
|
while (len >= 8) {
|
||||||
|
ulong k1 = XXH64_round(0, *(ulong*)input);
|
||||||
|
input += 8;
|
||||||
|
h64 ^= k1;
|
||||||
|
h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
len -= 8;
|
||||||
|
}
|
||||||
|
if (len >= 4) {
|
||||||
|
h64 ^= *(uint*)input * XXH_PRIME64_1;
|
||||||
|
input += 4;
|
||||||
|
h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
while (len > 0) {
|
||||||
|
h64 ^= (*input++) * XXH_PRIME64_5;
|
||||||
|
h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXH64_avalanche
|
||||||
|
h64 ^= h64 >> 33;
|
||||||
|
h64 *= XXH_PRIME64_2;
|
||||||
|
h64 ^= h64 >> 29;
|
||||||
|
h64 *= XXH_PRIME64_3;
|
||||||
|
h64 ^= h64 >> 32;
|
||||||
|
|
||||||
|
return h64;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe void __inline__XXH64_stream_process(byte[] input, int len, ref ulong v1, ref ulong v2, ref ulong v3,
|
||||||
|
ref ulong v4)
|
||||||
|
{
|
||||||
|
fixed (byte* pData = &input[0])
|
||||||
|
{
|
||||||
|
byte* ptr = pData;
|
||||||
|
byte* limit = ptr + len;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var reg1 = *((ulong*)(ptr + 0));
|
||||||
|
var reg2 = *((ulong*)(ptr + 8));
|
||||||
|
var reg3 = *((ulong*)(ptr + 16));
|
||||||
|
var reg4 = *((ulong*)(ptr + 24));
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v1 += reg1 * XXH_PRIME64_2;
|
||||||
|
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||||
|
v1 *= XXH_PRIME64_1;
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v2 += reg2 * XXH_PRIME64_2;
|
||||||
|
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||||
|
v2 *= XXH_PRIME64_1;
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v3 += reg3 * XXH_PRIME64_2;
|
||||||
|
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||||
|
v3 *= XXH_PRIME64_1;
|
||||||
|
|
||||||
|
// XXH64_round
|
||||||
|
v4 += reg4 * XXH_PRIME64_2;
|
||||||
|
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||||
|
v4 *= XXH_PRIME64_1;
|
||||||
|
ptr += 32;
|
||||||
|
} while (ptr < limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe ulong __inline__XXH64_stream_finalize(byte[] input, int len, ref ulong v1, ref ulong v2, ref ulong v3,
|
||||||
|
ref ulong v4, long length, ulong seed)
|
||||||
|
{
|
||||||
|
fixed (byte* pData = &input[0])
|
||||||
|
{
|
||||||
|
byte* ptr = pData;
|
||||||
|
byte* end = pData + len;
|
||||||
|
ulong h64;
|
||||||
|
|
||||||
|
if (length >= 32)
|
||||||
|
{
|
||||||
|
h64 = ((v1 << 1) | (v1 >> (64 - 1))) +
|
||||||
|
((v2 << 7) | (v2 >> (64 - 7))) +
|
||||||
|
((v3 << 12) | (v3 >> (64 - 12))) +
|
||||||
|
((v4 << 18) | (v4 >> (64 - 18)));
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v1 *= XXH_PRIME64_2;
|
||||||
|
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||||
|
v1 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v1;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v2 *= XXH_PRIME64_2;
|
||||||
|
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||||
|
v2 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v2;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v3 *= XXH_PRIME64_2;
|
||||||
|
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||||
|
v3 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v3;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
|
||||||
|
// XXH64_mergeRound
|
||||||
|
v4 *= XXH_PRIME64_2;
|
||||||
|
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||||
|
v4 *= XXH_PRIME64_1;
|
||||||
|
h64 ^= v4;
|
||||||
|
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
h64 = seed + XXH_PRIME64_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
h64 += (ulong) length;
|
||||||
|
|
||||||
|
// XXH64_finalize
|
||||||
|
len &= 31;
|
||||||
|
while (len >= 8) {
|
||||||
|
ulong k1 = XXH64_round(0, *(ulong*)ptr);
|
||||||
|
ptr += 8;
|
||||||
|
h64 ^= k1;
|
||||||
|
h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||||
|
len -= 8;
|
||||||
|
}
|
||||||
|
if (len >= 4) {
|
||||||
|
h64 ^= *(uint*)ptr * XXH_PRIME64_1;
|
||||||
|
ptr += 4;
|
||||||
|
h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
while (len > 0) {
|
||||||
|
h64 ^= (*ptr++) * XXH_PRIME64_5;
|
||||||
|
h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXH64_avalanche
|
||||||
|
h64 ^= h64 >> 33;
|
||||||
|
h64 *= XXH_PRIME64_2;
|
||||||
|
h64 ^= h64 >> 29;
|
||||||
|
h64 *= XXH_PRIME64_3;
|
||||||
|
h64 ^= h64 >> 32;
|
||||||
|
|
||||||
|
return h64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
#if NET6_0_OR_GREATER
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash128
|
public static partial class xxHash128
|
||||||
{
|
{
|
||||||
@@ -20,12 +20,21 @@ namespace Standart.Hash.xxHash
|
|||||||
private const uint XXH_PRIME32_5 = 374761393U;
|
private const uint XXH_PRIME32_5 = 374761393U;
|
||||||
|
|
||||||
private const int XXH_STRIPE_LEN = 64;
|
private const int XXH_STRIPE_LEN = 64;
|
||||||
private const int XXH_ACC_NB = XXH_STRIPE_LEN / 8;
|
private const int XXH_ACC_NB = 8;
|
||||||
private const int XXH_SECRET_CONSUME_RATE = 8;
|
private const int XXH_SECRET_CONSUME_RATE = 8;
|
||||||
private const int XXH_SECRET_MERGEACCS_START = 11;
|
private const int XXH_SECRET_MERGEACCS_START = 11;
|
||||||
private const int XXH_SECRET_DEFAULT_SIZE = 192;
|
private const int XXH_SECRET_DEFAULT_SIZE = 192;
|
||||||
private const int XXH_SECRET_LASTACC_START = 7;
|
private const int XXH_SECRET_LASTACC_START = 7;
|
||||||
|
|
||||||
|
private const byte MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
||||||
|
private const byte MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
||||||
|
|
||||||
|
[FixedAddressValueType]
|
||||||
|
private static readonly Vector256<uint> M256i_XXH_PRIME32_1 = Vector256.Create(XXH_PRIME32_1);
|
||||||
|
[FixedAddressValueType]
|
||||||
|
private static readonly Vector128<uint> M128i_XXH_PRIME32_1 = Vector128.Create(XXH_PRIME32_1);
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static uint XXH_rotl32(uint x, int r)
|
private static uint XXH_rotl32(uint x, int r)
|
||||||
{
|
{
|
||||||
@@ -129,3 +138,4 @@ namespace Standart.Hash.xxHash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
#if NET6_0_OR_GREATER
|
||||||
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash128
|
public static partial class xxHash128
|
||||||
{
|
{
|
||||||
private static byte[] XXH3_SECRET =
|
private static readonly byte[] XXH3_SECRET =
|
||||||
{
|
{
|
||||||
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
||||||
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
||||||
@@ -25,7 +24,7 @@ namespace Standart.Hash.xxHash
|
|||||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static ulong[] XXH3_INIT_ACC =
|
private static readonly ulong[] XXH3_INIT_ACC =
|
||||||
{
|
{
|
||||||
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3,
|
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3,
|
||||||
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1
|
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1
|
||||||
@@ -275,55 +274,43 @@ namespace Standart.Hash.xxHash
|
|||||||
if (seed == 0)
|
if (seed == 0)
|
||||||
return XXH3_hashLong_128b_internal(input, len, secret, secretSize);
|
return XXH3_hashLong_128b_internal(input, len, secret, secretSize);
|
||||||
|
|
||||||
int customSecretSize = XXH3_SECRET_DEFAULT_SIZE;
|
byte* customSecret = stackalloc byte[XXH3_SECRET_DEFAULT_SIZE];
|
||||||
byte* customSecret = stackalloc byte[customSecretSize];
|
|
||||||
|
|
||||||
fixed (byte* ptr = &XXH3_SECRET[0])
|
|
||||||
{
|
|
||||||
for (int i = 0; i < customSecretSize; i += 8)
|
|
||||||
{
|
|
||||||
customSecret[i] = ptr[i];
|
|
||||||
customSecret[i+1] = ptr[i+1];
|
|
||||||
customSecret[i+2] = ptr[i+2];
|
|
||||||
customSecret[i+3] = ptr[i+3];
|
|
||||||
customSecret[i+4] = ptr[i+4];
|
|
||||||
customSecret[i+5] = ptr[i+5];
|
|
||||||
customSecret[i+6] = ptr[i+6];
|
|
||||||
customSecret[i+7] = ptr[i+7];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XXH3_initCustomSecret(customSecret, seed);
|
XXH3_initCustomSecret(customSecret, seed);
|
||||||
|
|
||||||
return XXH3_hashLong_128b_internal(input, len, customSecret, customSecretSize);
|
return XXH3_hashLong_128b_internal(input, len, customSecret, XXH3_SECRET_DEFAULT_SIZE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe uint128 XXH3_hashLong_128b_internal(byte* input, int len, byte* secret, int secretSize)
|
private static unsafe uint128 XXH3_hashLong_128b_internal(byte* input, int len, byte* secret, int secretSize)
|
||||||
{
|
{
|
||||||
ulong* acc = stackalloc ulong[8];
|
fixed (ulong* src = &XXH3_INIT_ACC[0])
|
||||||
|
|
||||||
fixed (ulong* ptr = &XXH3_INIT_ACC[0])
|
|
||||||
{
|
{
|
||||||
acc[0] = ptr[0];
|
ulong* acc = stackalloc ulong[8]
|
||||||
acc[1] = ptr[1];
|
{
|
||||||
acc[2] = ptr[2];
|
*(src + 0),
|
||||||
acc[3] = ptr[3];
|
*(src + 1),
|
||||||
acc[4] = ptr[4];
|
*(src + 2),
|
||||||
acc[5] = ptr[5];
|
*(src + 3),
|
||||||
acc[6] = ptr[6];
|
*(src + 4),
|
||||||
acc[7] = ptr[7];
|
*(src + 5),
|
||||||
|
*(src + 6),
|
||||||
|
*(src + 7),
|
||||||
|
};
|
||||||
|
|
||||||
|
XXH3_hashLong_internal_loop(acc, input, len, secret, secretSize);
|
||||||
|
|
||||||
|
uint128 uint128;
|
||||||
|
uint128.low64 = XXH3_mergeAccs(acc,
|
||||||
|
secret + XXH_SECRET_MERGEACCS_START,
|
||||||
|
(ulong)len * XXH_PRIME64_1);
|
||||||
|
uint128.high64 = XXH3_mergeAccs(acc,
|
||||||
|
secret + secretSize - XXH3_ACC_SIZE - XXH_SECRET_MERGEACCS_START,
|
||||||
|
~((ulong)len * XXH_PRIME64_2));
|
||||||
|
|
||||||
|
return uint128;
|
||||||
}
|
}
|
||||||
XXH3_hashLong_internal_loop(acc, input, len, secret, secretSize);
|
|
||||||
|
|
||||||
uint128 uint128;
|
|
||||||
uint128.low64 = XXH3_mergeAccs(acc,
|
|
||||||
secret + XXH_SECRET_MERGEACCS_START,
|
|
||||||
(ulong)len * XXH_PRIME64_1);
|
|
||||||
uint128.high64 = XXH3_mergeAccs(acc,
|
|
||||||
secret + secretSize - XXH3_ACC_SIZE - XXH_SECRET_MERGEACCS_START,
|
|
||||||
~((ulong)len * XXH_PRIME64_2));
|
|
||||||
|
|
||||||
return uint128;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -390,51 +377,89 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_accumulate_512_avx2(ulong* acc, byte* input, byte* secret)
|
private static unsafe void XXH3_accumulate_512_avx2(ulong* acc, byte* input, byte* secret)
|
||||||
{
|
{
|
||||||
const int m256i_size = 32;
|
var acc_vec0 = Unsafe.Read<Vector256<ulong>>(acc + 0);
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector256<ulong>>(acc + 4);
|
||||||
const byte _MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m256i_size; i++)
|
var data_vec0 = Unsafe.Read<Vector256<ulong>>((ulong*)input + 0).AsUInt32();
|
||||||
{
|
var data_vec1 = Unsafe.Read<Vector256<ulong>>((ulong*)input + 4).AsUInt32();
|
||||||
int uint32_offset = i * 8;
|
|
||||||
int uint64_offset = i * 4;
|
|
||||||
|
|
||||||
var acc_vec = Avx2.LoadVector256(acc + uint64_offset);
|
var key_vec0 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 0).AsUInt32();
|
||||||
var data_vec = Avx2.LoadVector256((uint*)input + uint32_offset);
|
var key_vec1 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 4).AsUInt32();
|
||||||
var key_vec = Avx2.LoadVector256((uint*)secret + uint32_offset);
|
|
||||||
var data_key = Avx2.Xor(data_vec, key_vec);
|
var data_key0 = Avx2.Xor(data_vec0, key_vec0);
|
||||||
var data_key_lo = Avx2.Shuffle(data_key, _MM_SHUFFLE_0_3_0_1);
|
var data_key1 = Avx2.Xor(data_vec1, key_vec1);
|
||||||
var product = Avx2.Multiply(data_key, data_key_lo);
|
|
||||||
var data_swap = Avx2.Shuffle(data_vec, _MM_SHUFFLE_1_0_3_2).AsUInt64();
|
var data_key_lo0 = Avx2.Shuffle(data_key0, MM_SHUFFLE_0_3_0_1);
|
||||||
var sum = Avx2.Add(acc_vec, data_swap);
|
var data_key_lo1 = Avx2.Shuffle(data_key1, MM_SHUFFLE_0_3_0_1);
|
||||||
var result = Avx2.Add(product, sum);
|
|
||||||
Avx2.Store(acc + uint64_offset, result);
|
var product0 = Avx2.Multiply(data_key0, data_key_lo0);
|
||||||
}
|
var product1 = Avx2.Multiply(data_key1, data_key_lo1);
|
||||||
|
|
||||||
|
var data_swap0 = Avx2.Shuffle(data_vec0, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap1 = Avx2.Shuffle(data_vec1, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
|
||||||
|
var sum0 = Avx2.Add(acc_vec0, data_swap0);
|
||||||
|
var sum1 = Avx2.Add(acc_vec1, data_swap1);
|
||||||
|
|
||||||
|
var result0 = Avx2.Add(product0, sum0);
|
||||||
|
var result1 = Avx2.Add(product1, sum1);
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 4, result1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_accumulate_512_sse2(ulong* acc, byte* input, byte* secret)
|
private static unsafe void XXH3_accumulate_512_sse2(ulong* acc, byte* input, byte* secret)
|
||||||
{
|
{
|
||||||
const int m128i_size = 16;
|
var acc_vec0 = Unsafe.Read<Vector128<ulong>>(acc + 0);
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector128<ulong>>(acc + 2);
|
||||||
const byte _MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
var acc_vec2 = Unsafe.Read<Vector128<ulong>>(acc + 4);
|
||||||
|
var acc_vec3 = Unsafe.Read<Vector128<ulong>>(acc + 6);
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m128i_size; i++)
|
var data_vec0 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 0).AsUInt32();
|
||||||
{
|
var data_vec1 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 2).AsUInt32();
|
||||||
int uint32_offset = i * 4;
|
var data_vec2 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 4).AsUInt32();
|
||||||
int uint64_offset = i * 2;
|
var data_vec3 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 6).AsUInt32();
|
||||||
|
|
||||||
var acc_vec = Sse2.LoadVector128(acc + uint64_offset);
|
var key_vec0 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 0).AsUInt32();
|
||||||
var data_vec = Sse2.LoadVector128((uint*) input + uint32_offset);
|
var key_vec1 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 2).AsUInt32();
|
||||||
var key_vec = Sse2.LoadVector128((uint*) secret + uint32_offset);
|
var key_vec2 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 4).AsUInt32();
|
||||||
var data_key = Sse2.Xor(data_vec, key_vec);
|
var key_vec3 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 6).AsUInt32();
|
||||||
var data_key_lo = Sse2.Shuffle(data_key, _MM_SHUFFLE_0_3_0_1);
|
|
||||||
var product = Sse2.Multiply(data_key, data_key_lo);
|
var data_key0 = Sse2.Xor(data_vec0, key_vec0);
|
||||||
var data_swap = Sse2.Shuffle(data_vec, _MM_SHUFFLE_1_0_3_2).AsUInt64();
|
var data_key1 = Sse2.Xor(data_vec1, key_vec1);
|
||||||
var sum = Sse2.Add(acc_vec, data_swap);
|
var data_key2 = Sse2.Xor(data_vec2, key_vec2);
|
||||||
var result = Sse2.Add(product, sum);
|
var data_key3 = Sse2.Xor(data_vec3, key_vec3);
|
||||||
Sse2.Store(acc + uint64_offset, result);
|
|
||||||
}
|
var data_key_lo0 = Sse2.Shuffle(data_key0, MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_lo1 = Sse2.Shuffle(data_key1, MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_lo2 = Sse2.Shuffle(data_key2, MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_lo3 = Sse2.Shuffle(data_key3, MM_SHUFFLE_0_3_0_1);
|
||||||
|
|
||||||
|
var product0 = Sse2.Multiply(data_key0, data_key_lo0);
|
||||||
|
var product1 = Sse2.Multiply(data_key1, data_key_lo1);
|
||||||
|
var product2 = Sse2.Multiply(data_key2, data_key_lo2);
|
||||||
|
var product3 = Sse2.Multiply(data_key3, data_key_lo3);
|
||||||
|
|
||||||
|
var data_swap0 = Sse2.Shuffle(data_vec0, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap1 = Sse2.Shuffle(data_vec1, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap2 = Sse2.Shuffle(data_vec2, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap3 = Sse2.Shuffle(data_vec3, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
|
||||||
|
var sum0 = Sse2.Add(acc_vec0, data_swap0);
|
||||||
|
var sum1 = Sse2.Add(acc_vec1, data_swap1);
|
||||||
|
var sum2 = Sse2.Add(acc_vec2, data_swap2);
|
||||||
|
var sum3 = Sse2.Add(acc_vec3, data_swap3);
|
||||||
|
|
||||||
|
var result0 = Sse2.Add(product0, sum0);
|
||||||
|
var result1 = Sse2.Add(product1, sum1);
|
||||||
|
var result2 = Sse2.Add(product2, sum2);
|
||||||
|
var result3 = Sse2.Add(product3, sum3);
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 2, result1);
|
||||||
|
Unsafe.Write(acc + 4, result2);
|
||||||
|
Unsafe.Write(acc + 6, result3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -473,52 +498,89 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_scrambleAcc_avx2(ulong* acc, byte* secret)
|
private static unsafe void XXH3_scrambleAcc_avx2(ulong* acc, byte* secret)
|
||||||
{
|
{
|
||||||
const int m256i_size = 32;
|
var acc_vec0 = Unsafe.Read<Vector256<ulong>>(acc + 0);
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector256<ulong>>(acc + 4);
|
||||||
|
|
||||||
var prime32 = Vector256.Create(XXH_PRIME32_1);
|
var shifted0 = Avx2.ShiftRightLogical(acc_vec0, 47);
|
||||||
|
var shifted1 = Avx2.ShiftRightLogical(acc_vec1, 47);
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m256i_size; i++)
|
var data_vec0 = Avx2.Xor(acc_vec0, shifted0);
|
||||||
{
|
var data_vec1 = Avx2.Xor(acc_vec1, shifted1);
|
||||||
int uint64_offset = i * 4;
|
|
||||||
|
|
||||||
var acc_vec = Avx2.LoadVector256(acc + uint64_offset);
|
var key_vec0 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 0);
|
||||||
var shifted = Avx2.ShiftRightLogical(acc_vec, 47);
|
var key_vec1 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 4);
|
||||||
var data_vec = Avx2.Xor(acc_vec, shifted);
|
|
||||||
var key_vec = Avx2.LoadVector256((ulong*) secret + uint64_offset);
|
var data_key0 = Avx2.Xor(data_vec0, key_vec0).AsUInt32();
|
||||||
var data_key = Avx2.Xor(data_vec, key_vec).AsUInt32();
|
var data_key1 = Avx2.Xor(data_vec1, key_vec1).AsUInt32();
|
||||||
var data_key_hi = Avx2.Shuffle(data_key, _MM_SHUFFLE_0_3_0_1);
|
|
||||||
var prod_lo = Avx2.Multiply(data_key, prime32);
|
var data_key_hi0 = Avx2.Shuffle(data_key0, MM_SHUFFLE_0_3_0_1);
|
||||||
var prod_hi = Avx2.Multiply(data_key_hi, prime32);
|
var data_key_hi1 = Avx2.Shuffle(data_key1, MM_SHUFFLE_0_3_0_1);
|
||||||
var result = Avx2.Add(prod_lo, Avx2.ShiftLeftLogical(prod_hi, 32));
|
|
||||||
Avx2.Store(acc + uint64_offset, result);
|
var prod_lo0 = Avx2.Multiply(data_key0, M256i_XXH_PRIME32_1);
|
||||||
}
|
var prod_lo1 = Avx2.Multiply(data_key1, M256i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var prod_hi0 = Avx2.Multiply(data_key_hi0, M256i_XXH_PRIME32_1);
|
||||||
|
var prod_hi1 = Avx2.Multiply(data_key_hi1, M256i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var result0 = Avx2.Add(prod_lo0, Avx2.ShiftLeftLogical(prod_hi0, 32));
|
||||||
|
var result1 = Avx2.Add(prod_lo1, Avx2.ShiftLeftLogical(prod_hi1, 32));
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 4, result1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_scrambleAcc_sse2(ulong* acc, byte* secret)
|
private static unsafe void XXH3_scrambleAcc_sse2(ulong* acc, byte* secret)
|
||||||
{
|
{
|
||||||
const int m128i_size = 16;
|
var acc_vec0 = Unsafe.Read<Vector128<ulong>>(acc + 0).AsUInt32();
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector128<ulong>>(acc + 2).AsUInt32();
|
||||||
|
var acc_vec2 = Unsafe.Read<Vector128<ulong>>(acc + 4).AsUInt32();
|
||||||
|
var acc_vec3 = Unsafe.Read<Vector128<ulong>>(acc + 6).AsUInt32();
|
||||||
|
|
||||||
var prime32 = Vector128.Create(XXH_PRIME32_1);
|
var shifted0 = Sse2.ShiftRightLogical(acc_vec0, 47);
|
||||||
|
var shifted1 = Sse2.ShiftRightLogical(acc_vec1, 47);
|
||||||
|
var shifted2 = Sse2.ShiftRightLogical(acc_vec2, 47);
|
||||||
|
var shifted3 = Sse2.ShiftRightLogical(acc_vec3, 47);
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m128i_size; i++)
|
var data_vec0 = Sse2.Xor(acc_vec0, shifted0);
|
||||||
{
|
var data_vec1 = Sse2.Xor(acc_vec1, shifted1);
|
||||||
int uint32_offset = i * 4;
|
var data_vec2 = Sse2.Xor(acc_vec2, shifted2);
|
||||||
int uint64_offset = i * 2;
|
var data_vec3 = Sse2.Xor(acc_vec3, shifted3);
|
||||||
|
|
||||||
var acc_vec = Sse2.LoadVector128(acc + uint64_offset).AsUInt32();
|
var key_vec0 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 0).AsUInt32();
|
||||||
var shifted = Sse2.ShiftRightLogical(acc_vec, 47);
|
var key_vec1 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 2).AsUInt32();
|
||||||
var data_vec = Sse2.Xor(acc_vec, shifted);
|
var key_vec2 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 4).AsUInt32();
|
||||||
var key_vec = Sse2.LoadVector128((uint*) secret + uint32_offset);
|
var key_vec3 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 6).AsUInt32();
|
||||||
var data_key = Sse2.Xor(data_vec, key_vec);
|
|
||||||
var data_key_hi = Sse2.Shuffle(data_key.AsUInt32(), _MM_SHUFFLE_0_3_0_1);
|
var data_key0= Sse2.Xor(data_vec0, key_vec0);
|
||||||
var prod_lo = Sse2.Multiply(data_key, prime32);
|
var data_key1= Sse2.Xor(data_vec1, key_vec1);
|
||||||
var prod_hi = Sse2.Multiply(data_key_hi, prime32);
|
var data_key2= Sse2.Xor(data_vec2, key_vec2);
|
||||||
var result = Sse2.Add(prod_lo, Sse2.ShiftLeftLogical(prod_hi, 32));
|
var data_key3= Sse2.Xor(data_vec3, key_vec3);
|
||||||
Sse2.Store(acc + uint64_offset, result);
|
|
||||||
}
|
var data_key_hi0 = Sse2.Shuffle(data_key0.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_hi1 = Sse2.Shuffle(data_key1.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_hi2 = Sse2.Shuffle(data_key2.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_hi3 = Sse2.Shuffle(data_key3.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
|
||||||
|
var prod_lo0 = Sse2.Multiply(data_key0, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_lo1 = Sse2.Multiply(data_key1, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_lo2 = Sse2.Multiply(data_key2, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_lo3 = Sse2.Multiply(data_key3, M128i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var prod_hi0 = Sse2.Multiply(data_key_hi0, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_hi1 = Sse2.Multiply(data_key_hi1, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_hi2 = Sse2.Multiply(data_key_hi2, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_hi3 = Sse2.Multiply(data_key_hi3, M128i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var result0 = Sse2.Add(prod_lo0, Sse2.ShiftLeftLogical(prod_hi0, 32));
|
||||||
|
var result1 = Sse2.Add(prod_lo1, Sse2.ShiftLeftLogical(prod_hi1, 32));
|
||||||
|
var result2 = Sse2.Add(prod_lo2, Sse2.ShiftLeftLogical(prod_hi2, 32));
|
||||||
|
var result3 = Sse2.Add(prod_lo3, Sse2.ShiftLeftLogical(prod_hi3, 32));
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 2, result1);
|
||||||
|
Unsafe.Write(acc + 4, result2);
|
||||||
|
Unsafe.Write(acc + 6, result3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -558,20 +620,30 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_initCustomSecret_avx2(byte* customSecret, ulong seed64)
|
private static unsafe void XXH3_initCustomSecret_avx2(byte* customSecret, ulong seed64)
|
||||||
{
|
{
|
||||||
const int m256i_size = 32;
|
var seed = Vector256.Create(seed64, (0U - seed64), seed64, (0U - seed64));
|
||||||
|
|
||||||
var seed = Vector256.Create((ulong)seed64, (ulong)(0U - seed64), (ulong)seed64, (ulong)(0U - seed64));
|
|
||||||
|
|
||||||
fixed (byte* secret = &XXH3_SECRET[0])
|
fixed (byte* secret = &XXH3_SECRET[0])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < XXH_SECRET_DEFAULT_SIZE / m256i_size; i++)
|
var src0 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 0);
|
||||||
{
|
var src1 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 4);
|
||||||
int uint64_offset = i * 4;
|
var src2 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 8);
|
||||||
|
var src3 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 12);
|
||||||
|
var src4 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 16);
|
||||||
|
var src5 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 20);
|
||||||
|
|
||||||
var src32 = Avx2.LoadVector256(((ulong*)secret) + uint64_offset);
|
var dst0 = Avx2.Add(src0, seed);
|
||||||
var dst32 = Avx2.Add(src32, seed);
|
var dst1 = Avx2.Add(src1, seed);
|
||||||
Avx2.Store((ulong*) customSecret + uint64_offset, dst32);
|
var dst2 = Avx2.Add(src2, seed);
|
||||||
}
|
var dst3 = Avx2.Add(src3, seed);
|
||||||
|
var dst4 = Avx2.Add(src4, seed);
|
||||||
|
var dst5 = Avx2.Add(src5, seed);
|
||||||
|
|
||||||
|
Unsafe.Write((ulong*)customSecret + 0, dst0);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 4, dst1);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 8, dst2);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 12, dst3);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 16, dst4);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 20, dst5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,21 +651,48 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_initCustomSecret_sse2(byte* customSecret, ulong seed64)
|
private static unsafe void XXH3_initCustomSecret_sse2(byte* customSecret, ulong seed64)
|
||||||
{
|
{
|
||||||
const int m128i_size = 16;
|
|
||||||
|
|
||||||
var seed = Vector128.Create((long)seed64, (long)(0U - seed64));
|
var seed = Vector128.Create((long)seed64, (long)(0U - seed64));
|
||||||
|
|
||||||
fixed (byte* secret = &XXH3_SECRET[0])
|
fixed (byte* secret = &XXH3_SECRET[0])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < XXH_SECRET_DEFAULT_SIZE / m128i_size; i++)
|
var src0 = Unsafe.Read<Vector128<long>>((long*)secret + 0);
|
||||||
{
|
var src1 = Unsafe.Read<Vector128<long>>((long*)secret + 2);
|
||||||
int uint64_offset = i * 2;
|
var src2 = Unsafe.Read<Vector128<long>>((long*)secret + 4);
|
||||||
|
var src3 = Unsafe.Read<Vector128<long>>((long*)secret + 6);
|
||||||
|
var src4 = Unsafe.Read<Vector128<long>>((long*)secret + 8);
|
||||||
|
var src5 = Unsafe.Read<Vector128<long>>((long*)secret + 10);
|
||||||
|
var src6 = Unsafe.Read<Vector128<long>>((long*)secret + 12);
|
||||||
|
var src7 = Unsafe.Read<Vector128<long>>((long*)secret + 14);
|
||||||
|
var src8 = Unsafe.Read<Vector128<long>>((long*)secret + 16);
|
||||||
|
var src9 = Unsafe.Read<Vector128<long>>((long*)secret + 18);
|
||||||
|
var src10 = Unsafe.Read<Vector128<long>>((long*)secret + 20);
|
||||||
|
var src11 = Unsafe.Read<Vector128<long>>((long*)secret + 22);
|
||||||
|
|
||||||
var src16 = Sse2.LoadVector128(((long*) secret) + uint64_offset);
|
var dst0 = Sse2.Add(src0, seed);
|
||||||
var dst16 = Sse2.Add(src16, seed);
|
var dst1 = Sse2.Add(src1, seed);
|
||||||
Sse2.Store((long*) customSecret + uint64_offset, dst16);
|
var dst2 = Sse2.Add(src2, seed);
|
||||||
|
var dst3 = Sse2.Add(src3, seed);
|
||||||
|
var dst4 = Sse2.Add(src4, seed);
|
||||||
|
var dst5 = Sse2.Add(src5, seed);
|
||||||
|
var dst6 = Sse2.Add(src6, seed);
|
||||||
|
var dst7 = Sse2.Add(src7, seed);
|
||||||
|
var dst8 = Sse2.Add(src8, seed);
|
||||||
|
var dst9 = Sse2.Add(src9, seed);
|
||||||
|
var dst10 = Sse2.Add(src10, seed);
|
||||||
|
var dst11 = Sse2.Add(src11, seed);
|
||||||
|
|
||||||
}
|
Unsafe.Write((long*)customSecret + 0, dst0);
|
||||||
|
Unsafe.Write((long*)customSecret + 2, dst1);
|
||||||
|
Unsafe.Write((long*)customSecret + 4, dst2);
|
||||||
|
Unsafe.Write((long*)customSecret + 6, dst3);
|
||||||
|
Unsafe.Write((long*)customSecret + 8, dst4);
|
||||||
|
Unsafe.Write((long*)customSecret + 10, dst5);
|
||||||
|
Unsafe.Write((long*)customSecret + 12, dst6);
|
||||||
|
Unsafe.Write((long*)customSecret + 14, dst7);
|
||||||
|
Unsafe.Write((long*)customSecret + 16, dst8);
|
||||||
|
Unsafe.Write((long*)customSecret + 18, dst9);
|
||||||
|
Unsafe.Write((long*)customSecret + 20, dst10);
|
||||||
|
Unsafe.Write((long*)customSecret + 22, dst11);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,3 +714,4 @@ namespace Standart.Hash.xxHash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
#if NET6_0_OR_GREATER
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash128
|
public static partial class xxHash128
|
||||||
{
|
{
|
||||||
@@ -18,3 +17,4 @@ namespace Standart.Hash.xxHash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
#if NET6_0_OR_GREATER
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash128
|
public static partial class xxHash128
|
||||||
{
|
{
|
||||||
@@ -141,7 +140,6 @@ namespace Standart.Hash.xxHash
|
|||||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compute hash bytes for the string
|
/// Compute hash bytes for the string
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -166,10 +164,7 @@ namespace Standart.Hash.xxHash
|
|||||||
{
|
{
|
||||||
fixed (byte* secret = &XXH3_SECRET[0])
|
fixed (byte* secret = &XXH3_SECRET[0])
|
||||||
{
|
{
|
||||||
// Use inlined version
|
return XXH3_128bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
||||||
// return XXH3_128bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
|
||||||
|
|
||||||
return __inline__XXH3_128bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,3 +176,4 @@ namespace Standart.Hash.xxHash
|
|||||||
public ulong high64;
|
public ulong high64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
#pragma warning disable CS0414 // Field is assigned but its value is never used
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash3
|
public static partial class xxHash3
|
||||||
{
|
{
|
||||||
@@ -13,11 +14,11 @@ namespace Standart.Hash.xxHash
|
|||||||
private const ulong XXH_PRIME64_4 = 9650029242287828579UL;
|
private const ulong XXH_PRIME64_4 = 9650029242287828579UL;
|
||||||
private const ulong XXH_PRIME64_5 = 2870177450012600261UL;
|
private const ulong XXH_PRIME64_5 = 2870177450012600261UL;
|
||||||
|
|
||||||
private const uint XXH_PRIME32_1 = 2654435761U;
|
private static readonly uint XXH_PRIME32_1 = 2654435761U;
|
||||||
private const uint XXH_PRIME32_2 = 2246822519U;
|
private static readonly uint XXH_PRIME32_2 = 2246822519U;
|
||||||
private const uint XXH_PRIME32_3 = 3266489917U;
|
private static readonly uint XXH_PRIME32_3 = 3266489917U;
|
||||||
private const uint XXH_PRIME32_4 = 668265263U;
|
private static readonly uint XXH_PRIME32_4 = 668265263U;
|
||||||
private const uint XXH_PRIME32_5 = 374761393U;
|
private static readonly uint XXH_PRIME32_5 = 374761393U;
|
||||||
|
|
||||||
private const int XXH_STRIPE_LEN = 64;
|
private const int XXH_STRIPE_LEN = 64;
|
||||||
private const int XXH_ACC_NB = XXH_STRIPE_LEN / 8;
|
private const int XXH_ACC_NB = XXH_STRIPE_LEN / 8;
|
||||||
@@ -26,6 +27,14 @@ namespace Standart.Hash.xxHash
|
|||||||
private const int XXH_SECRET_MERGEACCS_START = 11;
|
private const int XXH_SECRET_MERGEACCS_START = 11;
|
||||||
private const int XXH_SECRET_LASTACC_START = 7;
|
private const int XXH_SECRET_LASTACC_START = 7;
|
||||||
|
|
||||||
|
private const byte MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
||||||
|
private const byte MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
||||||
|
|
||||||
|
[FixedAddressValueType]
|
||||||
|
private static readonly Vector256<uint> M256i_XXH_PRIME32_1 = Vector256.Create(XXH_PRIME32_1);
|
||||||
|
[FixedAddressValueType]
|
||||||
|
private static readonly Vector128<uint> M128i_XXH_PRIME32_1 = Vector128.Create(XXH_PRIME32_1);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe ulong XXH_readLE64(byte* ptr)
|
private static unsafe ulong XXH_readLE64(byte* ptr)
|
||||||
{
|
{
|
||||||
@@ -83,11 +92,10 @@ namespace Standart.Hash.xxHash
|
|||||||
{
|
{
|
||||||
*(ulong*) dst = v64;
|
*(ulong*) dst = v64;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static uint128 XXH_mult64to128(ulong lhs, ulong rhs)
|
private static uint128 XXH_mult64to128(ulong lhs, ulong rhs)
|
||||||
{
|
{
|
||||||
if (Bmi2.IsSupported)
|
if (Bmi2.X64.IsSupported)
|
||||||
return XXH_mult64to128_bmi2(lhs, rhs);
|
return XXH_mult64to128_bmi2(lhs, rhs);
|
||||||
|
|
||||||
return XXH_mult64to128_scalar(lhs, rhs);
|
return XXH_mult64to128_scalar(lhs, rhs);
|
||||||
@@ -123,3 +131,4 @@ namespace Standart.Hash.xxHash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash3
|
public static partial class xxHash3
|
||||||
{
|
{
|
||||||
private static byte[] XXH3_SECRET =
|
private static readonly byte[] XXH3_SECRET =
|
||||||
{
|
{
|
||||||
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
||||||
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
||||||
@@ -24,7 +23,7 @@ namespace Standart.Hash.xxHash
|
|||||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static ulong[] XXH3_INIT_ACC =
|
private static readonly ulong[] XXH3_INIT_ACC =
|
||||||
{
|
{
|
||||||
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3,
|
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3,
|
||||||
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1
|
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1
|
||||||
@@ -75,14 +74,12 @@ namespace Standart.Hash.xxHash
|
|||||||
+ XXH3_mul128_fold64(input_lo, input_hi);
|
+ XXH3_mul128_fold64(input_lo, input_hi);
|
||||||
return XXH3_avalanche(acc);
|
return XXH3_avalanche(acc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ulong XXH3_mul128_fold64(ulong lhs, ulong rhs)
|
private static ulong XXH3_mul128_fold64(ulong lhs, ulong rhs)
|
||||||
{
|
{
|
||||||
uint128 product = XXH_mult64to128(lhs, rhs);
|
uint128 product = XXH_mult64to128(lhs, rhs);
|
||||||
return product.low64 ^ product.high64;
|
return product.low64 ^ product.high64;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ulong XXH3_avalanche(ulong h64)
|
private static ulong XXH3_avalanche(ulong h64)
|
||||||
{
|
{
|
||||||
@@ -201,27 +198,11 @@ namespace Standart.Hash.xxHash
|
|||||||
if (seed == 0)
|
if (seed == 0)
|
||||||
return XXH3_hashLong_64b_internal(input, len, secret, secretSize);
|
return XXH3_hashLong_64b_internal(input, len, secret, secretSize);
|
||||||
|
|
||||||
int customSecretSize = XXH3_SECRET_DEFAULT_SIZE;
|
byte* customSecret = stackalloc byte[XXH3_SECRET_DEFAULT_SIZE];
|
||||||
byte* customSecret = stackalloc byte[customSecretSize];
|
|
||||||
|
|
||||||
fixed (byte* ptr = &XXH3_SECRET[0])
|
|
||||||
{
|
|
||||||
for (int i = 0; i < customSecretSize; i += 8)
|
|
||||||
{
|
|
||||||
customSecret[i] = ptr[i];
|
|
||||||
customSecret[i + 1] = ptr[i + 1];
|
|
||||||
customSecret[i + 2] = ptr[i + 2];
|
|
||||||
customSecret[i + 3] = ptr[i + 3];
|
|
||||||
customSecret[i + 4] = ptr[i + 4];
|
|
||||||
customSecret[i + 5] = ptr[i + 5];
|
|
||||||
customSecret[i + 6] = ptr[i + 6];
|
|
||||||
customSecret[i + 7] = ptr[i + 7];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XXH3_initCustomSecret(customSecret, seed);
|
XXH3_initCustomSecret(customSecret, seed);
|
||||||
|
|
||||||
return XXH3_hashLong_64b_internal(input, len, customSecret, customSecretSize);
|
return XXH3_hashLong_64b_internal(input, len, customSecret, XXH3_SECRET_DEFAULT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -238,40 +219,78 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_initCustomSecret_avx2(byte* customSecret, ulong seed64)
|
private static unsafe void XXH3_initCustomSecret_avx2(byte* customSecret, ulong seed64)
|
||||||
{
|
{
|
||||||
const int m256i_size = 32;
|
var seed = Vector256.Create(seed64, (0U - seed64), seed64, (0U - seed64));
|
||||||
|
|
||||||
var seed = Vector256.Create(seed64, 0U - seed64, seed64, 0U - seed64);
|
|
||||||
|
|
||||||
fixed (byte* secret = &XXH3_SECRET[0])
|
fixed (byte* secret = &XXH3_SECRET[0])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < XXH_SECRET_DEFAULT_SIZE / m256i_size; i++)
|
var src0 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 0);
|
||||||
{
|
var src1 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 4);
|
||||||
int uint64_offset = i * 4;
|
var src2 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 8);
|
||||||
|
var src3 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 12);
|
||||||
|
var src4 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 16);
|
||||||
|
var src5 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 20);
|
||||||
|
|
||||||
var src32 = Avx2.LoadVector256(((ulong*) secret) + uint64_offset);
|
var dst0 = Avx2.Add(src0, seed);
|
||||||
var dst32 = Avx2.Add(src32, seed);
|
var dst1 = Avx2.Add(src1, seed);
|
||||||
Avx2.Store((ulong*) customSecret + uint64_offset, dst32);
|
var dst2 = Avx2.Add(src2, seed);
|
||||||
}
|
var dst3 = Avx2.Add(src3, seed);
|
||||||
|
var dst4 = Avx2.Add(src4, seed);
|
||||||
|
var dst5 = Avx2.Add(src5, seed);
|
||||||
|
|
||||||
|
Unsafe.Write((ulong*)customSecret + 0, dst0);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 4, dst1);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 8, dst2);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 12, dst3);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 16, dst4);
|
||||||
|
Unsafe.Write((ulong*)customSecret + 20, dst5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_initCustomSecret_sse2(byte* customSecret, ulong seed64)
|
private static unsafe void XXH3_initCustomSecret_sse2(byte* customSecret, ulong seed64)
|
||||||
{
|
{
|
||||||
const int m128i_size = 16;
|
var seed = Vector128.Create((long)seed64, (long)(0U - seed64));
|
||||||
|
|
||||||
var seed = Vector128.Create((long) seed64, (long) (0U - seed64));
|
|
||||||
|
|
||||||
fixed (byte* secret = &XXH3_SECRET[0])
|
fixed (byte* secret = &XXH3_SECRET[0])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < XXH_SECRET_DEFAULT_SIZE / m128i_size; i++)
|
var src0 = Unsafe.Read<Vector128<long>>((long*)secret + 0);
|
||||||
{
|
var src1 = Unsafe.Read<Vector128<long>>((long*)secret + 2);
|
||||||
int uint64_offset = i * 2;
|
var src2 = Unsafe.Read<Vector128<long>>((long*)secret + 4);
|
||||||
|
var src3 = Unsafe.Read<Vector128<long>>((long*)secret + 6);
|
||||||
|
var src4 = Unsafe.Read<Vector128<long>>((long*)secret + 8);
|
||||||
|
var src5 = Unsafe.Read<Vector128<long>>((long*)secret + 10);
|
||||||
|
var src6 = Unsafe.Read<Vector128<long>>((long*)secret + 12);
|
||||||
|
var src7 = Unsafe.Read<Vector128<long>>((long*)secret + 14);
|
||||||
|
var src8 = Unsafe.Read<Vector128<long>>((long*)secret + 16);
|
||||||
|
var src9 = Unsafe.Read<Vector128<long>>((long*)secret + 18);
|
||||||
|
var src10 = Unsafe.Read<Vector128<long>>((long*)secret + 20);
|
||||||
|
var src11 = Unsafe.Read<Vector128<long>>((long*)secret + 22);
|
||||||
|
|
||||||
var src16 = Sse2.LoadVector128(((long*) secret) + uint64_offset);
|
var dst0 = Sse2.Add(src0, seed);
|
||||||
var dst16 = Sse2.Add(src16, seed);
|
var dst1 = Sse2.Add(src1, seed);
|
||||||
Sse2.Store((long*) customSecret + uint64_offset, dst16);
|
var dst2 = Sse2.Add(src2, seed);
|
||||||
}
|
var dst3 = Sse2.Add(src3, seed);
|
||||||
|
var dst4 = Sse2.Add(src4, seed);
|
||||||
|
var dst5 = Sse2.Add(src5, seed);
|
||||||
|
var dst6 = Sse2.Add(src6, seed);
|
||||||
|
var dst7 = Sse2.Add(src7, seed);
|
||||||
|
var dst8 = Sse2.Add(src8, seed);
|
||||||
|
var dst9 = Sse2.Add(src9, seed);
|
||||||
|
var dst10 = Sse2.Add(src10, seed);
|
||||||
|
var dst11 = Sse2.Add(src11, seed);
|
||||||
|
|
||||||
|
Unsafe.Write((long*)customSecret + 0, dst0);
|
||||||
|
Unsafe.Write((long*)customSecret + 2, dst1);
|
||||||
|
Unsafe.Write((long*)customSecret + 4, dst2);
|
||||||
|
Unsafe.Write((long*)customSecret + 6, dst3);
|
||||||
|
Unsafe.Write((long*)customSecret + 8, dst4);
|
||||||
|
Unsafe.Write((long*)customSecret + 10, dst5);
|
||||||
|
Unsafe.Write((long*)customSecret + 12, dst6);
|
||||||
|
Unsafe.Write((long*)customSecret + 14, dst7);
|
||||||
|
Unsafe.Write((long*)customSecret + 16, dst8);
|
||||||
|
Unsafe.Write((long*)customSecret + 18, dst9);
|
||||||
|
Unsafe.Write((long*)customSecret + 20, dst10);
|
||||||
|
Unsafe.Write((long*)customSecret + 22, dst11);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,23 +314,24 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe ulong XXH3_hashLong_64b_internal(byte* input, int len, byte* secret, int secretSize)
|
private static unsafe ulong XXH3_hashLong_64b_internal(byte* input, int len, byte* secret, int secretSize)
|
||||||
{
|
{
|
||||||
ulong* acc = stackalloc ulong[8];
|
fixed (ulong* src = &XXH3_INIT_ACC[0])
|
||||||
|
|
||||||
fixed (ulong* ptr = &XXH3_INIT_ACC[0])
|
|
||||||
{
|
{
|
||||||
acc[0] = ptr[0];
|
ulong* acc = stackalloc ulong[8]
|
||||||
acc[1] = ptr[1];
|
{
|
||||||
acc[2] = ptr[2];
|
*(src + 0),
|
||||||
acc[3] = ptr[3];
|
*(src + 1),
|
||||||
acc[4] = ptr[4];
|
*(src + 2),
|
||||||
acc[5] = ptr[5];
|
*(src + 3),
|
||||||
acc[6] = ptr[6];
|
*(src + 4),
|
||||||
acc[7] = ptr[7];
|
*(src + 5),
|
||||||
|
*(src + 6),
|
||||||
|
*(src + 7),
|
||||||
|
};
|
||||||
|
|
||||||
|
XXH3_hashLong_internal_loop(acc, input, len, secret, secretSize);
|
||||||
|
|
||||||
|
return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, ((ulong)len) * XXH_PRIME64_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
XXH3_hashLong_internal_loop(acc, input, len, secret, secretSize);
|
|
||||||
|
|
||||||
return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, ((ulong) len) * XXH_PRIME64_1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -378,51 +398,89 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_accumulate_512_avx2(ulong* acc, byte* input, byte* secret)
|
private static unsafe void XXH3_accumulate_512_avx2(ulong* acc, byte* input, byte* secret)
|
||||||
{
|
{
|
||||||
const int m256i_size = 32;
|
var acc_vec0 = Unsafe.Read<Vector256<ulong>>(acc + 0);
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector256<ulong>>(acc + 4);
|
||||||
const byte _MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m256i_size; i++)
|
var data_vec0 = Unsafe.Read<Vector256<ulong>>((ulong*)input + 0).AsUInt32();
|
||||||
{
|
var data_vec1 = Unsafe.Read<Vector256<ulong>>((ulong*)input + 4).AsUInt32();
|
||||||
int uint32_offset = i * 8;
|
|
||||||
int uint64_offset = i * 4;
|
|
||||||
|
|
||||||
var acc_vec = Avx2.LoadVector256(acc + uint64_offset);
|
var key_vec0 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 0).AsUInt32();
|
||||||
var data_vec = Avx2.LoadVector256((uint*) input + uint32_offset);
|
var key_vec1 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 4).AsUInt32();
|
||||||
var key_vec = Avx2.LoadVector256((uint*) secret + uint32_offset);
|
|
||||||
var data_key = Avx2.Xor(data_vec, key_vec);
|
var data_key0 = Avx2.Xor(data_vec0, key_vec0);
|
||||||
var data_key_lo = Avx2.Shuffle(data_key, _MM_SHUFFLE_0_3_0_1);
|
var data_key1 = Avx2.Xor(data_vec1, key_vec1);
|
||||||
var product = Avx2.Multiply(data_key, data_key_lo);
|
|
||||||
var data_swap = Avx2.Shuffle(data_vec, _MM_SHUFFLE_1_0_3_2).AsUInt64();
|
var data_key_lo0 = Avx2.Shuffle(data_key0, MM_SHUFFLE_0_3_0_1);
|
||||||
var sum = Avx2.Add(acc_vec, data_swap);
|
var data_key_lo1 = Avx2.Shuffle(data_key1, MM_SHUFFLE_0_3_0_1);
|
||||||
var result = Avx2.Add(product, sum);
|
|
||||||
Avx2.Store(acc + uint64_offset, result);
|
var product0 = Avx2.Multiply(data_key0, data_key_lo0);
|
||||||
}
|
var product1 = Avx2.Multiply(data_key1, data_key_lo1);
|
||||||
|
|
||||||
|
var data_swap0 = Avx2.Shuffle(data_vec0, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap1 = Avx2.Shuffle(data_vec1, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
|
||||||
|
var sum0 = Avx2.Add(acc_vec0, data_swap0);
|
||||||
|
var sum1 = Avx2.Add(acc_vec1, data_swap1);
|
||||||
|
|
||||||
|
var result0 = Avx2.Add(product0, sum0);
|
||||||
|
var result1 = Avx2.Add(product1, sum1);
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 4, result1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_accumulate_512_sse2(ulong* acc, byte* input, byte* secret)
|
private static unsafe void XXH3_accumulate_512_sse2(ulong* acc, byte* input, byte* secret)
|
||||||
{
|
{
|
||||||
const int m128i_size = 16;
|
var acc_vec0 = Unsafe.Read<Vector128<ulong>>(acc + 0);
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector128<ulong>>(acc + 2);
|
||||||
const byte _MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
var acc_vec2 = Unsafe.Read<Vector128<ulong>>(acc + 4);
|
||||||
|
var acc_vec3 = Unsafe.Read<Vector128<ulong>>(acc + 6);
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m128i_size; i++)
|
var data_vec0 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 0).AsUInt32();
|
||||||
{
|
var data_vec1 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 2).AsUInt32();
|
||||||
int uint32_offset = i * 4;
|
var data_vec2 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 4).AsUInt32();
|
||||||
int uint64_offset = i * 2;
|
var data_vec3 = Unsafe.Read<Vector128<ulong>>((ulong*)input + 6).AsUInt32();
|
||||||
|
|
||||||
var acc_vec = Sse2.LoadVector128(acc + uint64_offset);
|
var key_vec0 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 0).AsUInt32();
|
||||||
var data_vec = Sse2.LoadVector128((uint*) input + uint32_offset);
|
var key_vec1 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 2).AsUInt32();
|
||||||
var key_vec = Sse2.LoadVector128((uint*) secret + uint32_offset);
|
var key_vec2 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 4).AsUInt32();
|
||||||
var data_key = Sse2.Xor(data_vec, key_vec);
|
var key_vec3 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 6).AsUInt32();
|
||||||
var data_key_lo = Sse2.Shuffle(data_key, _MM_SHUFFLE_0_3_0_1);
|
|
||||||
var product = Sse2.Multiply(data_key, data_key_lo);
|
var data_key0 = Sse2.Xor(data_vec0, key_vec0);
|
||||||
var data_swap = Sse2.Shuffle(data_vec, _MM_SHUFFLE_1_0_3_2).AsUInt64();
|
var data_key1 = Sse2.Xor(data_vec1, key_vec1);
|
||||||
var sum = Sse2.Add(acc_vec, data_swap);
|
var data_key2 = Sse2.Xor(data_vec2, key_vec2);
|
||||||
var result = Sse2.Add(product, sum);
|
var data_key3 = Sse2.Xor(data_vec3, key_vec3);
|
||||||
Sse2.Store(acc + uint64_offset, result);
|
|
||||||
}
|
var data_key_lo0 = Sse2.Shuffle(data_key0, MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_lo1 = Sse2.Shuffle(data_key1, MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_lo2 = Sse2.Shuffle(data_key2, MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_lo3 = Sse2.Shuffle(data_key3, MM_SHUFFLE_0_3_0_1);
|
||||||
|
|
||||||
|
var product0 = Sse2.Multiply(data_key0, data_key_lo0);
|
||||||
|
var product1 = Sse2.Multiply(data_key1, data_key_lo1);
|
||||||
|
var product2 = Sse2.Multiply(data_key2, data_key_lo2);
|
||||||
|
var product3 = Sse2.Multiply(data_key3, data_key_lo3);
|
||||||
|
|
||||||
|
var data_swap0 = Sse2.Shuffle(data_vec0, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap1 = Sse2.Shuffle(data_vec1, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap2 = Sse2.Shuffle(data_vec2, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
var data_swap3 = Sse2.Shuffle(data_vec3, MM_SHUFFLE_1_0_3_2).AsUInt64();
|
||||||
|
|
||||||
|
var sum0 = Sse2.Add(acc_vec0, data_swap0);
|
||||||
|
var sum1 = Sse2.Add(acc_vec1, data_swap1);
|
||||||
|
var sum2 = Sse2.Add(acc_vec2, data_swap2);
|
||||||
|
var sum3 = Sse2.Add(acc_vec3, data_swap3);
|
||||||
|
|
||||||
|
var result0 = Sse2.Add(product0, sum0);
|
||||||
|
var result1 = Sse2.Add(product1, sum1);
|
||||||
|
var result2 = Sse2.Add(product2, sum2);
|
||||||
|
var result3 = Sse2.Add(product3, sum3);
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 2, result1);
|
||||||
|
Unsafe.Write(acc + 4, result2);
|
||||||
|
Unsafe.Write(acc + 6, result3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -459,52 +517,89 @@ namespace Standart.Hash.xxHash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_scrambleAcc_avx2(ulong* acc, byte* secret)
|
private static unsafe void XXH3_scrambleAcc_avx2(ulong* acc, byte* secret)
|
||||||
{
|
{
|
||||||
const int m256i_size = 32;
|
var acc_vec0 = Unsafe.Read<Vector256<ulong>>(acc + 0);
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector256<ulong>>(acc + 4);
|
||||||
|
|
||||||
var prime32 = Vector256.Create(XXH_PRIME32_1);
|
var shifted0 = Avx2.ShiftRightLogical(acc_vec0, 47);
|
||||||
|
var shifted1 = Avx2.ShiftRightLogical(acc_vec1, 47);
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m256i_size; i++)
|
var data_vec0 = Avx2.Xor(acc_vec0, shifted0);
|
||||||
{
|
var data_vec1 = Avx2.Xor(acc_vec1, shifted1);
|
||||||
int uint64_offset = i * 4;
|
|
||||||
|
|
||||||
var acc_vec = Avx2.LoadVector256(acc + uint64_offset);
|
var key_vec0 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 0);
|
||||||
var shifted = Avx2.ShiftRightLogical(acc_vec, 47);
|
var key_vec1 = Unsafe.Read<Vector256<ulong>>((ulong*)secret + 4);
|
||||||
var data_vec = Avx2.Xor(acc_vec, shifted);
|
|
||||||
var key_vec = Avx2.LoadVector256((ulong*) secret + uint64_offset);
|
var data_key0 = Avx2.Xor(data_vec0, key_vec0).AsUInt32();
|
||||||
var data_key = Avx2.Xor(data_vec, key_vec).AsUInt32();
|
var data_key1 = Avx2.Xor(data_vec1, key_vec1).AsUInt32();
|
||||||
var data_key_hi = Avx2.Shuffle(data_key, _MM_SHUFFLE_0_3_0_1);
|
|
||||||
var prod_lo = Avx2.Multiply(data_key, prime32);
|
var data_key_hi0 = Avx2.Shuffle(data_key0, MM_SHUFFLE_0_3_0_1);
|
||||||
var prod_hi = Avx2.Multiply(data_key_hi, prime32);
|
var data_key_hi1 = Avx2.Shuffle(data_key1, MM_SHUFFLE_0_3_0_1);
|
||||||
var result = Avx2.Add(prod_lo, Avx2.ShiftLeftLogical(prod_hi, 32));
|
|
||||||
Avx2.Store(acc + uint64_offset, result);
|
var prod_lo0 = Avx2.Multiply(data_key0, M256i_XXH_PRIME32_1);
|
||||||
}
|
var prod_lo1 = Avx2.Multiply(data_key1, M256i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var prod_hi0 = Avx2.Multiply(data_key_hi0, M256i_XXH_PRIME32_1);
|
||||||
|
var prod_hi1 = Avx2.Multiply(data_key_hi1, M256i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var result0 = Avx2.Add(prod_lo0, Avx2.ShiftLeftLogical(prod_hi0, 32));
|
||||||
|
var result1 = Avx2.Add(prod_lo1, Avx2.ShiftLeftLogical(prod_hi1, 32));
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 4, result1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static unsafe void XXH3_scrambleAcc_sse2(ulong* acc, byte* secret)
|
private static unsafe void XXH3_scrambleAcc_sse2(ulong* acc, byte* secret)
|
||||||
{
|
{
|
||||||
const int m128i_size = 16;
|
var acc_vec0 = Unsafe.Read<Vector128<ulong>>(acc + 0).AsUInt32();
|
||||||
const byte _MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
var acc_vec1 = Unsafe.Read<Vector128<ulong>>(acc + 2).AsUInt32();
|
||||||
|
var acc_vec2 = Unsafe.Read<Vector128<ulong>>(acc + 4).AsUInt32();
|
||||||
|
var acc_vec3 = Unsafe.Read<Vector128<ulong>>(acc + 6).AsUInt32();
|
||||||
|
|
||||||
var prime32 = Vector128.Create(XXH_PRIME32_1);
|
var shifted0 = Sse2.ShiftRightLogical(acc_vec0, 47);
|
||||||
|
var shifted1 = Sse2.ShiftRightLogical(acc_vec1, 47);
|
||||||
|
var shifted2 = Sse2.ShiftRightLogical(acc_vec2, 47);
|
||||||
|
var shifted3 = Sse2.ShiftRightLogical(acc_vec3, 47);
|
||||||
|
|
||||||
for (int i = 0; i < XXH_STRIPE_LEN / m128i_size; i++)
|
var data_vec0 = Sse2.Xor(acc_vec0, shifted0);
|
||||||
{
|
var data_vec1 = Sse2.Xor(acc_vec1, shifted1);
|
||||||
int uint32_offset = i * 4;
|
var data_vec2 = Sse2.Xor(acc_vec2, shifted2);
|
||||||
int uint64_offset = i * 2;
|
var data_vec3 = Sse2.Xor(acc_vec3, shifted3);
|
||||||
|
|
||||||
var acc_vec = Sse2.LoadVector128(acc + uint64_offset).AsUInt32();
|
var key_vec0 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 0).AsUInt32();
|
||||||
var shifted = Sse2.ShiftRightLogical(acc_vec, 47);
|
var key_vec1 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 2).AsUInt32();
|
||||||
var data_vec = Sse2.Xor(acc_vec, shifted);
|
var key_vec2 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 4).AsUInt32();
|
||||||
var key_vec = Sse2.LoadVector128((uint*) secret + uint32_offset);
|
var key_vec3 = Unsafe.Read<Vector128<ulong>>((ulong*)secret + 6).AsUInt32();
|
||||||
var data_key = Sse2.Xor(data_vec, key_vec);
|
|
||||||
var data_key_hi = Sse2.Shuffle(data_key.AsUInt32(), _MM_SHUFFLE_0_3_0_1);
|
var data_key0 = Sse2.Xor(data_vec0, key_vec0);
|
||||||
var prod_lo = Sse2.Multiply(data_key, prime32);
|
var data_key1 = Sse2.Xor(data_vec1, key_vec1);
|
||||||
var prod_hi = Sse2.Multiply(data_key_hi, prime32);
|
var data_key2 = Sse2.Xor(data_vec2, key_vec2);
|
||||||
var result = Sse2.Add(prod_lo, Sse2.ShiftLeftLogical(prod_hi, 32));
|
var data_key3 = Sse2.Xor(data_vec3, key_vec3);
|
||||||
Sse2.Store(acc + uint64_offset, result);
|
|
||||||
}
|
var data_key_hi0 = Sse2.Shuffle(data_key0.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_hi1 = Sse2.Shuffle(data_key1.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_hi2 = Sse2.Shuffle(data_key2.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
var data_key_hi3 = Sse2.Shuffle(data_key3.AsUInt32(), MM_SHUFFLE_0_3_0_1);
|
||||||
|
|
||||||
|
var prod_lo0 = Sse2.Multiply(data_key0, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_lo1 = Sse2.Multiply(data_key1, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_lo2 = Sse2.Multiply(data_key2, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_lo3 = Sse2.Multiply(data_key3, M128i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var prod_hi0 = Sse2.Multiply(data_key_hi0, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_hi1 = Sse2.Multiply(data_key_hi1, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_hi2 = Sse2.Multiply(data_key_hi2, M128i_XXH_PRIME32_1);
|
||||||
|
var prod_hi3 = Sse2.Multiply(data_key_hi3, M128i_XXH_PRIME32_1);
|
||||||
|
|
||||||
|
var result0 = Sse2.Add(prod_lo0, Sse2.ShiftLeftLogical(prod_hi0, 32));
|
||||||
|
var result1 = Sse2.Add(prod_lo1, Sse2.ShiftLeftLogical(prod_hi1, 32));
|
||||||
|
var result2 = Sse2.Add(prod_lo2, Sse2.ShiftLeftLogical(prod_hi2, 32));
|
||||||
|
var result3 = Sse2.Add(prod_lo3, Sse2.ShiftLeftLogical(prod_hi3, 32));
|
||||||
|
|
||||||
|
Unsafe.Write(acc + 0, result0);
|
||||||
|
Unsafe.Write(acc + 2, result1);
|
||||||
|
Unsafe.Write(acc + 4, result2);
|
||||||
|
Unsafe.Write(acc + 6, result3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -529,3 +624,4 @@ namespace Standart.Hash.xxHash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
#if NET6_0_OR_GREATER
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash3
|
public static partial class xxHash3
|
||||||
{
|
{
|
||||||
@@ -18,3 +17,4 @@ namespace Standart.Hash.xxHash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
#if NET6_0_OR_GREATER
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
public static partial class xxHash3
|
public static partial class xxHash3
|
||||||
{
|
{
|
||||||
@@ -89,11 +88,9 @@ namespace Standart.Hash.xxHash
|
|||||||
{
|
{
|
||||||
fixed (byte* secret = &XXH3_SECRET[0])
|
fixed (byte* secret = &XXH3_SECRET[0])
|
||||||
{
|
{
|
||||||
// Use inlined version
|
return XXH3_64bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
||||||
// return XXH3_64bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
|
||||||
|
|
||||||
return __inline__XXH3_64bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
21
DTLib.XXHash/xxHash32.XXH.cs
Normal file
21
DTLib.XXHash/xxHash32.XXH.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DTLib.XXHash
|
||||||
|
{
|
||||||
|
public static partial class xxHash32
|
||||||
|
{
|
||||||
|
private static readonly uint XXH_PRIME32_1 = 2654435761U;
|
||||||
|
private static readonly uint XXH_PRIME32_2 = 2246822519U;
|
||||||
|
private static readonly uint XXH_PRIME32_3 = 3266489917U;
|
||||||
|
private static readonly uint XXH_PRIME32_4 = 668265263U;
|
||||||
|
private static readonly uint XXH_PRIME32_5 = 374761393U;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static uint XXH_rotl32(uint x, int r)
|
||||||
|
{
|
||||||
|
return (x << r) | (x >> (32 - r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
264
DTLib.XXHash/xxHash32.cs
Normal file
264
DTLib.XXHash/xxHash32.cs
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DTLib.XXHash
|
||||||
|
{
|
||||||
|
public static partial class xxHash32
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the data byte array
|
||||||
|
/// </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(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the data byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">The source of data</param>
|
||||||
|
/// <param name="offset">The offset of the data for hashing</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(byte[] data, int offset, int length, uint seed = 0)
|
||||||
|
{
|
||||||
|
Debug.Assert(data != null);
|
||||||
|
Debug.Assert(length >= 0);
|
||||||
|
Debug.Assert(offset < data.Length);
|
||||||
|
Debug.Assert(length <= data.Length - offset);
|
||||||
|
|
||||||
|
fixed (byte* pData = &data[0 + offset])
|
||||||
|
{
|
||||||
|
return UnsafeComputeHash(pData, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the data byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">The source of data</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <returns>hash</returns>
|
||||||
|
public static ulong ComputeHash(ArraySegment<byte> data, uint seed = 0)
|
||||||
|
{
|
||||||
|
return ComputeHash(data.Array, data.Offset, data.Count, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the async stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream of data</param>
|
||||||
|
/// <param name="bufferSize">The buffer size</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <returns>The hash</returns>
|
||||||
|
public static async ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize = 4096, uint seed = 0)
|
||||||
|
{
|
||||||
|
return await ComputeHashAsync(stream, bufferSize, seed, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the async stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream of data</param>
|
||||||
|
/// <param name="bufferSize">The buffer size</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token</param>
|
||||||
|
/// <returns>The hash</returns>
|
||||||
|
public static async ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize, uint seed, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Debug.Assert(stream != null);
|
||||||
|
Debug.Assert(bufferSize > 16);
|
||||||
|
|
||||||
|
// Optimizing memory allocation
|
||||||
|
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 16);
|
||||||
|
|
||||||
|
int readBytes;
|
||||||
|
int offset = 0;
|
||||||
|
long length = 0;
|
||||||
|
|
||||||
|
// Prepare the seed vector
|
||||||
|
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||||
|
uint v2 = seed + XXH_PRIME32_2;
|
||||||
|
uint v3 = seed + 0;
|
||||||
|
uint v4 = seed - XXH_PRIME32_1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Read flow of bytes
|
||||||
|
while ((readBytes =
|
||||||
|
await stream.ReadAsync(buffer, offset, bufferSize, cancellationToken).ConfigureAwait(false)) > 0)
|
||||||
|
{
|
||||||
|
length = length + readBytes;
|
||||||
|
offset = offset + readBytes;
|
||||||
|
|
||||||
|
if (offset < 16) continue;
|
||||||
|
|
||||||
|
int r = offset % 16; // remain
|
||||||
|
int l = offset - r; // length
|
||||||
|
|
||||||
|
// Process the next chunk
|
||||||
|
__inline__XXH32_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||||
|
|
||||||
|
// Put remaining bytes to buffer
|
||||||
|
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||||
|
offset = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the final chunk
|
||||||
|
uint h32 = __inline__XXH32_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||||
|
|
||||||
|
return h32;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Free memory
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
/// <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 = &MemoryMarshal.GetReference(data))
|
||||||
|
{
|
||||||
|
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(ReadOnlySpan<byte> data, int length, uint seed = 0)
|
||||||
|
{
|
||||||
|
Debug.Assert(data != null);
|
||||||
|
Debug.Assert(length >= 0);
|
||||||
|
Debug.Assert(length <= data.Length);
|
||||||
|
|
||||||
|
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
||||||
|
{
|
||||||
|
return UnsafeComputeHash(pData, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream of data</param>
|
||||||
|
/// <param name="bufferSize">The buffer size</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <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);
|
||||||
|
|
||||||
|
int readBytes;
|
||||||
|
int offset = 0;
|
||||||
|
long length = 0;
|
||||||
|
|
||||||
|
// Prepare the seed vector
|
||||||
|
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||||
|
uint v2 = seed + XXH_PRIME32_2;
|
||||||
|
uint v3 = seed + 0;
|
||||||
|
uint v4 = seed - XXH_PRIME32_1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Read flow of bytes
|
||||||
|
while ((readBytes = stream.Read(buffer, offset, bufferSize)) > 0)
|
||||||
|
{
|
||||||
|
length = length + readBytes;
|
||||||
|
offset = offset + readBytes;
|
||||||
|
|
||||||
|
if (offset < 16) continue;
|
||||||
|
|
||||||
|
int r = offset % 16; // remain
|
||||||
|
int l = offset - r; // length
|
||||||
|
|
||||||
|
// Process the next chunk
|
||||||
|
__inline__XXH32_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||||
|
|
||||||
|
// Put remaining bytes to buffer
|
||||||
|
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||||
|
offset = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the last chunk
|
||||||
|
uint h32 = __inline__XXH32_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||||
|
|
||||||
|
return h32;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Free memory
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The source of data</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <returns>hash</returns>
|
||||||
|
public static unsafe uint ComputeHash(string str, uint seed = 0)
|
||||||
|
{
|
||||||
|
Debug.Assert(str != null);
|
||||||
|
|
||||||
|
fixed (char* c = str)
|
||||||
|
{
|
||||||
|
byte* ptr = (byte*) c;
|
||||||
|
int length = str.Length * 2;
|
||||||
|
|
||||||
|
return UnsafeComputeHash(ptr, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe uint UnsafeComputeHash(byte* ptr, int length, uint seed)
|
||||||
|
{
|
||||||
|
// Use inlined version
|
||||||
|
// return XXH32(ptr, length, seed);
|
||||||
|
|
||||||
|
return __inline__XXH32(ptr, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
DTLib.XXHash/xxHash64.XXH.cs
Normal file
21
DTLib.XXHash/xxHash64.XXH.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DTLib.XXHash
|
||||||
|
{
|
||||||
|
public static partial class xxHash64
|
||||||
|
{
|
||||||
|
private const ulong XXH_PRIME64_1 = 11400714785074694791UL;
|
||||||
|
private const ulong XXH_PRIME64_2 = 14029467366897019727UL;
|
||||||
|
private const ulong XXH_PRIME64_3 = 1609587929392839161UL;
|
||||||
|
private const ulong XXH_PRIME64_4 = 9650029242287828579UL;
|
||||||
|
private const ulong XXH_PRIME64_5 = 2870177450012600261UL;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ulong XXH_rotl64(ulong x, int r)
|
||||||
|
{
|
||||||
|
return (x << r) | (x >> (64 - r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash
|
namespace DTLib.XXHash
|
||||||
{
|
{
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
264
DTLib.XXHash/xxHash64.cs
Normal file
264
DTLib.XXHash/xxHash64.cs
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
using System.Buffers;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DTLib.XXHash
|
||||||
|
{
|
||||||
|
public static partial class xxHash64
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the data byte array
|
||||||
|
/// </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(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the data byte array
|
||||||
|
/// </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(byte[] data, int offset, int length, ulong seed = 0)
|
||||||
|
{
|
||||||
|
Debug.Assert(data != null);
|
||||||
|
Debug.Assert(length >= 0);
|
||||||
|
Debug.Assert(offset < data.Length);
|
||||||
|
Debug.Assert(length <= data.Length - offset);
|
||||||
|
|
||||||
|
fixed (byte* pData = &data[0 + offset])
|
||||||
|
{
|
||||||
|
return UnsafeComputeHash(pData, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the data byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">The source of data</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <returns>hash</returns>
|
||||||
|
public static ulong ComputeHash(System.ArraySegment<byte> data, ulong seed = 0)
|
||||||
|
{
|
||||||
|
return ComputeHash(data.Array, data.Offset, data.Count, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the async stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream of data</param>
|
||||||
|
/// <param name="bufferSize">The buffer size</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <returns>The hash</returns>
|
||||||
|
public static async ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize = 8192, ulong seed = 0)
|
||||||
|
{
|
||||||
|
return await ComputeHashAsync(stream, bufferSize, seed, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the async stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream of data</param>
|
||||||
|
/// <param name="bufferSize">The buffer size</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <param name="cancellationToken">The cancelation token</param>
|
||||||
|
/// <returns>The hash</returns>
|
||||||
|
public static async ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize, ulong seed,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Debug.Assert(stream != null);
|
||||||
|
Debug.Assert(bufferSize > 32);
|
||||||
|
|
||||||
|
// Optimizing memory allocation
|
||||||
|
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 32);
|
||||||
|
|
||||||
|
int readBytes;
|
||||||
|
int offset = 0;
|
||||||
|
long length = 0;
|
||||||
|
|
||||||
|
// Prepare the seed vector
|
||||||
|
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||||
|
ulong v2 = seed + XXH_PRIME64_2;
|
||||||
|
ulong v3 = seed + 0;
|
||||||
|
ulong v4 = seed - XXH_PRIME64_1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Read flow of bytes
|
||||||
|
while ((readBytes =
|
||||||
|
await stream.ReadAsync(buffer, offset, bufferSize, cancellationToken).ConfigureAwait(false)) > 0)
|
||||||
|
{
|
||||||
|
length = length + readBytes;
|
||||||
|
offset = offset + readBytes;
|
||||||
|
|
||||||
|
if (offset < 32) continue;
|
||||||
|
|
||||||
|
int r = offset % 32; // remain
|
||||||
|
int l = offset - r; // length
|
||||||
|
|
||||||
|
// Process the next chunk
|
||||||
|
__inline__XXH64_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||||
|
|
||||||
|
// Put remaining bytes to buffer
|
||||||
|
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||||
|
offset = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the final chunk
|
||||||
|
ulong h64 = __inline__XXH64_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||||
|
|
||||||
|
return h64;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Free memory
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
/// <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 = &MemoryMarshal.GetReference(data))
|
||||||
|
{
|
||||||
|
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(ReadOnlySpan<byte> data, int length, ulong seed = 0)
|
||||||
|
{
|
||||||
|
Debug.Assert(data != null);
|
||||||
|
Debug.Assert(length >= 0);
|
||||||
|
Debug.Assert(length <= data.Length);
|
||||||
|
|
||||||
|
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
||||||
|
{
|
||||||
|
return UnsafeComputeHash(pData, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream of data</param>
|
||||||
|
/// <param name="bufferSize">The buffer size</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <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);
|
||||||
|
|
||||||
|
int readBytes;
|
||||||
|
int offset = 0;
|
||||||
|
long length = 0;
|
||||||
|
|
||||||
|
// Prepare the seed vector
|
||||||
|
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||||
|
ulong v2 = seed + XXH_PRIME64_2;
|
||||||
|
ulong v3 = seed + 0;
|
||||||
|
ulong v4 = seed - XXH_PRIME64_1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Read flow of bytes
|
||||||
|
while ((readBytes = stream.Read(buffer, offset, bufferSize)) > 0)
|
||||||
|
{
|
||||||
|
length = length + readBytes;
|
||||||
|
offset = offset + readBytes;
|
||||||
|
|
||||||
|
if (offset < 32) continue;
|
||||||
|
|
||||||
|
int r = offset % 32; // remain
|
||||||
|
int l = offset - r; // length
|
||||||
|
|
||||||
|
// Process the next chunk
|
||||||
|
__inline__XXH64_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||||
|
|
||||||
|
// Put remaining bytes to buffer
|
||||||
|
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||||
|
offset = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the final chunk
|
||||||
|
ulong h64 = __inline__XXH64_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||||
|
|
||||||
|
return h64;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Free memory
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute xxHash for the string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The source of data</param>
|
||||||
|
/// <param name="seed">The seed number</param>
|
||||||
|
/// <returns>hash</returns>
|
||||||
|
public static unsafe ulong ComputeHash(string str, uint seed = 0)
|
||||||
|
{
|
||||||
|
Debug.Assert(str != null);
|
||||||
|
|
||||||
|
fixed (char* c = str)
|
||||||
|
{
|
||||||
|
byte* ptr = (byte*) c;
|
||||||
|
int length = str.Length * 2;
|
||||||
|
|
||||||
|
return UnsafeComputeHash(ptr, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe ulong UnsafeComputeHash(byte* ptr, int length, ulong seed)
|
||||||
|
{
|
||||||
|
// Use inlined version
|
||||||
|
// return XXH64(ptr, length, seed);
|
||||||
|
|
||||||
|
return __inline__XXH64(ptr, length, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
131
README.md
131
README.md
@@ -1,131 +0,0 @@
|
|||||||
<p align="center">
|
|
||||||
<a href="#" target="_blank" rel="noopener noreferrer">
|
|
||||||
<img width="550" src="https://user-images.githubusercontent.com/1567570/39971158-5b213cca-56ff-11e8-9a1e-6c717e95d092.png" alt="xxHash.st">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
Extremely fast non-cryptographic hash algorithm <a href="http://www.xxhash.com/" target="_blank">xxhash</a>
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
<p align="center">
|
|
||||||
<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"/>
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/uranium62/xxHash/blob/master/LICENSE">
|
|
||||||
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="license" />
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
xxHash is an Extremely fast Hash algorithm, running at RAM speed limits. It successfully completes the **SMHasher** test suite which evaluates collision, dispersion and randomness qualities of hash functions.
|
|
||||||
|
|
||||||
## Instalation
|
|
||||||
```
|
|
||||||
PM> Install-Package Standart.Hash.xxHash
|
|
||||||
```
|
|
||||||
|
|
||||||
## Benchmarks
|
|
||||||
This benchmark was launched on a **Windows 10.0.19044.1706 (21H2)**. The reference system uses a **AMD Ryzen 7 2700, 1 CPU, 16 logical and 8 physical cores**
|
|
||||||
```
|
|
||||||
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.1706 (21H2)
|
|
||||||
AMD Ryzen 7 2700, 1 CPU, 16 logical and 8 physical cores
|
|
||||||
.NET SDK=6.0.300
|
|
||||||
[Host] : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
|
|
||||||
Job-HQVLOG : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
|
|
||||||
Runtime=.NET 6.0
|
|
||||||
```
|
|
||||||
|
|
||||||
| Method | x64 |
|
|
||||||
|:---------------|-----------:|
|
|
||||||
| Hash32 Array | 5.87 GB/s |
|
|
||||||
| Hash64 Array | 9.07 GB/s |
|
|
||||||
| Hash128 Array | 12.04 GB/s |
|
|
||||||
| Hash3 Array | 12.08 GB/s |
|
|
||||||
| Hash32 Span | 5.87 GB/s |
|
|
||||||
| Hash64 Span | 9.07 GB/s |
|
|
||||||
| Hash128 Span | 12.04 GB/s |
|
|
||||||
| Hash3 Span | 12.08 GB/s |
|
|
||||||
| Hash32 Stream | 3.22 GB/s |
|
|
||||||
| Hash64 Stream | 4.81 GB/s |
|
|
||||||
|
|
||||||
## Comparison between С# and C implementation
|
|
||||||
|
|
||||||
| Method | Platform | Language | 1KB Time | 1MB Time | 1GB Time | Speed |
|
|
||||||
|:-------------------|---------:|---------:|----------:|----------:|----------:|-----------:|
|
|
||||||
| Hash32 | x64 | C# | 151.5 ns | 143.4 us | 170.3 ms | 5.87 GB/s |
|
|
||||||
| Hash32 | x64 | C | 138.5 ns | 129.5 us | 152.4 ms | 6.56 GB/s |
|
|
||||||
| Hash64 | x64 | C# | 84.6 ns | 77.9 us | 110.2 ms | 9.07 GB/s |
|
|
||||||
| Hash64 | x64 | C | 74.2 ns | 64.8 us | 83.0 ms | 12.04 GB/s |
|
|
||||||
| Hash128 (SSE2/AVX2)| x64 | C# | 151.6 ns | 64.5 us | 80.5 ms | 12.04 GB/s |
|
|
||||||
| Hash128 (SSE2/AVX2)| x64 | C | 84.4 ns | 38.3 us | 57.4 ms | 17.42 GB/s |
|
|
||||||
| Hash3 (SSE2/AVX2)| x64 | C# | 77.6 ns | 62.1 us | 78.5 ms | 12.08 GB/s |
|
|
||||||
| Hash3 (SSE2/AVX2)| x64 | C | 73.7 ns | 42.2 us | 59.8 ms | 16.72 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 ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize = 4096, uint seed = 0) { throw null; }
|
|
||||||
public static uint ComputeHash(string str, 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 ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize = 8192, ulong seed = 0) { throw null; }
|
|
||||||
public static ulong ComputeHash(string str, uint seed = 0) { throw null; }
|
|
||||||
|
|
||||||
public static uint128 ComputeHash(byte[] data, int length, uint seed = 0) { throw null; }
|
|
||||||
public static uint128 ComputeHash(Span<byte> data, int length, uint seed = 0) { throw null; }
|
|
||||||
public static uint128 ComputeHash(string str, uint seed = 0) { throw null; }
|
|
||||||
|
|
||||||
// allocations
|
|
||||||
public static byte[] ComputeHashBytes(byte[] data, int length, uint seed = 0) { throw null; }
|
|
||||||
public static byte[] ComputeHashBytes(Span<byte> data, int length, uint seed = 0) { throw null; }
|
|
||||||
public static byte[] ComputeHashBytes(string str, uint seed = 0) { throw null; }
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
A few examples of how to use api
|
|
||||||
```cs
|
|
||||||
byte[] data = Encoding.UTF8.GetBytes("veni vidi vici");
|
|
||||||
|
|
||||||
ulong h64_1 = xxHash64.ComputeHash(data, data.Length);
|
|
||||||
ulong h64_2 = xxHash64.ComputeHash(new Span<byte>(data), data.Length);
|
|
||||||
ulong h64_3 = xxHash64.ComputeHash(new ReadOnlySpan<byte>(data), data.Length);
|
|
||||||
ulong h64_4 = xxHash64.ComputeHash(new MemoryStream(data));
|
|
||||||
ulong h64_5 = await xxHash64.ComputeHashAsync(new MemoryStream(data));
|
|
||||||
ulong h64_6 = xxHash64.ComputeHash("veni vidi vici");
|
|
||||||
|
|
||||||
uint h32_1 = xxHash32.ComputeHash(data, data.Length);
|
|
||||||
uint h32_2 = xxHash32.ComputeHash(new Span<byte>(data), data.Length);
|
|
||||||
uint h32_3 = xxHash32.ComputeHash(new ReadOnlySpan<byte>(data), data.Length);
|
|
||||||
uint h32_4 = xxHash32.ComputeHash(new MemoryStream(data));
|
|
||||||
uint h32_5 = await xxHash32.ComputeHashAsync(new MemoryStream(data));
|
|
||||||
uint h32_6 = xxHash32.ComputeHash("veni vidi vici");
|
|
||||||
|
|
||||||
ulong h3_1 = xxHash3.ComputeHash(data, data.Length);
|
|
||||||
ulong h3_2 = xxHash3.ComputeHash(new Span<byte>(data), data.Length);
|
|
||||||
ulong h3_3 = xxHash3.ComputeHash(new ReadOnlySpan<byte>(data), data.Length);
|
|
||||||
ulong h3_4 = xxHash3.ComputeHash("veni vidi vici");
|
|
||||||
|
|
||||||
uint128 h128_1 = xxHash128.ComputeHash(data, data.Length);
|
|
||||||
uint128 h128_2 = xxHash128.ComputeHash(new Span<byte>(data), data.Length);
|
|
||||||
uint128 h128_3 = xxHash128.ComputeHash(new ReadOnlySpan<byte>(data), data.Length);
|
|
||||||
uint128 h128_4 = xxHash128.ComputeHash("veni vidi vici");
|
|
||||||
|
|
||||||
Guid guid = h128_1.ToGuid();
|
|
||||||
byte[] bytes = h128_1.ToBytes();
|
|
||||||
|
|
||||||
byte[] hash_bytes_1 = xxHash128.ComputeHashBytes(data, data.Length);
|
|
||||||
byte[] hash_bytes_2 = xxHash128.ComputeHashBytes(new Span<byte>(data), data.Length);
|
|
||||||
byte[] hash_bytes_3 = xxHash128.ComputeHashBytes(new ReadOnlySpan<byte>(data), data.Length);
|
|
||||||
byte[] hash_bytes_4 = xxHash128.ComputeHashBytes("veni vidi vici");
|
|
||||||
|
|
||||||
```
|
|
||||||
---
|
|
||||||
<p align="center">
|
|
||||||
Made in :beginner: Ukraine with :heart:
|
|
||||||
</p>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<BenchmarkDotNet>0.13.1</BenchmarkDotNet>
|
|
||||||
<MicrosoftSdk>17.2.0</MicrosoftSdk>
|
|
||||||
<xUnit>2.4.1</xUnit>
|
|
||||||
<xUnitRunner>2.4.5</xUnitRunner>
|
|
||||||
<xUnitTool>2.3.1</xUnitTool>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
15
nuget.props
15
nuget.props
@@ -1,15 +0,0 @@
|
|||||||
<Project>
|
|
||||||
<Import Project="deps.props" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<PackageId>Standart.Hash.xxHash</PackageId>
|
|
||||||
<VersionPrefix>4.0.3</VersionPrefix>
|
|
||||||
<AssemblyName>Standart.Hash.xxHash</AssemblyName>
|
|
||||||
<AssemblyTitle>Standart.Hash.xxHash</AssemblyTitle>
|
|
||||||
<Authors>Oleksandr Melnyk</Authors>
|
|
||||||
<PackageTags>hash;xxHash</PackageTags>
|
|
||||||
<Description>Standart.Hash.xxHash</Description>
|
|
||||||
<PackageProjectUrl>https://github.com/uranium62/xxHash</PackageProjectUrl>
|
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<Import Project="..\..\deps.props" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNet)" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Standart.Hash.xxHash\Standart.Hash.xxHash.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<Import Project="..\..\deps.props" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftSdk)" />
|
|
||||||
<PackageReference Include="xunit" Version="$(xUnit)" />
|
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(xUnitRunner)" />
|
|
||||||
<DotNetCliToolReference Include="dotnet-xunit" Version="$(xUnitTool)" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Standart.Hash.xxHash\Standart.Hash.xxHash.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash.Test;
|
|
||||||
|
|
||||||
public class xxHash128Test
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void Compute_hash128_for_bytes()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var bytes = new byte[]
|
|
||||||
{
|
|
||||||
0xd2, 0x94, 0x29, 0xc9, 0x4c, 0xc5, 0x0f, 0xbb,
|
|
||||||
0xaa, 0xf4, 0x7c, 0xd5, 0x69, 0x5a, 0xa9, 0xbd,
|
|
||||||
0xaf, 0xd8, 0x3f, 0xfb, 0xca, 0x6a, 0xd4, 0x2c,
|
|
||||||
0x6c, 0x69, 0x7a, 0x5b, 0x0d, 0xe8, 0xd2, 0xb1,
|
|
||||||
0x41, 0xb3, 0x1b, 0x23, 0xdb, 0x8c, 0x25, 0xb4,
|
|
||||||
0x6c, 0xfb
|
|
||||||
};
|
|
||||||
|
|
||||||
ulong expectedH = 3466251221427321594;
|
|
||||||
ulong expectedL = 2862260537881727713;
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var hash = xxHash128.ComputeHash(bytes, bytes.Length);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(expectedH, hash.high64);
|
|
||||||
Assert.Equal(expectedL, hash.low64);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Compute_hash128_for_span()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var bytes = new byte[]
|
|
||||||
{
|
|
||||||
0xd2, 0x94, 0x29, 0xc9, 0x4c, 0xc5, 0x0f, 0xbb,
|
|
||||||
0xaa, 0xf4, 0x7c, 0xd5, 0x69, 0x5a, 0xa9, 0xbd,
|
|
||||||
0xaf, 0xd8, 0x3f, 0xfb, 0xca, 0x6a, 0xd4, 0x2c,
|
|
||||||
0x6c, 0x69, 0x7a, 0x5b, 0x0d, 0xe8, 0xd2, 0xb1,
|
|
||||||
0x41, 0xb3, 0x1b, 0x23, 0xdb, 0x8c, 0x25, 0xb4,
|
|
||||||
0x6c, 0xfb
|
|
||||||
};
|
|
||||||
var span = bytes.AsSpan();
|
|
||||||
|
|
||||||
ulong expectedH = 3466251221427321594;
|
|
||||||
ulong expectedL = 2862260537881727713;
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var hash = xxHash128.ComputeHash(span, span.Length);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(expectedH, hash.high64);
|
|
||||||
Assert.Equal(expectedL, hash.low64);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Compute_hash128_for_string()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var str = "veni vidi vici";
|
|
||||||
var bytes = Encoding.Unicode.GetBytes(str);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var hash1 = xxHash128.ComputeHash(str);
|
|
||||||
var hash2 = xxHash128.ComputeHash(bytes, bytes.Length);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(hash1.high64, hash2.high64);
|
|
||||||
Assert.Equal(hash1.low64, hash2.low64);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Compute_hash128_bytes_for_bytes()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var bytes = new byte[]
|
|
||||||
{
|
|
||||||
0xd2, 0x94, 0x29, 0xc9, 0x4c, 0xc5, 0x0f, 0xbb,
|
|
||||||
0xaa, 0xf4, 0x7c, 0xd5, 0x69, 0x5a, 0xa9, 0xbd,
|
|
||||||
0xaf, 0xd8, 0x3f, 0xfb, 0xca, 0x6a, 0xd4, 0x2c,
|
|
||||||
0x6c, 0x69, 0x7a, 0x5b, 0x0d, 0xe8, 0xd2, 0xb1,
|
|
||||||
0x41, 0xb3, 0x1b, 0x23, 0xdb, 0x8c, 0x25, 0xb4,
|
|
||||||
0x6c, 0xfb
|
|
||||||
};
|
|
||||||
|
|
||||||
// ulong expectedH = 3466251221427321594;
|
|
||||||
// ulong expectedL = 2862260537881727713;
|
|
||||||
|
|
||||||
// (hBits * 18446744073709551616) + lBits
|
|
||||||
// (3466251221427321594 * 18446744073709551616) + 2862260537881727713
|
|
||||||
|
|
||||||
// dec: 63941049176852939372872402763456123617
|
|
||||||
// hex: 301A991EF3707AFA27B8CACB570F12E1
|
|
||||||
var expected = new byte[]
|
|
||||||
{
|
|
||||||
0xe1, 0x12, 0x0F, 0x57, 0xcb, 0xca, 0xb8, 0x27,
|
|
||||||
0xfa, 0x7a, 0x70, 0xf3, 0x1e, 0x99, 0x1a, 0x30
|
|
||||||
};
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var hash = xxHash128.ComputeHashBytes(bytes, bytes.Length);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
Assert.Equal(expected[i], hash[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Standart.Hash.xxHash", "Standart.Hash.xxHash\Standart.Hash.xxHash.csproj", "{E468CD00-D581-46DD-ADE6-71EFA74AD62E}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Standart.Hash.xxHash.Perf", "Standart.Hash.xxHash.Perf\Standart.Hash.xxHash.Perf.csproj", "{7B80269B-1EC4-40B5-8E19-F0A68C4404E5}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Standart.Hash.xxHash.Test", "Standart.Hash.xxHash.Test\Standart.Hash.xxHash.Test.csproj", "{0D9506CC-A6A1-4C0C-8827-9AB958942895}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{E468CD00-D581-46DD-ADE6-71EFA74AD62E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E468CD00-D581-46DD-ADE6-71EFA74AD62E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E468CD00-D581-46DD-ADE6-71EFA74AD62E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E468CD00-D581-46DD-ADE6-71EFA74AD62E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B80269B-1EC4-40B5-8E19-F0A68C4404E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7B80269B-1EC4-40B5-8E19-F0A68C4404E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7B80269B-1EC4-40B5-8E19-F0A68C4404E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B80269B-1EC4-40B5-8E19-F0A68C4404E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{0D9506CC-A6A1-4C0C-8827-9AB958942895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0D9506CC-A6A1-4C0C-8827-9AB958942895}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0D9506CC-A6A1-4C0C-8827-9AB958942895}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0D9506CC-A6A1-4C0C-8827-9AB958942895}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<Import Project="..\..\nuget.props" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<InternalsVisibleTo Include="$(AssemblyName).Test" />
|
|
||||||
<InternalsVisibleTo Include="$(AssemblyName).Perf" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,179 +0,0 @@
|
|||||||
/*
|
|
||||||
* This is the auto generated code.
|
|
||||||
* All function calls are inlined in XXH32
|
|
||||||
* Please don't try to analyze it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash;
|
|
||||||
|
|
||||||
public partial class xxHash32
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe uint __inline__XXH32(byte* input, int len, uint seed)
|
|
||||||
{
|
|
||||||
uint h32;
|
|
||||||
|
|
||||||
if (len >= 16)
|
|
||||||
{
|
|
||||||
byte* end = input + len;
|
|
||||||
byte* limit = end - 15;
|
|
||||||
|
|
||||||
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
|
||||||
uint v2 = seed + XXH_PRIME32_2;
|
|
||||||
uint v3 = seed + 0;
|
|
||||||
uint v4 = seed - XXH_PRIME32_1;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// XXH32_round
|
|
||||||
v1 += *((uint*) (input+0)) * XXH_PRIME32_2;
|
|
||||||
v1 = (v1 << 13) | (v1 >> (32 - 13));
|
|
||||||
v1 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
// XXH32_round
|
|
||||||
v2 += *((uint*) (input+4)) * XXH_PRIME32_2;
|
|
||||||
v2 = (v2 << 13) | (v2 >> (32 - 13));
|
|
||||||
v2 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
// XXH32_round
|
|
||||||
v3 += *((uint*) (input+8)) * XXH_PRIME32_2;
|
|
||||||
v3 = (v3 << 13) | (v3 >> (32 - 13));
|
|
||||||
v3 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
// XXH32_round
|
|
||||||
v4 += *((uint*) (input+12)) * XXH_PRIME32_2;
|
|
||||||
v4 = (v4 << 13) | (v4 >> (32 - 13));
|
|
||||||
v4 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
input += 16;
|
|
||||||
} while (input < limit);
|
|
||||||
|
|
||||||
h32 = ((v1 << 1) | (v1 >> (32 - 1))) +
|
|
||||||
((v2 << 7) | (v2 >> (32 - 7))) +
|
|
||||||
((v3 << 12) | (v3 >> (32 - 12))) +
|
|
||||||
((v4 << 18) | (v4 >> (32 - 18)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h32 = seed + XXH_PRIME32_5;
|
|
||||||
}
|
|
||||||
|
|
||||||
h32 += (uint) len;
|
|
||||||
|
|
||||||
// XXH32_finalize
|
|
||||||
len &= 15;
|
|
||||||
while (len >= 4)
|
|
||||||
{
|
|
||||||
h32 += *((uint*) input) * XXH_PRIME32_3;
|
|
||||||
input += 4;
|
|
||||||
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * XXH_PRIME32_4;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len > 0)
|
|
||||||
{
|
|
||||||
h32 += *((byte*) input) * XXH_PRIME32_5;
|
|
||||||
++input;
|
|
||||||
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * XXH_PRIME32_1;
|
|
||||||
--len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXH32_avalanche
|
|
||||||
h32 ^= h32 >> 15;
|
|
||||||
h32 *= XXH_PRIME32_2;
|
|
||||||
h32 ^= h32 >> 13;
|
|
||||||
h32 *= XXH_PRIME32_3;
|
|
||||||
h32 ^= h32 >> 16;
|
|
||||||
|
|
||||||
return h32;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe void __inline__XXH32_stream_process(byte[] input, int len, ref uint v1, ref uint v2, ref uint v3, ref uint v4)
|
|
||||||
{
|
|
||||||
fixed (byte* pData = &input[0])
|
|
||||||
{
|
|
||||||
byte* ptr = pData;
|
|
||||||
byte* limit = ptr + len;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// XXH32_round
|
|
||||||
v1 += *((uint*)(ptr + 0)) * XXH_PRIME32_2;
|
|
||||||
v1 = (v1 << 13) | (v1 >> (32 - 13));
|
|
||||||
v1 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
// XXH32_round
|
|
||||||
v2 += *((uint*)(ptr + 4)) * XXH_PRIME32_2;
|
|
||||||
v2 = (v2 << 13) | (v2 >> (32 - 13));
|
|
||||||
v2 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
// XXH32_round
|
|
||||||
v3 += *((uint*)(ptr + 8)) * XXH_PRIME32_2;
|
|
||||||
v3 = (v3 << 13) | (v3 >> (32 - 13));
|
|
||||||
v3 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
// XXH32_round
|
|
||||||
v4 += *((uint*)(ptr + 12)) * XXH_PRIME32_2;
|
|
||||||
v4 = (v4 << 13) | (v4 >> (32 - 13));
|
|
||||||
v4 *= XXH_PRIME32_1;
|
|
||||||
|
|
||||||
ptr += 16;
|
|
||||||
|
|
||||||
} while (ptr < limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe uint __inline__XXH32_stream_finalize(byte[] input, int len, ref uint v1, ref uint v2, ref uint v3, ref uint v4, long length, uint seed)
|
|
||||||
{
|
|
||||||
fixed (byte* pData = &input[0])
|
|
||||||
{
|
|
||||||
byte* ptr = pData;
|
|
||||||
uint h32;
|
|
||||||
|
|
||||||
if (length >= 16)
|
|
||||||
{
|
|
||||||
h32 = ((v1 << 1) | (v1 >> (32 - 1))) +
|
|
||||||
((v2 << 7) | (v2 >> (32 - 7))) +
|
|
||||||
((v3 << 12) | (v3 >> (32 - 12))) +
|
|
||||||
((v4 << 18) | (v4 >> (32 - 18)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h32 = seed + XXH_PRIME32_5;
|
|
||||||
}
|
|
||||||
|
|
||||||
h32 += (uint)length;
|
|
||||||
|
|
||||||
// XXH32_finalize
|
|
||||||
len &= 15;
|
|
||||||
while (len >= 4)
|
|
||||||
{
|
|
||||||
h32 += *((uint*)ptr) * XXH_PRIME32_3;
|
|
||||||
ptr += 4;
|
|
||||||
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * XXH_PRIME32_4;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len > 0)
|
|
||||||
{
|
|
||||||
h32 += *((byte*)ptr) * XXH_PRIME32_5;
|
|
||||||
ptr++;
|
|
||||||
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * XXH_PRIME32_1;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXH32_avalanche
|
|
||||||
h32 ^= h32 >> 15;
|
|
||||||
h32 *= XXH_PRIME32_2;
|
|
||||||
h32 ^= h32 >> 13;
|
|
||||||
h32 *= XXH_PRIME32_3;
|
|
||||||
h32 ^= h32 >> 16;
|
|
||||||
|
|
||||||
return h32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
/*
|
|
||||||
* This is the auto generated code.
|
|
||||||
* All function calls are inlined in XXH64
|
|
||||||
* Please don't try to analyze it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash;
|
|
||||||
|
|
||||||
public partial class xxHash64
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe ulong __inline__XXH64(byte* input, int len, ulong seed)
|
|
||||||
{
|
|
||||||
ulong h64;
|
|
||||||
|
|
||||||
if (len >= 32)
|
|
||||||
{
|
|
||||||
byte* end = input + len;
|
|
||||||
byte* limit = end - 31;
|
|
||||||
|
|
||||||
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
|
||||||
ulong v2 = seed + XXH_PRIME64_2;
|
|
||||||
ulong v3 = seed + 0;
|
|
||||||
ulong v4 = seed - XXH_PRIME64_1;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// XXH64_round
|
|
||||||
v1 += *((ulong*) input) * XXH_PRIME64_2;
|
|
||||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
|
||||||
v1 *= XXH_PRIME64_1;
|
|
||||||
input += 8;
|
|
||||||
|
|
||||||
// XXH64_round
|
|
||||||
v2 += *((ulong*) input) * XXH_PRIME64_2;
|
|
||||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
|
||||||
v2 *= XXH_PRIME64_1;
|
|
||||||
input += 8;
|
|
||||||
|
|
||||||
// XXH64_round
|
|
||||||
v3 += *((ulong*) input) * XXH_PRIME64_2;
|
|
||||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
|
||||||
v3 *= XXH_PRIME64_1;
|
|
||||||
input += 8;
|
|
||||||
|
|
||||||
// XXH64_round
|
|
||||||
v4 += *((ulong*) input) * XXH_PRIME64_2;
|
|
||||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
|
||||||
v4 *= XXH_PRIME64_1;
|
|
||||||
input += 8;
|
|
||||||
} while (input < limit);
|
|
||||||
|
|
||||||
h64 = ((v1 << 1) | (v1 >> (64 - 1))) +
|
|
||||||
((v2 << 7) | (v2 >> (64 - 7))) +
|
|
||||||
((v3 << 12) | (v3 >> (64 - 12))) +
|
|
||||||
((v4 << 18) | (v4 >> (64 - 18)));
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v1 *= XXH_PRIME64_2;
|
|
||||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
|
||||||
v1 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v1;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v2 *= XXH_PRIME64_2;
|
|
||||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
|
||||||
v2 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v2;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v3 *= XXH_PRIME64_2;
|
|
||||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
|
||||||
v3 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v3;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v4 *= XXH_PRIME64_2;
|
|
||||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
|
||||||
v4 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v4;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h64 = seed + XXH_PRIME64_5;
|
|
||||||
}
|
|
||||||
|
|
||||||
h64 += (ulong) len;
|
|
||||||
|
|
||||||
// XXH64_finalize
|
|
||||||
len &= 31;
|
|
||||||
while (len >= 8) {
|
|
||||||
ulong k1 = XXH64_round(0, *(ulong*)input);
|
|
||||||
input += 8;
|
|
||||||
h64 ^= k1;
|
|
||||||
h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
len -= 8;
|
|
||||||
}
|
|
||||||
if (len >= 4) {
|
|
||||||
h64 ^= *(uint*)input * XXH_PRIME64_1;
|
|
||||||
input += 4;
|
|
||||||
h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
while (len > 0) {
|
|
||||||
h64 ^= (*input++) * XXH_PRIME64_5;
|
|
||||||
h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1;
|
|
||||||
--len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXH64_avalanche
|
|
||||||
h64 ^= h64 >> 33;
|
|
||||||
h64 *= XXH_PRIME64_2;
|
|
||||||
h64 ^= h64 >> 29;
|
|
||||||
h64 *= XXH_PRIME64_3;
|
|
||||||
h64 ^= h64 >> 32;
|
|
||||||
|
|
||||||
return h64;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe void __inline__XXH64_stream_process(byte[] input, int len, ref ulong v1, ref ulong v2, ref ulong v3,
|
|
||||||
ref ulong v4)
|
|
||||||
{
|
|
||||||
fixed (byte* pData = &input[0])
|
|
||||||
{
|
|
||||||
byte* ptr = pData;
|
|
||||||
byte* limit = ptr + len;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// XXH64_round
|
|
||||||
v1 += *((ulong*) ptr) * XXH_PRIME64_2;
|
|
||||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
|
||||||
v1 *= XXH_PRIME64_1;
|
|
||||||
ptr += 8;
|
|
||||||
|
|
||||||
// XXH64_round
|
|
||||||
v2 += *((ulong*) ptr) * XXH_PRIME64_2;
|
|
||||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
|
||||||
v2 *= XXH_PRIME64_1;
|
|
||||||
ptr += 8;
|
|
||||||
|
|
||||||
// XXH64_round
|
|
||||||
v3 += *((ulong*) ptr) * XXH_PRIME64_2;
|
|
||||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
|
||||||
v3 *= XXH_PRIME64_1;
|
|
||||||
ptr += 8;
|
|
||||||
|
|
||||||
// XXH64_round
|
|
||||||
v4 += *((ulong*) ptr) * XXH_PRIME64_2;
|
|
||||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
|
||||||
v4 *= XXH_PRIME64_1;
|
|
||||||
ptr += 8;
|
|
||||||
} while (ptr < limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe ulong __inline__XXH64_stream_finalize(byte[] input, int len, ref ulong v1, ref ulong v2, ref ulong v3,
|
|
||||||
ref ulong v4, long length, ulong seed)
|
|
||||||
{
|
|
||||||
fixed (byte* pData = &input[0])
|
|
||||||
{
|
|
||||||
byte* ptr = pData;
|
|
||||||
byte* end = pData + len;
|
|
||||||
ulong h64;
|
|
||||||
|
|
||||||
if (length >= 32)
|
|
||||||
{
|
|
||||||
h64 = ((v1 << 1) | (v1 >> (64 - 1))) +
|
|
||||||
((v2 << 7) | (v2 >> (64 - 7))) +
|
|
||||||
((v3 << 12) | (v3 >> (64 - 12))) +
|
|
||||||
((v4 << 18) | (v4 >> (64 - 18)));
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v1 *= XXH_PRIME64_2;
|
|
||||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
|
||||||
v1 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v1;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v2 *= XXH_PRIME64_2;
|
|
||||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
|
||||||
v2 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v2;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v3 *= XXH_PRIME64_2;
|
|
||||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
|
||||||
v3 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v3;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
|
|
||||||
// XXH64_mergeRound
|
|
||||||
v4 *= XXH_PRIME64_2;
|
|
||||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
|
||||||
v4 *= XXH_PRIME64_1;
|
|
||||||
h64 ^= v4;
|
|
||||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h64 = seed + XXH_PRIME64_5;
|
|
||||||
}
|
|
||||||
|
|
||||||
h64 += (ulong) length;
|
|
||||||
|
|
||||||
// XXH64_finalize
|
|
||||||
len &= 31;
|
|
||||||
while (len >= 8) {
|
|
||||||
ulong k1 = XXH64_round(0, *(ulong*)ptr);
|
|
||||||
ptr += 8;
|
|
||||||
h64 ^= k1;
|
|
||||||
h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
||||||
len -= 8;
|
|
||||||
}
|
|
||||||
if (len >= 4) {
|
|
||||||
h64 ^= *(uint*)ptr * XXH_PRIME64_1;
|
|
||||||
ptr += 4;
|
|
||||||
h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
while (len > 0) {
|
|
||||||
h64 ^= (*ptr++) * XXH_PRIME64_5;
|
|
||||||
h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1;
|
|
||||||
--len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXH64_avalanche
|
|
||||||
h64 ^= h64 >> 33;
|
|
||||||
h64 *= XXH_PRIME64_2;
|
|
||||||
h64 ^= h64 >> 29;
|
|
||||||
h64 *= XXH_PRIME64_3;
|
|
||||||
h64 ^= h64 >> 32;
|
|
||||||
|
|
||||||
return h64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash;
|
|
||||||
|
|
||||||
public static partial class xxHash32
|
|
||||||
{
|
|
||||||
private const uint XXH_PRIME32_1 = 2654435761U;
|
|
||||||
private const uint XXH_PRIME32_2 = 2246822519U;
|
|
||||||
private const uint XXH_PRIME32_3 = 3266489917U;
|
|
||||||
private const uint XXH_PRIME32_4 = 668265263U;
|
|
||||||
private const uint XXH_PRIME32_5 = 374761393U;
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static uint XXH_rotl32(uint x, int r)
|
|
||||||
{
|
|
||||||
return (x << r) | (x >> (32 - r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash;
|
|
||||||
|
|
||||||
public static partial class xxHash32
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the data byte array
|
|
||||||
/// </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(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the data byte array
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The source of data</param>
|
|
||||||
/// <param name="offset">The offset of the data for hashing</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(byte[] data, int offset, int length, uint seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(data != null);
|
|
||||||
Debug.Assert(length >= 0);
|
|
||||||
Debug.Assert(offset < data.Length);
|
|
||||||
Debug.Assert(length <= data.Length - offset);
|
|
||||||
|
|
||||||
fixed (byte* pData = &data[0 + offset])
|
|
||||||
{
|
|
||||||
return UnsafeComputeHash(pData, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the data byte array
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The source of data</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <returns>hash</returns>
|
|
||||||
public static ulong ComputeHash(ArraySegment<byte> data, uint seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(data != null);
|
|
||||||
|
|
||||||
return ComputeHash(data.Array, data.Offset, data.Count, seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the async stream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream of data</param>
|
|
||||||
/// <param name="bufferSize">The buffer size</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <returns>The hash</returns>
|
|
||||||
public static async ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize = 4096, uint seed = 0)
|
|
||||||
{
|
|
||||||
return await ComputeHashAsync(stream, bufferSize, seed, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the async stream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream of data</param>
|
|
||||||
/// <param name="bufferSize">The buffer size</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token</param>
|
|
||||||
/// <returns>The hash</returns>
|
|
||||||
public static async ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize, uint seed, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Debug.Assert(stream != null);
|
|
||||||
Debug.Assert(bufferSize > 16);
|
|
||||||
|
|
||||||
// Optimizing memory allocation
|
|
||||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 16);
|
|
||||||
|
|
||||||
int readBytes;
|
|
||||||
int offset = 0;
|
|
||||||
long length = 0;
|
|
||||||
|
|
||||||
// Prepare the seed vector
|
|
||||||
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
|
||||||
uint v2 = seed + XXH_PRIME32_2;
|
|
||||||
uint v3 = seed + 0;
|
|
||||||
uint v4 = seed - XXH_PRIME32_1;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Read flow of bytes
|
|
||||||
while ((readBytes =
|
|
||||||
await stream.ReadAsync(buffer, offset, bufferSize, cancellationToken).ConfigureAwait(false)) > 0)
|
|
||||||
{
|
|
||||||
length = length + readBytes;
|
|
||||||
offset = offset + readBytes;
|
|
||||||
|
|
||||||
if (offset < 16) continue;
|
|
||||||
|
|
||||||
int r = offset % 16; // remain
|
|
||||||
int l = offset - r; // length
|
|
||||||
|
|
||||||
// Process the next chunk
|
|
||||||
__inline__XXH32_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
|
||||||
|
|
||||||
// Put remaining bytes to buffer
|
|
||||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
|
||||||
offset = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the final chunk
|
|
||||||
uint h32 = __inline__XXH32_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
|
||||||
|
|
||||||
return h32;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Free memory
|
|
||||||
ArrayPool<byte>.Shared.Return(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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 = &MemoryMarshal.GetReference(data))
|
|
||||||
{
|
|
||||||
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(ReadOnlySpan<byte> data, int length, uint seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(data != null);
|
|
||||||
Debug.Assert(length >= 0);
|
|
||||||
Debug.Assert(length <= data.Length);
|
|
||||||
|
|
||||||
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
|
||||||
{
|
|
||||||
return UnsafeComputeHash(pData, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the stream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream of data</param>
|
|
||||||
/// <param name="bufferSize">The buffer size</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <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);
|
|
||||||
|
|
||||||
int readBytes;
|
|
||||||
int offset = 0;
|
|
||||||
long length = 0;
|
|
||||||
|
|
||||||
// Prepare the seed vector
|
|
||||||
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
|
||||||
uint v2 = seed + XXH_PRIME32_2;
|
|
||||||
uint v3 = seed + 0;
|
|
||||||
uint v4 = seed - XXH_PRIME32_1;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Read flow of bytes
|
|
||||||
while ((readBytes = stream.Read(buffer, offset, bufferSize)) > 0)
|
|
||||||
{
|
|
||||||
length = length + readBytes;
|
|
||||||
offset = offset + readBytes;
|
|
||||||
|
|
||||||
if (offset < 16) continue;
|
|
||||||
|
|
||||||
int r = offset % 16; // remain
|
|
||||||
int l = offset - r; // length
|
|
||||||
|
|
||||||
// Process the next chunk
|
|
||||||
__inline__XXH32_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
|
||||||
|
|
||||||
// Put remaining bytes to buffer
|
|
||||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
|
||||||
offset = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the last chunk
|
|
||||||
uint h32 = __inline__XXH32_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
|
||||||
|
|
||||||
return h32;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Free memory
|
|
||||||
ArrayPool<byte>.Shared.Return(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the string
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="str">The source of data</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <returns>hash</returns>
|
|
||||||
public static unsafe uint ComputeHash(string str, uint seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(str != null);
|
|
||||||
|
|
||||||
fixed (char* c = str)
|
|
||||||
{
|
|
||||||
byte* ptr = (byte*) c;
|
|
||||||
int length = str.Length * 2;
|
|
||||||
|
|
||||||
return UnsafeComputeHash(ptr, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe uint UnsafeComputeHash(byte* ptr, int length, uint seed)
|
|
||||||
{
|
|
||||||
// Use inlined version
|
|
||||||
// return XXH32(ptr, length, seed);
|
|
||||||
|
|
||||||
return __inline__XXH32(ptr, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash;
|
|
||||||
|
|
||||||
public static partial class xxHash64
|
|
||||||
{
|
|
||||||
private const ulong XXH_PRIME64_1 = 11400714785074694791UL;
|
|
||||||
private const ulong XXH_PRIME64_2 = 14029467366897019727UL;
|
|
||||||
private const ulong XXH_PRIME64_3 = 1609587929392839161UL;
|
|
||||||
private const ulong XXH_PRIME64_4 = 9650029242287828579UL;
|
|
||||||
private const ulong XXH_PRIME64_5 = 2870177450012600261UL;
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static ulong XXH_rotl64(ulong x, int r)
|
|
||||||
{
|
|
||||||
return (x << r) | (x >> (64 - r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
// ReSharper disable InconsistentNaming
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Standart.Hash.xxHash;
|
|
||||||
|
|
||||||
public static partial class xxHash64
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the data byte array
|
|
||||||
/// </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(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the data byte array
|
|
||||||
/// </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(byte[] data, int offset, int length, ulong seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(data != null);
|
|
||||||
Debug.Assert(length >= 0);
|
|
||||||
Debug.Assert(offset < data.Length);
|
|
||||||
Debug.Assert(length <= data.Length - offset);
|
|
||||||
|
|
||||||
fixed (byte* pData = &data[0 + offset])
|
|
||||||
{
|
|
||||||
return UnsafeComputeHash(pData, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the data byte array
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The source of data</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <returns>hash</returns>
|
|
||||||
public static unsafe ulong ComputeHash(System.ArraySegment<byte> data, ulong seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(data != null);
|
|
||||||
|
|
||||||
return ComputeHash(data.Array, data.Offset, data.Count, seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the async stream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream of data</param>
|
|
||||||
/// <param name="bufferSize">The buffer size</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <returns>The hash</returns>
|
|
||||||
public static async ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize = 8192, ulong seed = 0)
|
|
||||||
{
|
|
||||||
return await ComputeHashAsync(stream, bufferSize, seed, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the async stream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream of data</param>
|
|
||||||
/// <param name="bufferSize">The buffer size</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <param name="cancellationToken">The cancelation token</param>
|
|
||||||
/// <returns>The hash</returns>
|
|
||||||
public static async ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize, ulong seed,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
Debug.Assert(stream != null);
|
|
||||||
Debug.Assert(bufferSize > 32);
|
|
||||||
|
|
||||||
// Optimizing memory allocation
|
|
||||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 32);
|
|
||||||
|
|
||||||
int readBytes;
|
|
||||||
int offset = 0;
|
|
||||||
long length = 0;
|
|
||||||
|
|
||||||
// Prepare the seed vector
|
|
||||||
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
|
||||||
ulong v2 = seed + XXH_PRIME64_2;
|
|
||||||
ulong v3 = seed + 0;
|
|
||||||
ulong v4 = seed - XXH_PRIME64_1;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Read flow of bytes
|
|
||||||
while ((readBytes =
|
|
||||||
await stream.ReadAsync(buffer, offset, bufferSize, cancellationToken).ConfigureAwait(false)) > 0)
|
|
||||||
{
|
|
||||||
length = length + readBytes;
|
|
||||||
offset = offset + readBytes;
|
|
||||||
|
|
||||||
if (offset < 32) continue;
|
|
||||||
|
|
||||||
int r = offset % 32; // remain
|
|
||||||
int l = offset - r; // length
|
|
||||||
|
|
||||||
// Process the next chunk
|
|
||||||
__inline__XXH64_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
|
||||||
|
|
||||||
// Put remaining bytes to buffer
|
|
||||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
|
||||||
offset = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the final chunk
|
|
||||||
ulong h64 = __inline__XXH64_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
|
||||||
|
|
||||||
return h64;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Free memory
|
|
||||||
ArrayPool<byte>.Shared.Return(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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 = &MemoryMarshal.GetReference(data))
|
|
||||||
{
|
|
||||||
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(ReadOnlySpan<byte> data, int length, ulong seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(data != null);
|
|
||||||
Debug.Assert(length >= 0);
|
|
||||||
Debug.Assert(length <= data.Length);
|
|
||||||
|
|
||||||
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
|
||||||
{
|
|
||||||
return UnsafeComputeHash(pData, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the stream
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream of data</param>
|
|
||||||
/// <param name="bufferSize">The buffer size</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <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);
|
|
||||||
|
|
||||||
int readBytes;
|
|
||||||
int offset = 0;
|
|
||||||
long length = 0;
|
|
||||||
|
|
||||||
// Prepare the seed vector
|
|
||||||
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
|
||||||
ulong v2 = seed + XXH_PRIME64_2;
|
|
||||||
ulong v3 = seed + 0;
|
|
||||||
ulong v4 = seed - XXH_PRIME64_1;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Read flow of bytes
|
|
||||||
while ((readBytes = stream.Read(buffer, offset, bufferSize)) > 0)
|
|
||||||
{
|
|
||||||
length = length + readBytes;
|
|
||||||
offset = offset + readBytes;
|
|
||||||
|
|
||||||
if (offset < 32) continue;
|
|
||||||
|
|
||||||
int r = offset % 32; // remain
|
|
||||||
int l = offset - r; // length
|
|
||||||
|
|
||||||
// Process the next chunk
|
|
||||||
__inline__XXH64_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
|
||||||
|
|
||||||
// Put remaining bytes to buffer
|
|
||||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
|
||||||
offset = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the final chunk
|
|
||||||
ulong h64 = __inline__XXH64_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
|
||||||
|
|
||||||
return h64;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Free memory
|
|
||||||
ArrayPool<byte>.Shared.Return(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compute xxHash for the string
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="str">The source of data</param>
|
|
||||||
/// <param name="seed">The seed number</param>
|
|
||||||
/// <returns>hash</returns>
|
|
||||||
public static unsafe ulong ComputeHash(string str, uint seed = 0)
|
|
||||||
{
|
|
||||||
Debug.Assert(str != null);
|
|
||||||
|
|
||||||
fixed (char* c = str)
|
|
||||||
{
|
|
||||||
byte* ptr = (byte*) c;
|
|
||||||
int length = str.Length * 2;
|
|
||||||
|
|
||||||
return UnsafeComputeHash(ptr, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe ulong UnsafeComputeHash(byte* ptr, int length, ulong seed)
|
|
||||||
{
|
|
||||||
// Use inlined version
|
|
||||||
// return XXH64(ptr, length, seed);
|
|
||||||
|
|
||||||
return __inline__XXH64(ptr, length, seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user