diff --git a/include/PerfectHash.h b/include/PerfectHash.h index 2ebb843b..4976e513 100644 --- a/include/PerfectHash.h +++ b/include/PerfectHash.h @@ -1948,6 +1948,11 @@ IsValidSeedMasks( 6, \ DECL_SEED_MASKS(0, 0, 0x1f1f1f1f, 0, 0, 0x1f1f1f1f, 0, 0) \ ) \ + ENTRY( \ + MultiplyRotateR, \ + 3, \ + DECL_SEED_MASKS(0, 0, 0x1f1f, 0, 0, 0, 0, 0) \ + ) \ LAST_ENTRY(Scratch, 3, NO_SEED_MASKS) #define PERFECT_HASH_HASH_FUNCTION_TABLE_ENTRY(ENTRY) \ diff --git a/include/PerfectHashErrors.h b/include/PerfectHashErrors.h index d25d4416..94cccd84 100644 --- a/include/PerfectHashErrors.h +++ b/include/PerfectHashErrors.h @@ -248,6 +248,7 @@ Module Name: // 18 ShiftMultiplyXorShift (3) // 19 ShiftMultiplyXorShift2 (6) // 20 RotateMultiplyXorRotate2 (6) +// 21 MultiplyRotateR (3) // // N.B. The lowest latency hash functions with good solving ability, in order of // ascending latency, are: Crc32RotateX, Crc32RotateXY, Crc32RotateWXYZ. diff --git a/src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd.c b/src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd.c new file mode 100644 index 00000000..54311acb --- /dev/null +++ b/src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd.c @@ -0,0 +1,29 @@ + +DECLARE_INDEX_ROUTINE() +{ + CPHINDEX Index; + CPHDKEY Vertex1; + CPHDKEY Vertex2; + CPHDKEY MaskedLow; + CPHDKEY MaskedHigh; + CPHDKEY DownsizedKey; + + DownsizedKey = DOWNSIZE_KEY(Key); + + Vertex1 = DownsizedKey * SEED1; + Vertex1 = _rotr(Vertex1, SEED3_BYTE1); + + Vertex2 = DownsizedKey * SEED2; + Vertex2 = _rotr(Vertex2, SEED3_BYTE2); + + MaskedLow = Vertex1 & HASH_MASK; + MaskedHigh = Vertex2 & HASH_MASK; + + Vertex1 = TABLE_DATA[MaskedLow]; + Vertex2 = TABLE_DATA[MaskedHigh]; + + Index = (CPHINDEX)((Vertex1 + Vertex2) & INDEX_MASK); + + return Index; +} + diff --git a/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd_CSource_RawCString.h b/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd_CSource_RawCString.h new file mode 100644 index 00000000..e672fdcf --- /dev/null +++ b/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd_CSource_RawCString.h @@ -0,0 +1,59 @@ +// +// Auto-generated. +// + +DECLSPEC_ALIGN(16) +const CHAR CompiledPerfectHashTableChm01IndexMultiplyRotateRAndCSourceRawCStr[] = + "\n" + "//\n" + "// Begin CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd.c.\n" + "//\n" + "\n" + "\n" + "DECLARE_INDEX_ROUTINE()\n" + "{\n" + " CPHINDEX Index;\n" + " CPHDKEY Vertex1;\n" + " CPHDKEY Vertex2;\n" + " CPHDKEY MaskedLow;\n" + " CPHDKEY MaskedHigh;\n" + " CPHDKEY DownsizedKey;\n" + "\n" + " DownsizedKey = DOWNSIZE_KEY(Key);\n" + "\n" + " Vertex1 = DownsizedKey * SEED1;\n" + " Vertex1 = _rotr(Vertex1, SEED3_BYTE1);\n" + "\n" + " Vertex2 = DownsizedKey * SEED2;\n" + " Vertex2 = _rotr(Vertex2, SEED3_BYTE2);\n" + "\n" + " MaskedLow = Vertex1 & HASH_MASK;\n" + " MaskedHigh = Vertex2 & HASH_MASK;\n" + "\n" + " Vertex1 = TABLE_DATA[MaskedLow];\n" + " Vertex2 = TABLE_DATA[MaskedHigh];\n" + "\n" + " Index = (CPHINDEX)((Vertex1 + Vertex2) & INDEX_MASK);\n" + "\n" + " return Index;\n" + "}\n" + "\n" + "\n" + "//\n" + "// End CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd.c.\n" + "//\n" + "\n" +; + +const STRING CompiledPerfectHashTableChm01IndexMultiplyRotateRAndCSourceRawCString = { + sizeof(CompiledPerfectHashTableChm01IndexMultiplyRotateRAndCSourceRawCStr) - sizeof(CHAR), + sizeof(CompiledPerfectHashTableChm01IndexMultiplyRotateRAndCSourceRawCStr), +#ifdef _WIN64 + 0, +#endif + (PCHAR)&CompiledPerfectHashTableChm01IndexMultiplyRotateRAndCSourceRawCStr, +}; + +#ifndef RawCString +#define RawCString (&CompiledPerfectHashTableChm01IndexMultiplyRotateRAndCSourceRawCString) +#endif diff --git a/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h b/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h index 2293c764..d3f67d17 100644 --- a/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h +++ b/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h @@ -18,6 +18,7 @@ #include "CompiledPerfectHashTableChm01IndexShiftMultiplyXorShiftAnd_CSource_RawCString.h" #include "CompiledPerfectHashTableChm01IndexShiftMultiplyXorShift2And_CSource_RawCString.h" #include "CompiledPerfectHashTableChm01IndexRotateMultiplyXorRotate2And_CSource_RawCString.h" +#include "CompiledPerfectHashTableChm01IndexMultiplyRotateRAnd_CSource_RawCString.h" // // Keep this last. diff --git a/src/PerfectHash/PerfectHash.vcxproj b/src/PerfectHash/PerfectHash.vcxproj index abfb0e4d..b90e98f5 100644 --- a/src/PerfectHash/PerfectHash.vcxproj +++ b/src/PerfectHash/PerfectHash.vcxproj @@ -114,6 +114,7 @@ + diff --git a/src/PerfectHash/PerfectHash.vcxproj.filters b/src/PerfectHash/PerfectHash.vcxproj.filters index e957c8f4..33386ebe 100644 --- a/src/PerfectHash/PerfectHash.vcxproj.filters +++ b/src/PerfectHash/PerfectHash.vcxproj.filters @@ -477,6 +477,9 @@ Private Header Files %28Auto-Generated%29 + + Private Header Files %28Auto-Generated%29 + Private Header Files diff --git a/src/PerfectHash/PerfectHashErrors.mc b/src/PerfectHash/PerfectHashErrors.mc index 8df9c6c9..eb538ad4 100644 --- a/src/PerfectHash/PerfectHashErrors.mc +++ b/src/PerfectHash/PerfectHashErrors.mc @@ -194,6 +194,7 @@ Hash Functions: 18 ShiftMultiplyXorShift (3) 19 ShiftMultiplyXorShift2 (6) 20 RotateMultiplyXorRotate2 (6) + 21 MultiplyRotateR (3) N.B. The lowest latency hash functions with good solving ability, in order of ascending latency, are: Crc32RotateX, Crc32RotateXY, Crc32RotateWXYZ. diff --git a/src/PerfectHash/PerfectHashErrors_English.bin b/src/PerfectHash/PerfectHashErrors_English.bin index 5e919119..6a7b65ac 100644 Binary files a/src/PerfectHash/PerfectHashErrors_English.bin and b/src/PerfectHash/PerfectHashErrors_English.bin differ diff --git a/src/PerfectHash/PerfectHashTableHash.c b/src/PerfectHash/PerfectHashTableHash.c index b64ccb0f..1b7b7e13 100644 --- a/src/PerfectHash/PerfectHashTableHash.c +++ b/src/PerfectHash/PerfectHashTableHash.c @@ -2286,4 +2286,100 @@ PerfectHashTableHashShiftMultiplyXorShift2( ); } +_Use_decl_annotations_ +HRESULT +PerfectHashTableSeededHashMultiplyRotateR( + PPERFECT_HASH_TABLE Table, + ULONG Key, + ULONG NumberOfSeeds, + PULONG Seeds, + PULONGLONG Hash + ) +/*++ + +Routine Description: + + Performs a multiply then right rotate. + +Arguments: + + Table - Supplies a pointer to the table for which the hash is being created. + + Key - Supplies the input value to hash. + + NumberOfSeeds - Supplies the number of elements in the Seeds array. + + Seeds - Supplies an array of ULONG seed values. + + Hash - Receives two 32-bit hashes merged into a 64-bit value. + +Return Value: + + S_OK on success. If the two 32-bit hash values are identical, E_FAIL. + +--*/ +{ + ULONG Seed1; + ULONG Seed2; + ULONG_BYTES Seed3; + ULONG Vertex1; + ULONG Vertex2; + ULONG DownsizedKey; + ULARGE_INTEGER Result; + + UNREFERENCED_PARAMETER(Table); + + ASSERT(NumberOfSeeds >= 3); + UNREFERENCED_PARAMETER(NumberOfSeeds); + + // + // Initialize aliases. + // + + Seed1 = Seeds[0]; + Seed2 = Seeds[1]; + Seed3.AsULong = Seeds[2]; + DownsizedKey = Key; + + // + // Calculate the individual hash parts. + // + + Vertex1 = DownsizedKey * SEED1; + Vertex1 = _rotr(Vertex1, SEED3_BYTE1); + + Vertex2 = DownsizedKey * SEED2; + Vertex2 = _rotr(Vertex2, SEED3_BYTE2); + + if (Vertex1 == Vertex2) { + return E_FAIL; + } + + Result.LowPart = Vertex1; + Result.HighPart = Vertex2; + + *Hash = Result.QuadPart; + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT +PerfectHashTableHashMultiplyRotateR( + PPERFECT_HASH_TABLE Table, + ULONG Key, + PULONGLONG Hash + ) +{ + PTABLE_INFO_ON_DISK TableInfo = Table->TableInfoOnDisk; + + return PerfectHashTableSeededHashMultiplyRotateR( + Table, + Key, + TableInfo->NumberOfSeeds, + &TableInfo->FirstSeed, + Hash + ); +} + // vim:set ts=8 sw=4 sts=4 tw=80 expandtab :