diff --git a/src/hashing.h b/src/hashing.h new file mode 100644 index 0000000000000000000000000000000000000000..3551d6862151aab80ea1600dabeecb5d74f655b9 --- /dev/null +++ b/src/hashing.h @@ -0,0 +1,63 @@ +#ifndef HASHING_H +#define HASHING_H + +#include <cmath> + + +/* + * hashing by division + */ +template<typename T> +struct DivHashing { + const size_t m; + DivHashing(size_t table_size) : m(table_size) {} + + size_t operator()(T key) { return key % m; } +}; + +/* + * hashing by multiplication + */ +template<typename T> +struct MulHashing { + const double gratio = 0.61803; + const size_t m; + MulHashing(size_t table_size) : m(table_size) {} + + size_t operator()(T key) { return m * (gratio*key - std::floor(gratio*key)); } +}; + +/* + * linear probing + */ +struct LinearProbing { + const size_t h; + const size_t m; + LinearProbing(size_t hash, size_t table_size) : h(hash), m(table_size) {} + + size_t operator()(size_t i) { return (h+i) % m; } +}; + +/* + * quadratic probing + */ +struct QuadraticProbing { + const size_t h; + const size_t m; + QuadraticProbing(size_t hash, size_t table_size) : h(hash), m(table_size) {} + + size_t operator()(size_t i) { return (h + i*i) % m; } +}; + +/* + * double hashing + */ +struct DoubleHashing { + const size_t h; + const size_t m; + DoubleHashing(size_t hash, size_t table_size) : h(hash), m(table_size) {} + + size_t operator()(size_t i) { return (h + i*(h+1)) % m; } +}; + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 47ef1cf71f7146f15767471b2dc2cee907f3f7b0..d02f383fa9f56fea859486bf6d374af5df944739 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,12 +6,15 @@ include(CTest) # the executables that run the tests add_executable(test_main test_main.cpp) +add_executable(test_hashing test_hashing.cpp) add_executable(test_hashtable test_constructor.cpp test_hashtable.cpp) # link needed libraries target_link_libraries(test_main gtest gtest_main) +target_link_libraries(test_hashing gtest gtest_main) target_link_libraries(test_hashtable hashtable gtest gtest_main) # run with ctest add_test(NAME test_main COMMAND ${EXECUTABLE_OUTPUT_PATH}/test_main) +add_test(NAME test_hashing COMMAND ${EXECUTABLE_OUTPUT_PATH}/test_hashing) add_test(NAME test_hashtable COMMAND ${EXECUTABLE_OUTPUT_PATH}/test_hashtable) diff --git a/tests/test_hashing.cpp b/tests/test_hashing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..719b9588e121fe9102b4ddb0e3ebd6d6d340c0b4 --- /dev/null +++ b/tests/test_hashing.cpp @@ -0,0 +1,102 @@ +#include <gtest/gtest.h> +#include "hashing.h" + + +TEST(hashing, DivHashing) { + DivHashing<unsigned> hash0(1); + DivHashing<unsigned> hash1(7); + DivHashing<unsigned> hash2(23); + DivHashing<unsigned> hash3(512); + DivHashing<unsigned> hash4(6899); + + for (unsigned i=0; i<65535; i++) { + EXPECT_EQ(i%1, hash0(i)); + EXPECT_EQ(i%7, hash1(i)); + EXPECT_EQ(i%23, hash2(i)); + EXPECT_EQ(i%512, hash3(i)); + EXPECT_EQ(i%6899, hash4(i)); + } +} + +TEST(hashing, MulHashing) { + const double a = 0.61803; + using std::floor; + #define H(k,m) (floor((m*((a*k)-floor(a*k))))) + + MulHashing<unsigned> hash0(1); + MulHashing<unsigned> hash1(7); + MulHashing<unsigned> hash2(23); + MulHashing<unsigned> hash3(512); + MulHashing<unsigned> hash4(6899); + + for (unsigned i=0; i<65535; i++) { + EXPECT_EQ(H(i,1), hash0(i)); + EXPECT_EQ(H(i,7), hash1(i)); + EXPECT_EQ(H(i,23), hash2(i)); + EXPECT_EQ(H(i,512), hash3(i)); + EXPECT_EQ(H(i,6899), hash4(i)); + } +} + +TEST(hashing, LinearProbing) { + LinearProbing p0(2, 1); + LinearProbing p1(4, 512); + LinearProbing p2(0, 8); + LinearProbing p3(7, 32); + LinearProbing p4(16, 6899); + + for (unsigned i=0; i<10000; i++) { + EXPECT_LT(p0(i), 1); + EXPECT_EQ(p0(i), (2+i)%1); + EXPECT_LT(p1(i), 512); + EXPECT_EQ(p1(i), (4+i)%512); + EXPECT_LT(p2(i), 8); + EXPECT_EQ(p2(i), (0+i)%8); + EXPECT_LT(p3(i), 32); + EXPECT_EQ(p3(i), (7+i)%32); + EXPECT_LT(p4(i), 6899); + EXPECT_EQ(p4(i), (16+i)%6899); + } +} + +TEST(hashing, QuadraticProbing) { + QuadraticProbing p0(2, 1); + QuadraticProbing p1(4, 512); + QuadraticProbing p2(0, 8); + QuadraticProbing p3(7, 32); + QuadraticProbing p4(16, 6899); + + for (unsigned i=0; i<10000; i++) { + EXPECT_LT(p0(i), 1); + EXPECT_EQ(p0(i), (2+i*i)%1); + EXPECT_LT(p1(i), 512); + EXPECT_EQ(p1(i), (4+i*i)%512); + EXPECT_LT(p2(i), 8); + EXPECT_EQ(p2(i), (0+i*i)%8); + EXPECT_LT(p3(i), 32); + EXPECT_EQ(p3(i), (7+i*i)%32); + EXPECT_LT(p4(i), 6899); + EXPECT_EQ(p4(i), (16+i*i)%6899); + } +} + +TEST(hashing, DoubleHashing) { + DoubleHashing p0(2, 1); + DoubleHashing p1(4, 512); + DoubleHashing p2(0, 8); + DoubleHashing p3(7, 32); + DoubleHashing p4(16, 6899); + + for (unsigned i=0; i<10000; i++) { + EXPECT_LT(p0(i), 1); + EXPECT_EQ(p0(i), (2+i*(2+1))%1); + EXPECT_LT(p1(i), 512); + EXPECT_EQ(p1(i), (4+i*(4+1))%512); + EXPECT_LT(p2(i), 8); + EXPECT_EQ(p2(i), (0+i*(0+1))%8); + EXPECT_LT(p3(i), 32); + EXPECT_EQ(p3(i), (7+i*(7+1))%32); + EXPECT_LT(p4(i), 6899); + EXPECT_EQ(p4(i), (16+i*(16+1))%6899); + } +}