/* * Copyright (C) 2011 Andrea Mazzoleni * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * Derivative work from MurmorHash3.cpp revision r136 * * SMHasher & MurmurHash * http://code.google.com/p/smhasher/ * * Exact source used as reference: * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp?spec=svn136&r=136 */ // MurmurHash3 was written by Austin Appleby, and is placed in the public // domain. The author hereby disclaims copyright to this source code. /* Rotate left */ inline uint32_t rotl32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); } /* Swap endianess */ #if WORDS_BIGENDIAN static inline uint32_t swap32(uint32_t v) { return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | ((v >> 24) & 0xff); } #else static inline uint32_t swap32(uint32_t v) { return v; } #endif /* Finalization mix - force all bits of a hash block to avalanche */ static inline uint32_t fmix32(uint32_t h) { h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13; h *= 0xc2b2ae35; h ^= h >> 16; return h; } /* * Warning! * Don't declare these variables static, otherwise the gcc optimizer * may generate very slow code for multiplication with these constants, * like: -> .cpp k1 *= c1; -> .asm 152: 8d 14 80 lea (%eax,%eax,4),%edx 155: 8d 14 90 lea (%eax,%edx,4),%edx 158: c1 e2 03 shl $0x3,%edx 15b: 29 c2 sub %eax,%edx 15d: 8d 14 d2 lea (%edx,%edx,8),%edx 160: 8d 14 90 lea (%eax,%edx,4),%edx 163: 8d 14 d0 lea (%eax,%edx,8),%edx 166: 8d 14 90 lea (%eax,%edx,4),%edx 169: 8d 14 50 lea (%eax,%edx,2),%edx 16c: 8d 14 90 lea (%eax,%edx,4),%edx 16f: 8d 14 92 lea (%edx,%edx,4),%edx 172: 8d 14 50 lea (%eax,%edx,2),%edx 175: 8d 04 d0 lea (%eax,%edx,8),%eax 178: 8d 14 c5 00 00 00 00 lea 0x0(,%eax,8),%edx 17f: 29 d0 sub %edx,%eax * resulting in speeds of 500 MB/s instead of 3000 MB/s. * * Verified with gcc 4.4.4 compiling with : * * g++ -g -c -O2 MurmurHash3.cpp -o MurmurHash3.o */ uint32_t c1 = 0x239b961b; uint32_t c2 = 0xab0e9789; uint32_t c3 = 0x38b34ae5; uint32_t c4 = 0xa1e38b93; void MurmurHash3_x86_128(const void * key, unsigned len, uint32_t seed, void* out) { const uint8_t * data = (const uint8_t*)key; unsigned nblocks = len / 16; unsigned i; uint32_t h1 = seed; uint32_t h2 = seed; uint32_t h3 = seed; uint32_t h4 = seed; const uint32_t* blocks = (const uint32_t*)data; /* body */ for(i=0;i