Skip to content

Commit bcd8690

Browse files
authored
Merge pull request #1 from cptr0/cptr0-Lookup3-1
Add hash_lookup3.c
2 parents e5dad3f + a236a2c commit bcd8690

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

hash/hash_lookup3.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* @addtogroup hash Hash algorithms
3+
* @{
4+
* @file hash_lookup3.c
5+
* @author [cptr0](https://github.com/cptr0)
6+
* @brief 32-bit [Jenkins hash](https://en.wikipedia.org/wiki/Jenkins_hash_function) algorithm
7+
*/
8+
9+
#include <assert.h>
10+
#include <inttypes.h>
11+
#include <string.h>
12+
#include <stdio.h>
13+
14+
// Rotate x left by k bits
15+
#define rot(x,k) (((x) << (k)) | ((x) >> (32-(k))))
16+
17+
/**
18+
* @brief 32-bit Jenkins Lookup3 algorithm implementation
19+
*
20+
* @param s NULL terminated ASCII string to hash
21+
* @return 32-bit hash result
22+
*/
23+
24+
uint32_t lookup3_32(const char *key, uint32_t seed)
25+
{
26+
uint32_t a, b, c;
27+
a = b = 0x9e3779b9;
28+
c = seed;
29+
30+
size_t i = 0;
31+
32+
size_t length = strlen(key);
33+
34+
while (length - i >= 12)
35+
{
36+
a += (uint32_t)key[i] | ((uint32_t)key[i+1] << 8) |
37+
((uint32_t)key[i+2] << 16) | ((uint32_t)key[i+3] << 24);
38+
b += (uint32_t)key[i+4] | ((uint32_t)key[i+5] << 8) |
39+
((uint32_t)key[i+6] << 16) | ((uint32_t)key[i+7] << 24);
40+
c += (uint32_t)key[i+8] | ((uint32_t)key[i+9] << 8) |
41+
((uint32_t)key[i+10] << 16) | ((uint32_t)key[i+11] << 24);
42+
43+
a -= c; a ^= rot(c,4); c += b;
44+
b -= a; b ^= rot(a,6); a += c;
45+
c -= b; c ^= rot(b,8); b += a;
46+
a -= c; a ^= rot(c,16); c += b;
47+
b -= a; b ^= rot(a,19); a += c;
48+
c -= b; c ^= rot(b,4); b += a;
49+
50+
i += 12;
51+
}
52+
53+
uint32_t remainingA = 0, remainingB = 0, remainingC = 0;
54+
switch (length - i)
55+
{
56+
case 11: remainingC += ((uint32_t)key[i+10]) << 16;
57+
case 10: remainingC += ((uint32_t)key[i+9]) << 8;
58+
case 9: remainingC += (uint32_t)key[i+8];
59+
case 8: remainingB += ((uint32_t)key[i+7]) << 24;
60+
case 7: remainingB += ((uint32_t)key[i+6]) << 16;
61+
case 6: remainingB += ((uint32_t)key[i+5]) << 8;
62+
case 5: remainingB += (uint32_t)key[i+4];
63+
case 4: remainingA += ((uint32_t)key[i+3]) << 24;
64+
case 3: remainingA += ((uint32_t)key[i+2]) << 16;
65+
case 2: remainingA += ((uint32_t)key[i+1]) << 8;
66+
case 1: remainingA += (uint32_t)key[i];
67+
a += remainingA;
68+
b += remainingB;
69+
c += remainingC;
70+
}
71+
72+
c ^= b; c -= rot(b,14);
73+
a ^= c; a -= rot(c,11);
74+
b ^= a; b -= rot(a,25);
75+
c ^= b; c -= rot(b,16);
76+
a ^= c; a -= rot(c,4);
77+
b ^= a; b -= rot(a,14);
78+
c ^= b; c -= rot(b,24);
79+
80+
return c;
81+
}
82+
/**
83+
* @brief Test function for lookup3_32 function
84+
*
85+
* @returns None
86+
*/
87+
void test_lookup3_32()
88+
{
89+
assert(lookup3_32("Hello, Jenkins!", 0) == 2484708164);
90+
assert(lookup3_32("Hello Jenkinss", 0) == 850494015);
91+
assert(lookup3_32("Hello, Jenkins", 0) == 3393305742);
92+
assert(lookup3_32("hello, jenkins!", 0) == 3521406038);
93+
94+
printf("%s", "Test passed.\n");
95+
}
96+
97+
/**
98+
* @brief Main function
99+
*
100+
* @returns 0 on successful program exit
101+
*/
102+
int main()
103+
{
104+
test_lookup3_32();
105+
return 0;
106+
}

0 commit comments

Comments
 (0)