Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions src/Phf.Net/PerfectHashFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class PerfectHashFunction

public uint DisplacementMax { get; set; } /* maximum displacement value in g */

public static PerfectHashFunction Create(string[] keys, PhfSettings settings)
public static PerfectHashFunction Create(ReadOnlyMemory<Byte>[] keys, PhfSettings settings)
{
var keysLengthNormalized = Math.Max((uint) keys.Length, 1); /* for computations that require n > 0 */
var itemsPerBucketNormalized = Math.Max(settings.ItemsPerBucket, 1);
Expand Down Expand Up @@ -45,7 +45,7 @@ public static PerfectHashFunction Create(string[] keys, PhfSettings settings)
var seed = settings.Seed;
for (uint i = 0; i < (uint) keys.Length; i++)
{
var idx = Phf_g_mod_r(keys[i], seed, numberOfBuckets, noDivision);
var idx = Phf_g_mod_r(keys[i].Span, seed, numberOfBuckets, noDivision);

bucketSlots[i].Key = keys[i];
bucketSlots[i].G = idx;
Expand All @@ -70,13 +70,13 @@ public static PerfectHashFunction Create(string[] keys, PhfSettings settings)
var delta = bucketSize[bucketSlots[i].G];
for (var j = i; j < i + delta; j++)
{
f = Phf_f_mod_m(displacement, bucketSlots[j].Key, seed, outputArraySize, noDivision);
f = Phf_f_mod_m(displacement, bucketSlots[j].Key.Span, seed, outputArraySize, noDivision);
if (PhfIsSet(bitmap, f) || PhfIsSet(bitmapWorking, f))
{
/* reset bitmapWorking[] */
for (j = i; j < i + delta; j++)
{
f = Phf_f_mod_m(displacement, bucketSlots[j].Key, seed, outputArraySize, noDivision);
f = Phf_f_mod_m(displacement, bucketSlots[j].Key.Span, seed, outputArraySize, noDivision);
PhfClearBit(bitmapWorking, f);
}

Expand All @@ -89,7 +89,7 @@ public static PerfectHashFunction Create(string[] keys, PhfSettings settings)
/* commit to bitmap[] */
for (var j = i; j < i + bucketSize[bucketSlots[i].G]; j++)
{
f = Phf_f_mod_m(displacement, bucketSlots[j].Key, seed, outputArraySize, noDivision);
f = Phf_f_mod_m(displacement, bucketSlots[j].Key.Span, seed, outputArraySize, noDivision);
PhfSetBit(bitmap, f);
}

Expand All @@ -106,12 +106,12 @@ public static PerfectHashFunction Create(string[] keys, PhfSettings settings)
return phf;
}

public uint Evaluate(string key)
public uint Evaluate(ReadOnlySpan<Byte> key)
{
return PhfHash(DisplacementMap, key, Seed, OutputArraySize, NoDivision);
}

private static uint PhfHash(uint[] g, string k, uint seed, uint m, bool noDivision)
private static uint PhfHash(uint[] g, ReadOnlySpan<Byte> k, uint seed, uint m, bool noDivision)
{
if (noDivision)
{
Expand Down Expand Up @@ -140,12 +140,12 @@ private static bool PhfIsSet(ulong[] set, uint i)
return (set[i / 64] & (1UL << (int)(i % 64))) != 0;
}

private static uint Phf_f_mod_m(uint d, string k, uint seed, uint m, bool noDivision)
private static uint Phf_f_mod_m(uint d, ReadOnlySpan<Byte> k, uint seed, uint m, bool noDivision)
{
return noDivision ? Phf_f(d, k, seed) & (m - 1) : Phf_f(d, k, seed) % m;
}

private static uint Phf_f(uint d, string k, uint seed)
private static uint Phf_f(uint d, ReadOnlySpan<Byte> k, uint seed)
{
uint h1 = seed;

Expand All @@ -160,12 +160,12 @@ private static uint PhfHowMany(uint x, uint y)
return (x + (y - 1)) / y;
}

private static uint Phf_g_mod_r(string k, uint seed, uint r, bool noDivision)
private static uint Phf_g_mod_r(ReadOnlySpan<Byte> k, uint seed, uint r, bool noDivision)
{
return noDivision ? Phf_g(k, seed) & (r - 1) : Phf_g(k, seed) % r;
}

private static uint Phf_g(string k, uint seed)
private static uint Phf_g(ReadOnlySpan<Byte> k, uint seed)
{
uint h1 = seed;

Expand All @@ -185,7 +185,7 @@ private static uint PhfMix32(uint h1)
return h1;
}

private static uint PhfRound32(string s, uint h1)
private static uint PhfRound32(ReadOnlySpan<Byte> s, uint h1)
{
uint k1;
uint n = (uint)s.Length;
Expand Down
6 changes: 5 additions & 1 deletion src/Phf.Net/Phf.Net.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard1.0</TargetFramework>
<TargetFramework>netstandard1.1</TargetFramework>
<LangVersion>7.3</LangVersion>
<RootNamespace>Phf.Net</RootNamespace>
</PropertyGroup>
Expand All @@ -27,4 +27,8 @@
<None Include="../../README.md" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.3" />
</ItemGroup>

</Project>
4 changes: 3 additions & 1 deletion src/Phf.Net/PhfKey.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;

namespace Phf.Net
{
public struct PhfKey
{
public string Key;
public ReadOnlyMemory<Byte> Key;

public uint G; /* result of g(k) % r */

Expand Down
8 changes: 5 additions & 3 deletions tests/Phf.Net.Tests/PerfectHashFunctionTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Linq;
using System;
using System.Linq;
using System.Text;
using FluentAssertions;
using Xunit;

Expand All @@ -12,11 +14,11 @@ public void SmokeTest(
[CombinatorialValues(80, 100)] uint alpha,
bool noDivision)
{
var strings = Enumerable.Range(0, count).Select(x => $"str{x}").ToArray();
var strings = Enumerable.Range(0, count).Select(x => (ReadOnlyMemory<Byte>) Encoding.UTF8.GetBytes($"str{x}")).ToArray();
var settings = new PhfSettings {Alpha = alpha, NoDivision = noDivision, ItemsPerBucket = 4, Seed = 31337};

var function = PerfectHashFunction.Create(strings, settings);
var ids = strings.Select(x => function.Evaluate(x)).Distinct().ToArray();
var ids = strings.Select(x => function.Evaluate(x.Span)).Distinct().ToArray();

ids.Length.Should().Be(strings.Length);
ids.All(x => x < function.OutputArraySize).Should().BeTrue();
Expand Down