diff --git a/acinclude.m4 b/acinclude.m4 index b49a92b..bde7628 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -12,6 +12,82 @@ AC_DEFUN([AC_CHECK_SPOON], [ AC_MSG_RESULT(no) ]) +dnl Check for baseline language coverage in the compiler for the C++0x standard. +# AC_COMPILE_STDCXX_OX +AC_DEFUN([AC_COMPILE_STDCXX_0X], [ + AC_CACHE_CHECK(if compiler supports C++0x features without additional flags, + ac_cv_cxx_compile_cxx0x_native, + [AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ + #include + #include + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + ],, + ac_cv_cxx_compile_cxx0x_native=yes, ac_cv_cxx_compile_cxx0x_native=no) + AC_LANG_RESTORE + ]) + + AC_CACHE_CHECK(if compiler supports C++0x features with -std=c++0x, + ac_cv_cxx_compile_cxx0x_cxx, + [AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -std=c++0x" + AC_TRY_COMPILE([ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b;],, + ac_cv_cxx_compile_cxx0x_cxx=yes, ac_cv_cxx_compile_cxx0x_cxx=no) + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE + ]) + + AC_CACHE_CHECK(if compiler supports C++0x features with -std=gnu++0x, + ac_cv_cxx_compile_cxx0x_gxx, + [AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -std=gnu++0x" + AC_TRY_COMPILE([ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b;],, + ac_cv_cxx_compile_cxx0x_gxx=yes, ac_cv_cxx_compile_cxx0x_gxx=no) + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE + ]) + + if test "$ac_cv_cxx_compile_cxx0x_native" = yes || + test "$ac_cv_cxx_compile_cxx0x_cxx" = yes || + test "$ac_cv_cxx_compile_cxx0x_gxx" = yes; then + AC_DEFINE(HAVE_STDCXX_0X,,[Define if g++ supports C++0x features. ]) + fi +]) + dnl By default, many hosts won't let programs access large files; dnl one must use special compiler options to get large-file access to work. dnl For more details about this brain damage please see: diff --git a/configure.ac b/configure.ac index b749ad3..172b02f 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,17 @@ CFLAGS="-Wall -Werror" AC_PROG_CXX AC_ENABLE_CXXMPH if test x$cxxmph = xtrue; then - AC_SUBST([CXXMPH], "cxxmph") + AC_COMPILE_STDCXX_0X + if test x$ac_cv_cxx_compile_cxx0x_native = "xno"; then + if test x$ac_cv_cxx_compile_cxx0x_cxx = "xyes"; then + CXXFLAGS="$CXXFLAGS -std=c++0x" + elif test x$ac_cv_cxx_compile_cxx0x_gxx = "xyes"; then + CXXFLAGS="$CXXFLAGS -std=gnu++0x" + else + AC_MSG_ERROR("cxxmph demands a working c++0x compiler.") + fi + fi + AC_SUBST([CXXMPH], "cxxmph") fi AC_CHECK_SPOON diff --git a/cxxmph/Makefile.am b/cxxmph/Makefile.am index c02e1c9..0396811 100644 --- a/cxxmph/Makefile.am +++ b/cxxmph/Makefile.am @@ -1,4 +1,3 @@ -AM_CXXFLAGS='-std=c++0x' TESTS = $(check_PROGRAMS) check_PROGRAMS = mph_map_test mph_index_test # trigraph_test noinst_PROGRAMS = bm_index bm_map diff --git a/src/jenkins_hash.c b/src/jenkins_hash.c index bd65ff6..65cdff9 100644 --- a/src/jenkins_hash.c +++ b/src/jenkins_hash.c @@ -7,9 +7,8 @@ #include #include -// #define DEBUG +//#define DEBUG #include "debug.h" -#include "MurmurHash2.h" #define hashsize(n) ((cmph_uint32)1<<(n)) #define hashmask(n) (hashsize(n)-1) @@ -88,8 +87,8 @@ acceptable. Do NOT use for cryptographic purposes. jenkins_state_t *jenkins_state_new(cmph_uint32 size) //size of hash table { jenkins_state_t *state = (jenkins_state_t *)malloc(sizeof(jenkins_state_t)); + DEBUGP("Initializing jenkins hash\n"); state->seed = ((cmph_uint32)rand() % size); - DEBUGP("Initializied jenkins hash with seed %d\n", state->seed); return state; } void jenkins_state_destroy(jenkins_state_t *state) @@ -100,67 +99,63 @@ void jenkins_state_destroy(jenkins_state_t *state) static inline void __jenkins_hash_vector(cmph_uint32 seed, const char *k, cmph_uint32 keylen, cmph_uint32 * hashes) { - int i; - for (i = 0; i < 3; ++i) { - hashes[i] = MurmurHash2(k, keylen, seed + i); + register cmph_uint32 len, length; + + /* Set up the internal state */ + length = keylen; + len = length; + hashes[0] = hashes[1] = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + hashes[2] = seed; /* the previous hash value - seed in our case */ + + /*---------------------------------------- handle most of the key */ + while (len >= 12) + { + hashes[0] += ((cmph_uint32)k[0] +((cmph_uint32)k[1]<<8) +((cmph_uint32)k[2]<<16) +((cmph_uint32)k[3]<<24)); + hashes[1] += ((cmph_uint32)k[4] +((cmph_uint32)k[5]<<8) +((cmph_uint32)k[6]<<16) +((cmph_uint32)k[7]<<24)); + hashes[2] += ((cmph_uint32)k[8] +((cmph_uint32)k[9]<<8) +((cmph_uint32)k[10]<<16)+((cmph_uint32)k[11]<<24)); + mix(hashes[0],hashes[1],hashes[2]); + k += 12; len -= 12; } -// register cmph_uint32 len, length; -// -// /* Set up the internal state */ -// length = keylen; -// len = length; -// hashes[0] = hashes[1] = 0x9e3779b9; /* the golden ratio; an arbitrary value */ -// hashes[2] = seed; /* the previous hash value - seed in our case */ -// -// /*---------------------------------------- handle most of the key */ -// while (len >= 12) -// { -// hashes[0] += ((cmph_uint32)k[0] +((cmph_uint32)k[1]<<8) +((cmph_uint32)k[2]<<16) +((cmph_uint32)k[3]<<24)); -// hashes[1] += ((cmph_uint32)k[4] +((cmph_uint32)k[5]<<8) +((cmph_uint32)k[6]<<16) +((cmph_uint32)k[7]<<24)); -// hashes[2] += ((cmph_uint32)k[8] +((cmph_uint32)k[9]<<8) +((cmph_uint32)k[10]<<16)+((cmph_uint32)k[11]<<24)); -// mix(hashes[0],hashes[1],hashes[2]); -// k += 12; len -= 12; -// } -// -// /*------------------------------------- handle the last 11 bytes */ -// hashes[2] += length; -// switch(len) /* all the case statements fall through */ -// { -// case 11: -// hashes[2] +=((cmph_uint32)k[10]<<24); -// case 10: -// hashes[2] +=((cmph_uint32)k[9]<<16); -// case 9 : -// hashes[2] +=((cmph_uint32)k[8]<<8); -// /* the first byte of hashes[2] is reserved for the length */ -// case 8 : -// hashes[1] +=((cmph_uint32)k[7]<<24); -// case 7 : -// hashes[1] +=((cmph_uint32)k[6]<<16); -// case 6 : -// hashes[1] +=((cmph_uint32)k[5]<<8); -// case 5 : -// hashes[1] +=(cmph_uint8) k[4]; -// case 4 : -// hashes[0] +=((cmph_uint32)k[3]<<24); -// case 3 : -// hashes[0] +=((cmph_uint32)k[2]<<16); -// case 2 : -// hashes[0] +=((cmph_uint32)k[1]<<8); -// case 1 : -// hashes[0] +=(cmph_uint8)k[0]; -// /* case 0: nothing left to add */ -// } -// -// mix(hashes[0],hashes[1],hashes[2]); + + /*------------------------------------- handle the last 11 bytes */ + hashes[2] += length; + switch(len) /* all the case statements fall through */ + { + case 11: + hashes[2] +=((cmph_uint32)k[10]<<24); + case 10: + hashes[2] +=((cmph_uint32)k[9]<<16); + case 9 : + hashes[2] +=((cmph_uint32)k[8]<<8); + /* the first byte of hashes[2] is reserved for the length */ + case 8 : + hashes[1] +=((cmph_uint32)k[7]<<24); + case 7 : + hashes[1] +=((cmph_uint32)k[6]<<16); + case 6 : + hashes[1] +=((cmph_uint32)k[5]<<8); + case 5 : + hashes[1] +=(cmph_uint8) k[4]; + case 4 : + hashes[0] +=((cmph_uint32)k[3]<<24); + case 3 : + hashes[0] +=((cmph_uint32)k[2]<<16); + case 2 : + hashes[0] +=((cmph_uint32)k[1]<<8); + case 1 : + hashes[0] +=(cmph_uint8)k[0]; + /* case 0: nothing left to add */ + } + + mix(hashes[0],hashes[1],hashes[2]); } cmph_uint32 jenkins_hash(jenkins_state_t *state, const char *k, cmph_uint32 keylen) { -// cmph_uint32 hashes[3]; -// __jenkins_hash_vector(state->seed, k, keylen, hashes); -// return hashes[2]; - cmph_uint32 a, b, c; + cmph_uint32 hashes[3]; + __jenkins_hash_vector(state->seed, k, keylen, hashes); + return hashes[2]; +/* cmph_uint32 a, b, c; cmph_uint32 len, length; // Set up the internal state @@ -214,6 +209,7 @@ cmph_uint32 jenkins_hash(jenkins_state_t *state, const char *k, cmph_uint32 keyl /// report the result return c; + */ } void jenkins_hash_vector_(jenkins_state_t *state, const char *k, cmph_uint32 keylen, cmph_uint32 * hashes)