From 08fbeab97db991e7029aa71677b2888faaf2a413 Mon Sep 17 00:00:00 2001 From: Trent Nelson Date: Tue, 18 Feb 2020 22:08:15 -0800 Subject: [PATCH] Implement Multiply and MultiplyXor hash functions. --- include/PerfectHash.h | 2 + include/PerfectHashErrors.h | 2 + ...ledPerfectHashTableChm01IndexMultiplyAnd.c | 27 +++ ...PerfectHashTableChm01IndexMultiplyXorAnd.c | 29 +++ ...Chm01IndexMultiplyAnd_CSource_RawCString.h | 57 ++++++ ...01IndexMultiplyXorAnd_CSource_RawCString.h | 59 ++++++ .../CompiledPerfectHashTableIndexRoutines.h | 2 + src/PerfectHash/PerfectHash.vcxproj | 4 +- src/PerfectHash/PerfectHash.vcxproj.filters | 8 +- src/PerfectHash/PerfectHashErrors.mc | 2 + src/PerfectHash/PerfectHashErrors_English.bin | Bin 85628 -> 85724 bytes src/PerfectHash/PerfectHashTableHash.c | 190 ++++++++++++++++++ 12 files changed, 380 insertions(+), 2 deletions(-) create mode 100644 src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyAnd.c create mode 100644 src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyXorAnd.c create mode 100644 src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyAnd_CSource_RawCString.h create mode 100644 src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyXorAnd_CSource_RawCString.h diff --git a/include/PerfectHash.h b/include/PerfectHash.h index a4626fa1..47a95f52 100644 --- a/include/PerfectHash.h +++ b/include/PerfectHash.h @@ -1968,6 +1968,8 @@ IsValidSeedMasks( 3, \ DECL_SEED_MASKS(0, 0, 0x1f1f, 0, 0, 0, 0, 0) \ ) \ + ENTRY(Multiply, 2, NO_SEED_MASKS) \ + ENTRY(MultiplyXor, 4, NO_SEED_MASKS) \ 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 ac25f2e3..4f50c3ee 100644 --- a/include/PerfectHashErrors.h +++ b/include/PerfectHashErrors.h @@ -252,6 +252,8 @@ Module Name: // 22 MultiplyRotateLR (3) // 23 MultiplyShiftR (3) // 24 MultiplyShiftLR (3) +// 25 Multiply (2) +// 26 MultiplyXor (4) // // 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/CompiledPerfectHashTableChm01IndexMultiplyAnd.c b/src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyAnd.c new file mode 100644 index 00000000..faf1f7b7 --- /dev/null +++ b/src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyAnd.c @@ -0,0 +1,27 @@ + +DECLARE_INDEX_ROUTINE() +{ + CPHINDEX Index; + CPHDKEY Vertex1; + CPHDKEY Vertex2; + CPHDKEY MaskedLow; + CPHDKEY MaskedHigh; + CPHDKEY DownsizedKey; + + DownsizedKey = DOWNSIZE_KEY(Key); + + Vertex1 = DownsizedKey * SEED1; + + Vertex2 = DownsizedKey * SEED2; + + 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/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyXorAnd.c b/src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyXorAnd.c new file mode 100644 index 00000000..a8731264 --- /dev/null +++ b/src/CompiledPerfectHashTable/CompiledPerfectHashTableChm01IndexMultiplyXorAnd.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 ^= SEED2; + + Vertex2 = DownsizedKey * SEED3; + Vertex2 ^= SEED4; + + 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/CompiledPerfectHashTableChm01IndexMultiplyAnd_CSource_RawCString.h b/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyAnd_CSource_RawCString.h new file mode 100644 index 00000000..cea2576f --- /dev/null +++ b/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyAnd_CSource_RawCString.h @@ -0,0 +1,57 @@ +// +// Auto-generated. +// + +DECLSPEC_ALIGN(16) +const CHAR CompiledPerfectHashTableChm01IndexMultiplyAndCSourceRawCStr[] = + "\n" + "//\n" + "// Begin CompiledPerfectHashTableChm01IndexMultiplyAnd.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" + "\n" + " Vertex2 = DownsizedKey * SEED2;\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 CompiledPerfectHashTableChm01IndexMultiplyAnd.c.\n" + "//\n" + "\n" +; + +const STRING CompiledPerfectHashTableChm01IndexMultiplyAndCSourceRawCString = { + sizeof(CompiledPerfectHashTableChm01IndexMultiplyAndCSourceRawCStr) - sizeof(CHAR), + sizeof(CompiledPerfectHashTableChm01IndexMultiplyAndCSourceRawCStr), +#ifdef _WIN64 + 0, +#endif + (PCHAR)&CompiledPerfectHashTableChm01IndexMultiplyAndCSourceRawCStr, +}; + +#ifndef RawCString +#define RawCString (&CompiledPerfectHashTableChm01IndexMultiplyAndCSourceRawCString) +#endif diff --git a/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyXorAnd_CSource_RawCString.h b/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyXorAnd_CSource_RawCString.h new file mode 100644 index 00000000..eb8d6a52 --- /dev/null +++ b/src/PerfectHash/CompiledPerfectHashTableChm01IndexMultiplyXorAnd_CSource_RawCString.h @@ -0,0 +1,59 @@ +// +// Auto-generated. +// + +DECLSPEC_ALIGN(16) +const CHAR CompiledPerfectHashTableChm01IndexMultiplyXorAndCSourceRawCStr[] = + "\n" + "//\n" + "// Begin CompiledPerfectHashTableChm01IndexMultiplyXorAnd.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 ^= SEED2;\n" + "\n" + " Vertex2 = DownsizedKey * SEED3;\n" + " Vertex2 ^= SEED4;\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 CompiledPerfectHashTableChm01IndexMultiplyXorAnd.c.\n" + "//\n" + "\n" +; + +const STRING CompiledPerfectHashTableChm01IndexMultiplyXorAndCSourceRawCString = { + sizeof(CompiledPerfectHashTableChm01IndexMultiplyXorAndCSourceRawCStr) - sizeof(CHAR), + sizeof(CompiledPerfectHashTableChm01IndexMultiplyXorAndCSourceRawCStr), +#ifdef _WIN64 + 0, +#endif + (PCHAR)&CompiledPerfectHashTableChm01IndexMultiplyXorAndCSourceRawCStr, +}; + +#ifndef RawCString +#define RawCString (&CompiledPerfectHashTableChm01IndexMultiplyXorAndCSourceRawCString) +#endif diff --git a/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h b/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h index 588a411c..441cbaaf 100644 --- a/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h +++ b/src/PerfectHash/CompiledPerfectHashTableIndexRoutines.h @@ -22,6 +22,8 @@ #include "CompiledPerfectHashTableChm01IndexMultiplyRotateLRAnd_CSource_RawCString.h" #include "CompiledPerfectHashTableChm01IndexMultiplyShiftRAnd_CSource_RawCString.h" #include "CompiledPerfectHashTableChm01IndexMultiplyShiftLRAnd_CSource_RawCString.h" +#include "CompiledPerfectHashTableChm01IndexMultiplyAnd_CSource_RawCString.h" +#include "CompiledPerfectHashTableChm01IndexMultiplyXorAnd_CSource_RawCString.h" // // Keep this last. diff --git a/src/PerfectHash/PerfectHash.vcxproj b/src/PerfectHash/PerfectHash.vcxproj index 820ef419..cd00377e 100644 --- a/src/PerfectHash/PerfectHash.vcxproj +++ b/src/PerfectHash/PerfectHash.vcxproj @@ -119,6 +119,8 @@ + + @@ -271,4 +273,4 @@ - \ No newline at end of file + diff --git a/src/PerfectHash/PerfectHash.vcxproj.filters b/src/PerfectHash/PerfectHash.vcxproj.filters index d1132917..3051c96b 100644 --- a/src/PerfectHash/PerfectHash.vcxproj.filters +++ b/src/PerfectHash/PerfectHash.vcxproj.filters @@ -489,6 +489,12 @@ Private Header Files %28Auto-Generated%29 + + Private Header Files %28Auto-Generated%29 + + + Private Header Files %28Auto-Generated%29 + Private Header Files @@ -566,4 +572,4 @@ Resource Files - \ No newline at end of file + diff --git a/src/PerfectHash/PerfectHashErrors.mc b/src/PerfectHash/PerfectHashErrors.mc index 4c9f9a4c..6238e99d 100644 --- a/src/PerfectHash/PerfectHashErrors.mc +++ b/src/PerfectHash/PerfectHashErrors.mc @@ -198,6 +198,8 @@ Hash Functions: 22 MultiplyRotateLR (3) 23 MultiplyShiftR (3) 24 MultiplyShiftLR (3) + 25 Multiply (2) + 26 MultiplyXor (4) 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 77c017f8ad4f74d7a2a86971b78c984037402cae..8274a1b6462866533633887fb90d7c3ed3ba1955 100644 GIT binary patch delta 181 zcmew}hxN`})(HlQ3*Is?2s5!fkO$(DFANNdKw1NcRemxsXanhfAQt(mIh)E9YzK@Agu(%AAoEXAl(MUGd51tXJfpx`5@at=E(wF z9E_%u1G&US6&N%aj2JW-cp11D6u{7k!3-ob*?^Oc6(nmic_F{-<{4Z|IGe3Rwp)oX HI#~e#y;U!{ delta 135 zcmcaJm-Wva)(HlQ4sRJ4gqc_#$OEy+7X}7JAguw!M}9CcXanhfAl~wufngGmo)5$g zvWyH2%q$NifVf48kwFSbO9Sx>ZAJz;Agu(%6Lc6ERDg6F5L;}VsL#e&v-u#~LFUP9 V0%DuLaV_C&o+Gk-jtHZJ6#ytlDV6{L diff --git a/src/PerfectHash/PerfectHashTableHash.c b/src/PerfectHash/PerfectHashTableHash.c index 3839d6f9..797b3595 100644 --- a/src/PerfectHash/PerfectHashTableHash.c +++ b/src/PerfectHash/PerfectHashTableHash.c @@ -2670,5 +2670,195 @@ PerfectHashTableHashMultiplyShiftLR( ); } +_Use_decl_annotations_ +HRESULT +PerfectHashTableSeededHashMultiply( + PPERFECT_HASH_TABLE Table, + ULONG Key, + ULONG NumberOfSeeds, + PULONG Seeds, + PULONGLONG Hash + ) +/*++ + +Routine Description: + + Performs a single multiply on each vertex. + +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 Vertex1; + ULONG Vertex2; + ULONG DownsizedKey; + ULARGE_INTEGER Result; + + UNREFERENCED_PARAMETER(Table); + + ASSERT(NumberOfSeeds >= 2); + UNREFERENCED_PARAMETER(NumberOfSeeds); + + // + // Initialize aliases. + // + + Seed1 = Seeds[0]; + Seed2 = Seeds[1]; + DownsizedKey = Key; + + // + // Calculate the individual hash parts. + // + + Vertex1 = DownsizedKey * Seed1; + + Vertex2 = DownsizedKey * Seed2; + + if (Vertex1 == Vertex2) { + return E_FAIL; + } + + Result.LowPart = Vertex1; + Result.HighPart = Vertex2; + + *Hash = Result.QuadPart; + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT +PerfectHashTableHashMultiply( + PPERFECT_HASH_TABLE Table, + ULONG Key, + PULONGLONG Hash + ) +{ + PTABLE_INFO_ON_DISK TableInfo = Table->TableInfoOnDisk; + + return PerfectHashTableSeededHashMultiply( + Table, + Key, + TableInfo->NumberOfSeeds, + &TableInfo->FirstSeed, + Hash + ); +} + +_Use_decl_annotations_ +HRESULT +PerfectHashTableSeededHashMultiplyXor( + PPERFECT_HASH_TABLE Table, + ULONG Key, + ULONG NumberOfSeeds, + PULONG Seeds, + PULONGLONG Hash + ) +/*++ + +Routine Description: + + Performs a multiply then xor on each vertex. + +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 Seed3; + ULONG Seed4; + ULONG Vertex1; + ULONG Vertex2; + ULONG DownsizedKey; + ULARGE_INTEGER Result; + + UNREFERENCED_PARAMETER(Table); + + ASSERT(NumberOfSeeds >= 4); + UNREFERENCED_PARAMETER(NumberOfSeeds); + + // + // Initialize aliases. + // + + Seed1 = Seeds[0]; + Seed2 = Seeds[1]; + Seed3 = Seeds[2]; + Seed4 = Seeds[3]; + DownsizedKey = Key; + + // + // Calculate the individual hash parts. + // + + Vertex1 = DownsizedKey * Seed1; + Vertex1 ^= Seed2; + + Vertex2 = DownsizedKey * Seed3; + Vertex2 ^= Seed4; + + if (Vertex1 == Vertex2) { + return E_FAIL; + } + + Result.LowPart = Vertex1; + Result.HighPart = Vertex2; + + *Hash = Result.QuadPart; + + return S_OK; +} + +_Use_decl_annotations_ +HRESULT +PerfectHashTableHashMultiplyXor( + PPERFECT_HASH_TABLE Table, + ULONG Key, + PULONGLONG Hash + ) +{ + PTABLE_INFO_ON_DISK TableInfo = Table->TableInfoOnDisk; + + return PerfectHashTableSeededHashMultiplyXor( + Table, + Key, + TableInfo->NumberOfSeeds, + &TableInfo->FirstSeed, + Hash + ); +} + // vim:set ts=8 sw=4 sts=4 tw=80 expandtab :