blob: b7094d37a0c30d7eb797c3af96f4d54f8b6c1c23 [file] [log] [blame]
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +00001#include "pstdint.h"
2
3/* By Paul Hsieh (C) 2004, 2005. Covered under the Paul Hsieh derivative
4 license. See:
5 http://www.azillionmonkeys.com/qed/weblicense.html for license details.
6
7 http://www.azillionmonkeys.com/qed/hash.html */
8
9#undef get16bits
10#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
11 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
12#define get16bits(d) (*((const uint16_t *) (d)))
13#endif
14
15#if !defined (get16bits)
16#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
17 +(uint32_t)(((const uint8_t *)(d))[0]) )
18#endif
19
20uint32_t SuperFastHash (const char * data, int len) {
21uint32_t hash = 0, tmp;
22int rem;
23
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000024 if (len <= 0 || data == NULL) return 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000025
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000026 rem = len & 3;
27 len >>= 2;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000028
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000029 /* Main loop */
30 for (;len > 0; len--) {
31 hash += get16bits (data);
32 tmp = (get16bits (data+2) << 11) ^ hash;
33 hash = (hash << 16) ^ tmp;
34 data += 2*sizeof (uint16_t);
35 hash += hash >> 11;
36 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000037
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000038 /* Handle end cases */
39 switch (rem) {
40 case 3: hash += get16bits (data);
41 hash ^= hash << 16;
42 hash ^= data[sizeof (uint16_t)] << 18;
43 hash += hash >> 11;
44 break;
45 case 2: hash += get16bits (data);
46 hash ^= hash << 11;
47 hash += hash >> 17;
48 break;
49 case 1: hash += *data;
50 hash ^= hash << 10;
51 hash += hash >> 1;
52 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000053
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000054 /* Force "avalanching" of final 127 bits */
55 hash ^= hash << 3;
56 hash += hash >> 5;
57 hash ^= hash << 4;
58 hash += hash >> 17;
59 hash ^= hash << 25;
60 hash += hash >> 6;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000061
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000062 return hash;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000063}
64
65void SuperFastHash ( const void * key, int len, uint32_t /*seed*/, void * out )
66{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000067 *(uint32_t*)out = SuperFastHash((const char*)key,len);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000068}