/Users/deen/code/yugabyte-db/src/yb/gutil/hash/jenkins.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2011 Google Inc. All Rights Reserved. |
2 | | // |
3 | | // The following only applies to changes made to this file as part of YugaByte development. |
4 | | // |
5 | | // Portions Copyright (c) YugaByte, Inc. |
6 | | // |
7 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
8 | | // in compliance with the License. You may obtain a copy of the License at |
9 | | // |
10 | | // http://www.apache.org/licenses/LICENSE-2.0 |
11 | | // |
12 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
13 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
14 | | // or implied. See the License for the specific language governing permissions and limitations |
15 | | // under the License. |
16 | | // |
17 | | // Contains the legacy Bob Jenkins Lookup2-based hashing routines. These need to |
18 | | // always return the same results as their values have been recorded in various |
19 | | // places and cannot easily be updated. |
20 | | // |
21 | | // Original Author: Sanjay Ghemawat |
22 | | // |
23 | | // This is based on Bob Jenkins newhash function |
24 | | // see: http://burtleburtle.net/bob/hash/evahash.html |
25 | | // According to http://burtleburtle.net/bob/c/lookup2.c, |
26 | | // his implementation is public domain. |
27 | | // |
28 | | // The implementation here is backwards compatible with the google1 |
29 | | // implementation. The google1 implementation used a 'signed char *' |
30 | | // to load words from memory a byte at a time. See gwshash.cc for an |
31 | | // implementation that is compatible with Bob Jenkins' lookup2.c. |
32 | | |
33 | | #include "yb/gutil/hash/jenkins.h" |
34 | | |
35 | | #include "yb/gutil/integral_types.h" |
36 | | #include <glog/logging.h> |
37 | | #include "yb/gutil/hash/jenkins_lookup2.h" |
38 | | #include "yb/gutil/macros.h" |
39 | | |
40 | 97.4M | static inline uint32 char2unsigned(char c) { |
41 | 97.4M | return static_cast<uint32>(static_cast<unsigned char>(c)); |
42 | 97.4M | } |
43 | | |
44 | 47.5M | static inline uint64 char2unsigned64(char c) { |
45 | 47.5M | return static_cast<uint64>(static_cast<unsigned char>(c)); |
46 | 47.5M | } |
47 | | |
48 | 0 | uint32 Hash32StringWithSeedReferenceImplementation(const char *s, size_t len, uint32 c) { |
49 | 0 | uint32 a, b; |
50 | 0 | size_t keylen; |
51 | |
|
52 | 0 | a = b = 0x9e3779b9UL; // the golden ratio; an arbitrary value |
53 | |
|
54 | 0 | for ( keylen = len; keylen >= 3*sizeof(a); |
55 | 0 | keylen -= static_cast<uint32>(3*sizeof(a)), s += 3*sizeof(a) ) { |
56 | 0 | a += Google1At(s); |
57 | 0 | b += Google1At(s + sizeof(a)); |
58 | 0 | c += Google1At(s + sizeof(a)*2); |
59 | 0 | mix(a, b, c); |
60 | 0 | } |
61 | |
|
62 | 0 | c += len; |
63 | 0 | switch ( keylen ) { // deal with rest. Cases fall through |
64 | 0 | case 11: c += char2unsigned(s[10]) << 24; FALLTHROUGH_INTENDED; |
65 | 0 | case 10: c += char2unsigned(s[9]) << 16; FALLTHROUGH_INTENDED; |
66 | 0 | case 9 : c += char2unsigned(s[8]) << 8; FALLTHROUGH_INTENDED; |
67 | | // the first byte of c is reserved for the length |
68 | 0 | case 8 : b += Google1At(s+4); a += Google1At(s); break; |
69 | 0 | case 7 : b += char2unsigned(s[6]) << 16; FALLTHROUGH_INTENDED; |
70 | 0 | case 6 : b += char2unsigned(s[5]) << 8; FALLTHROUGH_INTENDED; |
71 | 0 | case 5 : b += char2unsigned(s[4]); FALLTHROUGH_INTENDED; |
72 | 0 | case 4 : a += Google1At(s); break; |
73 | 0 | case 3 : a += char2unsigned(s[2]) << 16; FALLTHROUGH_INTENDED; |
74 | 0 | case 2 : a += char2unsigned(s[1]) << 8; FALLTHROUGH_INTENDED; |
75 | 0 | case 1 : a += char2unsigned(s[0]); |
76 | | // case 0 : nothing left to add |
77 | 0 | } |
78 | 0 | mix(a, b, c); |
79 | 0 | return c; |
80 | 0 | } |
81 | | |
82 | | |
83 | 70.2M | uint32 Hash32StringWithSeed(const char *s, size_t len, uint32 c) { |
84 | 70.2M | uint32 a, b; |
85 | | |
86 | 70.2M | a = b = 0x9e3779b9UL; // the golden ratio; an arbitrary value |
87 | | |
88 | 70.2M | size_t keylen = len; |
89 | 70.2M | if (keylen >= 4 * sizeof(a)) { |
90 | 6.95M | uint32 word32AtOffset0 = Google1At(s); |
91 | 6.96M | do { |
92 | 6.96M | a += word32AtOffset0; |
93 | 6.96M | b += Google1At(s + sizeof(a)); |
94 | 6.96M | c += Google1At(s + sizeof(a) * 2); |
95 | 6.96M | s += 3 * sizeof(a); |
96 | 6.96M | word32AtOffset0 = Google1At(s); |
97 | 6.96M | mix(a, b, c); |
98 | 6.96M | keylen -= 3 * static_cast<uint32>(sizeof(a)); |
99 | 6.96M | } while (keylen >= 4 * sizeof(a)); |
100 | 6.95M | if (keylen >= 3 * sizeof(a)) { |
101 | 462k | a += word32AtOffset0; |
102 | 462k | b += Google1At(s + sizeof(a)); |
103 | 462k | c += Google1At(s + sizeof(a) * 2); |
104 | 462k | s += 3 * sizeof(a); |
105 | 462k | mix(a, b, c); |
106 | 462k | keylen -= 3 * static_cast<uint32>(sizeof(a)); |
107 | 462k | DCHECK_LT(keylen, sizeof(a)); |
108 | 462k | c += len; |
109 | 462k | switch ( keylen ) { // deal with rest. Cases fall through |
110 | 222k | case 3 : a += char2unsigned(s[2]) << 16; FALLTHROUGH_INTENDED; |
111 | 444k | case 2 : a += char2unsigned(s[1]) << 8; FALLTHROUGH_INTENDED; |
112 | 444k | case 1 : a += char2unsigned(s[0]); |
113 | 462k | } |
114 | 6.49M | } else { |
115 | 6.49M | DCHECK(sizeof(a) <= keylen && keylen < 3 * sizeof(a)); |
116 | 6.49M | c += len; |
117 | 6.49M | switch ( keylen ) { // deal with rest. Cases fall through |
118 | 263k | case 11: c += char2unsigned(s[10]) << 24; FALLTHROUGH_INTENDED; |
119 | 494k | case 10: c += char2unsigned(s[9]) << 16; FALLTHROUGH_INTENDED; |
120 | 1.00M | case 9 : c += char2unsigned(s[8]) << 8; FALLTHROUGH_INTENDED; |
121 | 1.97M | case 8 : b += Google1At(s+4); a += word32AtOffset0; break; |
122 | 217k | case 7 : b += char2unsigned(s[6]) << 16; FALLTHROUGH_INTENDED; |
123 | 858k | case 6 : b += char2unsigned(s[5]) << 8; FALLTHROUGH_INTENDED; |
124 | 1.91M | case 5 : b += char2unsigned(s[4]); FALLTHROUGH_INTENDED; |
125 | 4.51M | case 4 : a += word32AtOffset0; break; |
126 | 63.2M | } |
127 | 63.2M | } |
128 | 63.2M | } else { |
129 | 63.2M | if (keylen >= 3 * sizeof(a)) { |
130 | 12.2M | a += Google1At(s); |
131 | 12.2M | b += Google1At(s + sizeof(a)); |
132 | 12.2M | c += Google1At(s + sizeof(a) * 2); |
133 | 12.2M | s += 3 * sizeof(a); |
134 | 12.2M | mix(a, b, c); |
135 | 12.2M | keylen -= 3 * static_cast<uint32>(sizeof(a)); |
136 | 12.2M | } |
137 | 63.2M | c += len; |
138 | 63.2M | switch ( keylen ) { // deal with rest. Cases fall through |
139 | 6.09M | case 11: c += char2unsigned(s[10]) << 24; FALLTHROUGH_INTENDED; |
140 | 11.6M | case 10: c += char2unsigned(s[9]) << 16; FALLTHROUGH_INTENDED; |
141 | 17.2M | case 9 : c += char2unsigned(s[8]) << 8; FALLTHROUGH_INTENDED; |
142 | 22.6M | case 8 : b += Google1At(s+4); a += Google1At(s); break; |
143 | 3.42M | case 7 : b += char2unsigned(s[6]) << 16; FALLTHROUGH_INTENDED; |
144 | 5.32M | case 6 : b += char2unsigned(s[5]) << 8; FALLTHROUGH_INTENDED; |
145 | 13.5M | case 5 : b += char2unsigned(s[4]); FALLTHROUGH_INTENDED; |
146 | 19.2M | case 4 : a += Google1At(s); break; |
147 | 3.51M | case 3 : a += char2unsigned(s[2]) << 16; FALLTHROUGH_INTENDED; |
148 | 12.5M | case 2 : a += char2unsigned(s[1]) << 8; FALLTHROUGH_INTENDED; |
149 | 18.3M | case 1 : a += char2unsigned(s[0]); |
150 | 63.2M | } |
151 | 63.2M | } |
152 | 70.2M | mix(a, b, c); |
153 | 70.2M | return c; |
154 | 70.2M | } |
155 | | |
156 | 16.7M | uint64 Hash64StringWithSeed(const char *s, size_t len, uint64 c) { |
157 | 16.7M | uint64 a, b; |
158 | 16.7M | size_t keylen; |
159 | | |
160 | 16.7M | a = b = GG_ULONGLONG(0xe08c1d668b756f82); // the golden ratio; an arbitrary value |
161 | | |
162 | 27.3M | for ( keylen = len; keylen >= 3 * sizeof(a); |
163 | 10.5M | keylen -= 3 * static_cast<uint32>(sizeof(a)), s += 3 * sizeof(a) ) { |
164 | 10.5M | a += Word64At(s); |
165 | 10.5M | b += Word64At(s + sizeof(a)); |
166 | 10.5M | c += Word64At(s + sizeof(a) * 2); |
167 | 10.5M | mix(a, b, c); |
168 | 10.5M | } |
169 | | |
170 | 16.7M | c += len; |
171 | 16.7M | switch ( keylen ) { // deal with rest. Cases fall through |
172 | 64 | case 23: c += char2unsigned64(s[22]) << 56; FALLTHROUGH_INTENDED; |
173 | 93 | case 22: c += char2unsigned64(s[21]) << 48; FALLTHROUGH_INTENDED; |
174 | 8.29k | case 21: c += char2unsigned64(s[20]) << 40; FALLTHROUGH_INTENDED; |
175 | 9.17k | case 20: c += char2unsigned64(s[19]) << 32; FALLTHROUGH_INTENDED; |
176 | 11.2k | case 19: c += char2unsigned64(s[18]) << 24; FALLTHROUGH_INTENDED; |
177 | 18.6k | case 18: c += char2unsigned64(s[17]) << 16; FALLTHROUGH_INTENDED; |
178 | 3.88M | case 17: c += char2unsigned64(s[16]) << 8; FALLTHROUGH_INTENDED; |
179 | | // the first byte of c is reserved for the length |
180 | 7.28M | case 16: b += Word64At(s+8); a += Word64At(s); break; |
181 | 1.45M | case 15: b += char2unsigned64(s[14]) << 48; FALLTHROUGH_INTENDED; |
182 | 3.13M | case 14: b += char2unsigned64(s[13]) << 40; FALLTHROUGH_INTENDED; |
183 | 3.14M | case 13: b += char2unsigned64(s[12]) << 32; FALLTHROUGH_INTENDED; |
184 | 3.28M | case 12: b += char2unsigned64(s[11]) << 24; FALLTHROUGH_INTENDED; |
185 | 3.52M | case 11: b += char2unsigned64(s[10]) << 16; FALLTHROUGH_INTENDED; |
186 | 3.57M | case 10: b += char2unsigned64(s[ 9]) << 8; FALLTHROUGH_INTENDED; |
187 | 3.61M | case 9: b += char2unsigned64(s[ 8]) ; FALLTHROUGH_INTENDED; |
188 | 4.04M | case 8: a += Word64At(s); break; |
189 | 47.8k | case 7: a += char2unsigned64(s[ 6]) << 48; FALLTHROUGH_INTENDED; |
190 | 51.1k | case 6: a += char2unsigned64(s[ 5]) << 40; FALLTHROUGH_INTENDED; |
191 | 122k | case 5: a += char2unsigned64(s[ 4]) << 32; FALLTHROUGH_INTENDED; |
192 | 5.38M | case 4: a += char2unsigned64(s[ 3]) << 24; FALLTHROUGH_INTENDED; |
193 | 5.38M | case 3: a += char2unsigned64(s[ 2]) << 16; FALLTHROUGH_INTENDED; |
194 | 5.44M | case 2: a += char2unsigned64(s[ 1]) << 8; FALLTHROUGH_INTENDED; |
195 | 5.46M | case 1: a += char2unsigned64(s[ 0]); |
196 | | // case 0: nothing left to add |
197 | 16.7M | } |
198 | 16.7M | mix(a, b, c); |
199 | 16.7M | return c; |
200 | 16.7M | } |