Commit 0953f929 authored by Rusty Russell's avatar Rusty Russell

Move hash into ccan/ dir

parent f51dd128
#include <string.h>
/**
* hash - routines for hashing bytes
*
......
......@@ -59,9 +59,9 @@
* a 32-bit hash.
*
* This hash will have the same results on different machines, so can
* be used for external hashes (ie. not hashes sent across the network
* or saved to disk). The results will not change in future versions
* of this package.
* be used for external hashes (ie. hashes sent across the network or
* saved to disk). The results will not change in future versions of
* this module.
*
* Example:
* #include "hash/hash.h"
......@@ -97,6 +97,31 @@
*/
uint32_t hash_u32(const uint32_t *key, size_t num, uint32_t base);
/**
* hash_string - very fast hash of an ascii string
* @str: the nul-terminated string
*
* The string is hashed, using a hash function optimized for ASCII and
* similar strings. It's weaker than the other hash functions.
*
* This hash may have different results on different machines, so is
* only useful for internal hashes (ie. not hashes sent across the
* network or saved to disk). The results will be different from the
* other hash functions in this module, too.
*/
static inline uint32_t hash_string(const char *string)
{
/* This is Karl Nelson <kenelson@ece.ucdavis.edu>'s X31 hash.
* It's a little faster than the (much better) lookup3 hash(): 56ns vs
* 84ns on my 2GHz Intel Core Duo 2 laptop for a 10 char string. */
uint32_t ret;
for (ret = 0; *string; string++)
ret = (ret << 5) - ret + *string;
return ret;
}
/* Our underlying operations. */
uint32_t hash_any(const void *key, size_t length, uint32_t base);
uint32_t hash_any_stable(const void *key, size_t length, uint32_t base);
......@@ -153,7 +178,7 @@ static inline uint32_t hash_pointer(const void *p, uint32_t base)
} u;
u.p = p;
return hash_u32(u.u32, sizeof(p) / sizeof(uint32_t), base);
}
return hash(&p, 1, base);
} else
return hash(&p, 1, base);
}
#endif /* HASH_H */
......@@ -17,7 +17,7 @@ int main(int argc, char *argv[])
for (i = 0; i < ARRAY_WORDS; i++)
array[i] = i;
plan_tests(53);
plan_tests(55);
/* hash_stable is guaranteed. */
ok1(hash_stable(array, ARRAY_WORDS, 0) == 0x13305f8c);
......@@ -111,5 +111,42 @@ int main(int argc, char *argv[])
diag("hash_pointer byte %i, range %u-%u", i, lowest, highest);
}
/* String hash: weak, so only test bottom byte */
for (i = 0; i < 1; i++) {
unsigned int num = 0, cursor, lowest = -1U, highest = 0;
char p[5];
memset(results, 0, sizeof(results));
memset(p, 'A', sizeof(p));
p[sizeof(p)-1] = '\0';
for (;;) {
for (cursor = 0; cursor < sizeof(p)-1; cursor++) {
p[cursor]++;
if (p[cursor] <= 'z')
break;
p[cursor] = 'A';
}
if (cursor == sizeof(p)-1)
break;
results[(hash_string(p) >> i*8)&0xFF]++;
num++;
}
for (j = 0; j < 256; j++) {
if (results[j] < lowest)
lowest = results[j];
if (results[j] > highest)
highest = results[j];
}
/* Expect within 20% */
ok(lowest > 35000, "hash_pointer byte %i lowest %i", i, lowest);
ok(highest < 53000, "hash_pointer byte %i highest %i",
i, highest);
diag("hash_pointer byte %i, range %u-%u", i, lowest, highest);
}
return exit_status();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment