Add tests for xxHash128
This commit is contained in:
parent
8d6f7fa43b
commit
c079a400a0
@ -35,5 +35,50 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_convert_to_bytes()
|
||||
{
|
||||
var hash = new uint128
|
||||
{
|
||||
high64 = 3466251221427321594,
|
||||
low64 = 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 actual = hash.ToBytes();
|
||||
|
||||
// Assert
|
||||
for (int i = 0; i < 16; i++)
|
||||
Assert.Equal(expected[i], actual[i]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_convert_to_guid()
|
||||
{
|
||||
var hash = new uint128
|
||||
{
|
||||
high64 = 3466251221427321594,
|
||||
low64 = 2862260537881727713
|
||||
};
|
||||
|
||||
// Act
|
||||
var guid1 = new Guid(hash.ToBytes());
|
||||
var guid2 = hash.ToGuid();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(guid1, guid2);
|
||||
}
|
||||
}
|
||||
}
|
||||
113
src/Standart.Hash.xxHash.Test/xxHash128Test.cs
Normal file
113
src/Standart.Hash.xxHash.Test/xxHash128Test.cs
Normal file
@ -0,0 +1,113 @@
|
||||
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,4 +1,6 @@
|
||||
namespace Standart.Hash.xxHash.Test
|
||||
using System.Text;
|
||||
|
||||
namespace Standart.Hash.xxHash.Test
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
@ -420,5 +422,20 @@
|
||||
Assert.Equal(hash1, hash2);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compute_hash32_for_string()
|
||||
{
|
||||
// Arrange
|
||||
var str = "veni vidi vici";
|
||||
var bytes = Encoding.Unicode.GetBytes(str);
|
||||
|
||||
// Act
|
||||
var hash1 = xxHash32.ComputeHash(str);
|
||||
var hash2 = xxHash32.ComputeHash(bytes, bytes.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash1, hash2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
namespace Standart.Hash.xxHash.Test
|
||||
using System.Text;
|
||||
|
||||
namespace Standart.Hash.xxHash.Test
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
@ -383,5 +385,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compute_hash64_for_string()
|
||||
{
|
||||
// Arrange
|
||||
var str = "veni vidi vici";
|
||||
var bytes = Encoding.Unicode.GetBytes(str);
|
||||
|
||||
// Act
|
||||
var hash1 = xxHash64.ComputeHash(str);
|
||||
var hash2 = xxHash64.ComputeHash(bytes, bytes.Length);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash1, hash2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,16 +8,28 @@ namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static Guid ToGuid(this uint128 value)
|
||||
{
|
||||
// allocation
|
||||
return new Guid(value.ToBytes());
|
||||
var a = (Int32) (value.low64);
|
||||
var b = (Int16) (value.low64 >> 32);
|
||||
var c = (Int16) (value.low64 >> 48);
|
||||
|
||||
var d = (Byte) (value.high64);
|
||||
var e = (Byte) (value.high64 >> 8);
|
||||
var f = (Byte) (value.high64 >> 16);
|
||||
var g = (Byte) (value.high64 >> 24);
|
||||
var h = (Byte) (value.high64 >> 32);
|
||||
var i = (Byte) (value.high64 >> 40);
|
||||
var j = (Byte) (value.high64 >> 48);
|
||||
var k = (Byte) (value.high64 >> 56);
|
||||
|
||||
return new Guid(a, b, c, d, e, f,g, h, i, j, k);
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this uint128 value)
|
||||
{
|
||||
// allocation
|
||||
byte[] bytes = new byte[sizeof(ulong) * 2];
|
||||
Unsafe.As<byte, ulong>(ref bytes[0]) = value.high64;
|
||||
Unsafe.As<byte, ulong>(ref bytes[8]) = value.low64;
|
||||
Unsafe.As<byte, ulong>(ref bytes[0]) = value.low64;
|
||||
Unsafe.As<byte, ulong>(ref bytes[8]) = value.high64;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
@ -79,12 +79,88 @@ namespace Standart.Hash.xxHash
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes 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 byte[] ComputeHashBytes(byte[] data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes for the 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 byte[] ComputeHashBytes(Span<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes 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 byte[] ComputeHashBytes(ReadOnlySpan<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes 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 byte[] ComputeHashBytes(string str, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(str != null);
|
||||
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 UnsafeComputeHash(byte* input, int len, ulong seed)
|
||||
{
|
||||
|
||||
@ -248,7 +248,7 @@ public static partial class xxHash32
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ public static partial class xxHash64
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user