mirror of
https://github.com/Kaehvaman/OAIP.git
synced 2025-01-18 08:39:11 +04:00
48 lines
1.8 KiB
C
48 lines
1.8 KiB
C
#pragma once
|
|
|
|
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
|
|
typedef unsigned char ub1;
|
|
|
|
#define hashsize(n) ((ub4)1<<(n))
|
|
#define hashmask(n) (hashsize(n)-1)
|
|
|
|
/*
|
|
--------------------------------------------------------------------
|
|
mix -- mix 3 32-bit values reversibly.
|
|
For every delta with one or two bit set, and the deltas of all three
|
|
high bits or all three low bits, whether the original value of a,b,c
|
|
is almost all zero or is uniformly distributed,
|
|
* If mix() is run forward or backward, at least 32 bits in a,b,c
|
|
have at least 1/4 probability of changing.
|
|
* If mix() is run forward, every bit of c will change between 1/3 and
|
|
2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
|
|
mix() was built out of 36 single-cycle latency instructions in a
|
|
structure that could supported 2x parallelism, like so:
|
|
a -= b;
|
|
a -= c; x = (c>>13);
|
|
b -= c; a ^= x;
|
|
b -= a; x = (a<<8);
|
|
c -= a; b ^= x;
|
|
c -= b; x = (b>>13);
|
|
...
|
|
Unfortunately, superscalar Pentiums and Sparcs can't take advantage
|
|
of that parallelism. They've also turned some of those single-cycle
|
|
latency instructions into multi-cycle latency instructions. Still,
|
|
this is the fastest good hash I could find. There were about 2^^68
|
|
to choose from. I only looked at a billion or so.
|
|
--------------------------------------------------------------------
|
|
*/
|
|
#define mix(a,b,c) \
|
|
{ \
|
|
a -= b; a -= c; a ^= (c>>13); \
|
|
b -= c; b -= a; b ^= (a<<8); \
|
|
c -= a; c -= b; c ^= (b>>13); \
|
|
a -= b; a -= c; a ^= (c>>12); \
|
|
b -= c; b -= a; b ^= (a<<16); \
|
|
c -= a; c -= b; c ^= (b>>5); \
|
|
a -= b; a -= c; a ^= (c>>3); \
|
|
b -= c; b -= a; b ^= (a<<10); \
|
|
c -= a; c -= b; c ^= (b>>15); \
|
|
}
|
|
|
|
ub4 jhash(register ub1* k, register ub4 length, register ub4 initval); |