00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef UTIL_JENKINSHASH_C_DEFINED
00015 #define UTIL_JENKINSHASH_C_DEFINED
00016
00017 #include "Util/jenkinshash.H"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <stddef.h>
00031 #include <stdlib.h>
00032
00033 namespace
00034 {
00035
00036 typedef uint32 ub4;
00037 typedef byte ub1;
00038
00039 #define hashsize(n) ((ub4)1<<(n))
00040 #define hashmask(n) (hashsize(n)-1)
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define mix(a,b,c) \
00069 { \
00070 a -= b; a -= c; a ^= (c>>13); \
00071 b -= c; b -= a; b ^= (a<<8); \
00072 c -= a; c -= b; c ^= (b>>13); \
00073 a -= b; a -= c; a ^= (c>>12); \
00074 b -= c; b -= a; b ^= (a<<16); \
00075 c -= a; c -= b; c ^= (b>>5); \
00076 a -= b; a -= c; a ^= (c>>3); \
00077 b -= c; b -= a; b ^= (a<<10); \
00078 c -= a; c -= b; c ^= (b>>15); \
00079 }
00080
00081
00082 #define mix2(a,b,c) \
00083 { \
00084 a -= b; a -= c; a ^= (c>>13); \
00085 b -= c; b -= a; b ^= (a<< 8); \
00086 c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
00087 a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
00088 b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
00089 c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
00090 a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
00091 b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
00092 c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 ub4 hash(const ub1* k,
00124 const ub4 length,
00125 const ub4 initval)
00126 {
00127 ub4 a,b,c,len;
00128
00129
00130 len = length;
00131 a = b = 0x9e3779b9;
00132 c = initval;
00133
00134
00135 while (len >= 12)
00136 {
00137 a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
00138 b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
00139 c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
00140 mix(a,b,c);
00141 k += 12; len -= 12;
00142 }
00143
00144
00145 c += length;
00146 switch(len)
00147 {
00148 case 11: c+=((ub4)k[10]<<24);
00149 case 10: c+=((ub4)k[9]<<16);
00150 case 9 : c+=((ub4)k[8]<<8);
00151
00152 case 8 : b+=((ub4)k[7]<<24);
00153 case 7 : b+=((ub4)k[6]<<16);
00154 case 6 : b+=((ub4)k[5]<<8);
00155 case 5 : b+=k[4];
00156 case 4 : a+=((ub4)k[3]<<24);
00157 case 3 : a+=((ub4)k[2]<<16);
00158 case 2 : a+=((ub4)k[1]<<8);
00159 case 1 : a+=k[0];
00160
00161 }
00162 mix(a,b,c);
00163
00164 return c;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 ub4 hash2(const ub4 *k,
00180 const ub4 length,
00181 const ub4 initval)
00182 {
00183 ub4 a,b,c,len;
00184
00185
00186 len = length;
00187 a = b = 0x9e3779b9;
00188 c = initval;
00189
00190
00191 while (len >= 3)
00192 {
00193 a += k[0];
00194 b += k[1];
00195 c += k[2];
00196 mix(a,b,c);
00197 k += 3; len -= 3;
00198 }
00199
00200
00201 c += length;
00202 switch(len)
00203 {
00204
00205 case 2 : b+=k[1];
00206 case 1 : a+=k[0];
00207
00208 }
00209 mix(a,b,c);
00210
00211 return c;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 ub4 hash3(const ub1 *k,
00225 const ub4 length,
00226 const ub4 initval)
00227 {
00228 ub4 a,b,c,len;
00229
00230
00231 len = length;
00232 a = b = 0x9e3779b9;
00233 c = initval;
00234
00235
00236 if (((unsigned long)k)&3)
00237 {
00238 while (len >= 12)
00239 {
00240 a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
00241 b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
00242 c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
00243 mix(a,b,c);
00244 k += 12; len -= 12;
00245 }
00246 }
00247 else
00248 {
00249 while (len >= 12)
00250 {
00251 a += *(ub4 *)(k+0);
00252 b += *(ub4 *)(k+4);
00253 c += *(ub4 *)(k+8);
00254 mix(a,b,c);
00255 k += 12; len -= 12;
00256 }
00257 }
00258
00259
00260 c += length;
00261 switch(len)
00262 {
00263 case 11: c+=((ub4)k[10]<<24);
00264 case 10: c+=((ub4)k[9]<<16);
00265 case 9 : c+=((ub4)k[8]<<8);
00266
00267 case 8 : b+=((ub4)k[7]<<24);
00268 case 7 : b+=((ub4)k[6]<<16);
00269 case 6 : b+=((ub4)k[5]<<8);
00270 case 5 : b+=k[4];
00271 case 4 : a+=((ub4)k[3]<<24);
00272 case 3 : a+=((ub4)k[2]<<16);
00273 case 2 : a+=((ub4)k[1]<<8);
00274 case 1 : a+=k[0];
00275
00276 }
00277 mix(a,b,c);
00278
00279 return c;
00280 }
00281
00282
00283
00284
00285 void driver1()
00286 {
00287 ub1 buf[1024];
00288 ub4 i;
00289 ub4 h=0;
00290
00291 for (i=0; i<256; ++i)
00292 {
00293 h = hash(buf,i,h);
00294 }
00295 }
00296
00297
00298 #define HASHSTATE 1
00299 #define HASHLEN 1
00300 #define MAXPAIR 80
00301 #define MAXLEN 70
00302 void driver2()
00303 {
00304 ub1 qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
00305 ub4 c[HASHSTATE], d[HASHSTATE], i, j=0, k, l, m=1, z;
00306 ub4 e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
00307 ub4 x[HASHSTATE],y[HASHSTATE];
00308 ub4 hlen;
00309
00310 printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
00311 for (hlen=0; hlen < MAXLEN; ++hlen)
00312 {
00313 z=0;
00314 for (i=0; i<hlen; ++i)
00315 {
00316 for (j=0; j<8; ++j)
00317 {
00318 for (m=1; m<8; ++m)
00319 {
00320 for (l=0; l<HASHSTATE; ++l) e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((ub4)0);
00321
00322
00323 for (k=0; k<MAXPAIR; k+=2)
00324 {
00325 ub4 finished=1;
00326
00327 for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (ub1)0;}
00328
00329 a[i] ^= (k<<j);
00330 a[i] ^= (k>>(8-j));
00331 c[0] = hash(a, hlen, m);
00332 b[i] ^= ((k+1)<<j);
00333 b[i] ^= ((k+1)>>(8-j));
00334 d[0] = hash(b, hlen, m);
00335
00336 for (l=0; l<HASHSTATE; ++l)
00337 {
00338 e[l] &= (c[l]^d[l]);
00339 f[l] &= ~(c[l]^d[l]);
00340 g[l] &= c[l];
00341 h[l] &= ~c[l];
00342 x[l] &= d[l];
00343 y[l] &= ~d[l];
00344 if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
00345 }
00346 if (finished) break;
00347 }
00348 if (k>z) z=k;
00349 if (k==MAXPAIR)
00350 {
00351 printf("Some bit didn't change: ");
00352 printf("%x %x %x %x %x %x ",
00353 e[0],f[0],g[0],h[0],x[0],y[0]);
00354 printf("i %d j %d m %d len %d\n",i,j,m,hlen);
00355 }
00356 if (z==MAXPAIR) goto done;
00357 }
00358 }
00359 }
00360 done:
00361 if (z < MAXPAIR)
00362 {
00363 printf("Mix success %2d bytes %2d initvals ",i,m);
00364 printf("required %d trials\n",z/2);
00365 }
00366 }
00367 printf("\n");
00368 }
00369
00370
00371 void driver3()
00372 {
00373 ub1 buf[MAXLEN+20], *b;
00374 ub4 len;
00375 ub1 q[] = "This is the time for all good men to come to the aid of their country";
00376 ub1 qq[] = "xThis is the time for all good men to come to the aid of their country";
00377 ub1 qqq[] = "xxThis is the time for all good men to come to the aid of their country";
00378 ub1 qqqq[] = "xxxThis is the time for all good men to come to the aid of their country";
00379 ub4 h,i,j,ref,x,y;
00380
00381 printf("Endianness. These should all be the same:\n");
00382 printf("%x\n", hash(q, sizeof(q)-1, (ub4)0));
00383 printf("%x\n", hash(qq+1, sizeof(q)-1, (ub4)0));
00384 printf("%x\n", hash(qqq+2, sizeof(q)-1, (ub4)0));
00385 printf("%x\n", hash(qqqq+3, sizeof(q)-1, (ub4)0));
00386 printf("\n");
00387 for (h=0, b=buf+1; h<8; ++h, ++b)
00388 {
00389 for (i=0; i<MAXLEN; ++i)
00390 {
00391 len = i;
00392 for (j=0; j<i; ++j) *(b+j)=0;
00393
00394
00395 ref = hash(b, len, (ub4)1);
00396 *(b+i)=(ub1)~0;
00397 *(b-1)=(ub1)~0;
00398 x = hash(b, len, (ub4)1);
00399 y = hash(b, len, (ub4)1);
00400 if ((ref != x) || (ref != y))
00401 {
00402 printf("alignment error: %x %x %x %d %d\n",ref,x,y,h,i);
00403 }
00404 }
00405 }
00406 }
00407
00408
00409 void driver4()
00410 {
00411 ub1 buf[1];
00412 ub4 h,i;
00413
00414
00415 buf[0] = ~0;
00416 printf("These should all be different\n");
00417 for (i=0, h=0; i<8; ++i)
00418 {
00419 h = hash(buf, (ub4)0, h);
00420 printf("%2d 0-byte strings, hash is %x\n", i, h);
00421 }
00422 }
00423
00424 }
00425
00426 #ifdef SELF_TEST
00427
00428 int main()
00429 {
00430 driver1();
00431 driver2();
00432 driver3();
00433 driver4();
00434 return 1;
00435 }
00436
00437 #endif
00438
00439 #include "rutz/trace.h"
00440
00441 uint32 jenkinshash(const byte* key, uint32 length, uint32 initval)
00442 {
00443 GVX_TRACE(__PRETTY_FUNCTION__);
00444 return hash(key, length, initval);
00445 }
00446
00447 uint32 jenkinshash2(const uint32* key, uint32 length, uint32 initval)
00448 {
00449 GVX_TRACE(__PRETTY_FUNCTION__);
00450 return hash2(key, length, initval);
00451 }
00452
00453
00454
00455
00456
00457
00458
00459 #endif // UTIL_JENKINSHASH_C_DEFINED