/* * 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. /* 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, const uint8_t* seed, void* out) { const uint8_t* data = key; unsigned nblocks = len / 16; unsigned i; const uint32_t* blocks; uint32_t h1 = ((uint32_t*)seed)[0]; uint32_t h2 = ((uint32_t*)seed)[1]; uint32_t h3 = ((uint32_t*)seed)[2]; uint32_t h4 = ((uint32_t*)seed)[3]; #if WORDS_BIGENDIAN h1 = swap32(h1); h2 = swap32(h2); h3 = swap32(h3); h4 = swap32(h4); #endif blocks = (const uint32_t*)data; /* body */ for(i=0;i