summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/hashtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/hashtab.c')
-rw-r--r--contrib/gcc/hashtab.c853
1 files changed, 0 insertions, 853 deletions
diff --git a/contrib/gcc/hashtab.c b/contrib/gcc/hashtab.c
deleted file mode 100644
index 231fbc0..0000000
--- a/contrib/gcc/hashtab.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/* An expandable hash tables datatype.
- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
- Contributed by Vladimir Makarov (vmakarov@cygnus.com).
-
-This file is part of the libiberty library.
-Libiberty is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public
-License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-Libiberty is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with libiberty; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* This package implements basic hash table functionality. It is possible
- to search for an entry, create an entry and destroy an entry.
-
- Elements in the table are generic pointers.
-
- The size of the table is not fixed; if the occupancy of the table
- grows too high the hash table will be expanded.
-
- The abstract data implementation is based on generalized Algorithm D
- from Knuth's book "The art of computer programming". Hash table is
- expanded by creation of new hash table and transferring elements from
- the old table to the new table. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-#include <stdio.h>
-
-#include "libiberty.h"
-#include "hashtab.h"
-
-/* This macro defines reserved value for empty table entry. */
-
-#define EMPTY_ENTRY ((PTR) 0)
-
-/* This macro defines reserved value for table entry which contained
- a deleted element. */
-
-#define DELETED_ENTRY ((PTR) 1)
-
-static unsigned long higher_prime_number PARAMS ((unsigned long));
-static hashval_t hash_pointer PARAMS ((const void *));
-static int eq_pointer PARAMS ((const void *, const void *));
-static int htab_expand PARAMS ((htab_t));
-static PTR *find_empty_slot_for_expand PARAMS ((htab_t, hashval_t));
-
-/* At some point, we could make these be NULL, and modify the
- hash-table routines to handle NULL specially; that would avoid
- function-call overhead for the common case of hashing pointers. */
-htab_hash htab_hash_pointer = hash_pointer;
-htab_eq htab_eq_pointer = eq_pointer;
-
-/* The following function returns a nearest prime number which is
- greater than N, and near a power of two. */
-
-static unsigned long
-higher_prime_number (n)
- unsigned long n;
-{
- /* These are primes that are near, but slightly smaller than, a
- power of two. */
- static const unsigned long primes[] = {
- (unsigned long) 7,
- (unsigned long) 13,
- (unsigned long) 31,
- (unsigned long) 61,
- (unsigned long) 127,
- (unsigned long) 251,
- (unsigned long) 509,
- (unsigned long) 1021,
- (unsigned long) 2039,
- (unsigned long) 4093,
- (unsigned long) 8191,
- (unsigned long) 16381,
- (unsigned long) 32749,
- (unsigned long) 65521,
- (unsigned long) 131071,
- (unsigned long) 262139,
- (unsigned long) 524287,
- (unsigned long) 1048573,
- (unsigned long) 2097143,
- (unsigned long) 4194301,
- (unsigned long) 8388593,
- (unsigned long) 16777213,
- (unsigned long) 33554393,
- (unsigned long) 67108859,
- (unsigned long) 134217689,
- (unsigned long) 268435399,
- (unsigned long) 536870909,
- (unsigned long) 1073741789,
- (unsigned long) 2147483647,
- /* 4294967291L */
- ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
- };
-
- const unsigned long *low = &primes[0];
- const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])];
-
- while (low != high)
- {
- const unsigned long *mid = low + (high - low) / 2;
- if (n > *mid)
- low = mid + 1;
- else
- high = mid;
- }
-
- /* If we've run out of primes, abort. */
- if (n > *low)
- {
- fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
- abort ();
- }
-
- return *low;
-}
-
-/* Returns a hash code for P. */
-
-static hashval_t
-hash_pointer (p)
- const PTR p;
-{
- return (hashval_t) ((long)p >> 3);
-}
-
-/* Returns non-zero if P1 and P2 are equal. */
-
-static int
-eq_pointer (p1, p2)
- const PTR p1;
- const PTR p2;
-{
- return p1 == p2;
-}
-
-/* This function creates table with length slightly longer than given
- source length. Created hash table is initiated as empty (all the
- hash table entries are EMPTY_ENTRY). The function returns the
- created hash table, or NULL if memory allocation fails. */
-
-htab_t
-htab_create_alloc (size, hash_f, eq_f, del_f, alloc_f, free_f)
- size_t size;
- htab_hash hash_f;
- htab_eq eq_f;
- htab_del del_f;
- htab_alloc alloc_f;
- htab_free free_f;
-{
- htab_t result;
-
- size = higher_prime_number (size);
- result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
- if (result == NULL)
- return NULL;
- result->entries = (PTR *) (*alloc_f) (size, sizeof (PTR));
- if (result->entries == NULL)
- {
- if (free_f != NULL)
- (*free_f) (result);
- return NULL;
- }
- result->size = size;
- result->hash_f = hash_f;
- result->eq_f = eq_f;
- result->del_f = del_f;
- result->alloc_f = alloc_f;
- result->free_f = free_f;
- return result;
-}
-
-/* As above, but use the variants of alloc_f and free_f which accept
- an extra argument. */
-
-htab_t
-htab_create_alloc_ex (size, hash_f, eq_f, del_f, alloc_arg, alloc_f,
- free_f)
- size_t size;
- htab_hash hash_f;
- htab_eq eq_f;
- htab_del del_f;
- PTR alloc_arg;
- htab_alloc_with_arg alloc_f;
- htab_free_with_arg free_f;
-{
- htab_t result;
-
- size = higher_prime_number (size);
- result = (htab_t) (*alloc_f) (alloc_arg, 1, sizeof (struct htab));
- if (result == NULL)
- return NULL;
- result->entries = (PTR *) (*alloc_f) (alloc_arg, size, sizeof (PTR));
- if (result->entries == NULL)
- {
- if (free_f != NULL)
- (*free_f) (alloc_arg, result);
- return NULL;
- }
- result->size = size;
- result->hash_f = hash_f;
- result->eq_f = eq_f;
- result->del_f = del_f;
- result->alloc_arg = alloc_arg;
- result->alloc_with_arg_f = alloc_f;
- result->free_with_arg_f = free_f;
- return result;
-}
-
-/* Update the function pointers and allocation parameter in the htab_t. */
-
-void
-htab_set_functions_ex (htab, hash_f, eq_f, del_f, alloc_arg, alloc_f, free_f)
- htab_t htab;
- htab_hash hash_f;
- htab_eq eq_f;
- htab_del del_f;
- PTR alloc_arg;
- htab_alloc_with_arg alloc_f;
- htab_free_with_arg free_f;
-{
- htab->hash_f = hash_f;
- htab->eq_f = eq_f;
- htab->del_f = del_f;
- htab->alloc_arg = alloc_arg;
- htab->alloc_with_arg_f = alloc_f;
- htab->free_with_arg_f = free_f;
-}
-
-/* These functions exist solely for backward compatibility. */
-
-#undef htab_create
-htab_t
-htab_create (size, hash_f, eq_f, del_f)
- size_t size;
- htab_hash hash_f;
- htab_eq eq_f;
- htab_del del_f;
-{
- return htab_create_alloc (size, hash_f, eq_f, del_f, xcalloc, free);
-}
-
-htab_t
-htab_try_create (size, hash_f, eq_f, del_f)
- size_t size;
- htab_hash hash_f;
- htab_eq eq_f;
- htab_del del_f;
-{
- return htab_create_alloc (size, hash_f, eq_f, del_f, calloc, free);
-}
-
-/* This function frees all memory allocated for given hash table.
- Naturally the hash table must already exist. */
-
-void
-htab_delete (htab)
- htab_t htab;
-{
- int i;
-
- if (htab->del_f)
- for (i = htab->size - 1; i >= 0; i--)
- if (htab->entries[i] != EMPTY_ENTRY
- && htab->entries[i] != DELETED_ENTRY)
- (*htab->del_f) (htab->entries[i]);
-
- if (htab->free_f != NULL)
- {
- (*htab->free_f) (htab->entries);
- (*htab->free_f) (htab);
- }
- else if (htab->free_with_arg_f != NULL)
- {
- (*htab->free_with_arg_f) (htab->alloc_arg, htab->entries);
- (*htab->free_with_arg_f) (htab->alloc_arg, htab);
- }
-}
-
-/* This function clears all entries in the given hash table. */
-
-void
-htab_empty (htab)
- htab_t htab;
-{
- int i;
-
- if (htab->del_f)
- for (i = htab->size - 1; i >= 0; i--)
- if (htab->entries[i] != EMPTY_ENTRY
- && htab->entries[i] != DELETED_ENTRY)
- (*htab->del_f) (htab->entries[i]);
-
- memset (htab->entries, 0, htab->size * sizeof (PTR));
-}
-
-/* Similar to htab_find_slot, but without several unwanted side effects:
- - Does not call htab->eq_f when it finds an existing entry.
- - Does not change the count of elements/searches/collisions in the
- hash table.
- This function also assumes there are no deleted entries in the table.
- HASH is the hash value for the element to be inserted. */
-
-static PTR *
-find_empty_slot_for_expand (htab, hash)
- htab_t htab;
- hashval_t hash;
-{
- size_t size = htab->size;
- unsigned int index = hash % size;
- PTR *slot = htab->entries + index;
- hashval_t hash2;
-
- if (*slot == EMPTY_ENTRY)
- return slot;
- else if (*slot == DELETED_ENTRY)
- abort ();
-
- hash2 = 1 + hash % (size - 2);
- for (;;)
- {
- index += hash2;
- if (index >= size)
- index -= size;
-
- slot = htab->entries + index;
- if (*slot == EMPTY_ENTRY)
- return slot;
- else if (*slot == DELETED_ENTRY)
- abort ();
- }
-}
-
-/* The following function changes size of memory allocated for the
- entries and repeatedly inserts the table elements. The occupancy
- of the table after the call will be about 50%. Naturally the hash
- table must already exist. Remember also that the place of the
- table entries is changed. If memory allocation failures are allowed,
- this function will return zero, indicating that the table could not be
- expanded. If all goes well, it will return a non-zero value. */
-
-static int
-htab_expand (htab)
- htab_t htab;
-{
- PTR *oentries;
- PTR *olimit;
- PTR *p;
- PTR *nentries;
- size_t nsize;
-
- oentries = htab->entries;
- olimit = oentries + htab->size;
-
- /* Resize only when table after removal of unused elements is either
- too full or too empty. */
- if ((htab->n_elements - htab->n_deleted) * 2 > htab->size
- || ((htab->n_elements - htab->n_deleted) * 8 < htab->size
- && htab->size > 32))
- nsize = higher_prime_number ((htab->n_elements - htab->n_deleted) * 2);
- else
- nsize = htab->size;
-
- if (htab->alloc_with_arg_f != NULL)
- nentries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
- sizeof (PTR *));
- else
- nentries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR *));
- if (nentries == NULL)
- return 0;
- htab->entries = nentries;
- htab->size = nsize;
-
- htab->n_elements -= htab->n_deleted;
- htab->n_deleted = 0;
-
- p = oentries;
- do
- {
- PTR x = *p;
-
- if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
- {
- PTR *q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x));
-
- *q = x;
- }
-
- p++;
- }
- while (p < olimit);
-
- if (htab->free_f != NULL)
- (*htab->free_f) (oentries);
- else if (htab->free_with_arg_f != NULL)
- (*htab->free_with_arg_f) (htab->alloc_arg, oentries);
- return 1;
-}
-
-/* This function searches for a hash table entry equal to the given
- element. It cannot be used to insert or delete an element. */
-
-PTR
-htab_find_with_hash (htab, element, hash)
- htab_t htab;
- const PTR element;
- hashval_t hash;
-{
- unsigned int index;
- hashval_t hash2;
- size_t size;
- PTR entry;
-
- htab->searches++;
- size = htab->size;
- index = hash % size;
-
- entry = htab->entries[index];
- if (entry == EMPTY_ENTRY
- || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)))
- return entry;
-
- hash2 = 1 + hash % (size - 2);
-
- for (;;)
- {
- htab->collisions++;
- index += hash2;
- if (index >= size)
- index -= size;
-
- entry = htab->entries[index];
- if (entry == EMPTY_ENTRY
- || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)))
- return entry;
- }
-}
-
-/* Like htab_find_slot_with_hash, but compute the hash value from the
- element. */
-
-PTR
-htab_find (htab, element)
- htab_t htab;
- const PTR element;
-{
- return htab_find_with_hash (htab, element, (*htab->hash_f) (element));
-}
-
-/* This function searches for a hash table slot containing an entry
- equal to the given element. To delete an entry, call this with
- INSERT = 0, then call htab_clear_slot on the slot returned (possibly
- after doing some checks). To insert an entry, call this with
- INSERT = 1, then write the value you want into the returned slot.
- When inserting an entry, NULL may be returned if memory allocation
- fails. */
-
-PTR *
-htab_find_slot_with_hash (htab, element, hash, insert)
- htab_t htab;
- const PTR element;
- hashval_t hash;
- enum insert_option insert;
-{
- PTR *first_deleted_slot;
- unsigned int index;
- hashval_t hash2;
- size_t size;
- PTR entry;
-
- if (insert == INSERT && htab->size * 3 <= htab->n_elements * 4
- && htab_expand (htab) == 0)
- return NULL;
-
- size = htab->size;
- index = hash % size;
-
- htab->searches++;
- first_deleted_slot = NULL;
-
- entry = htab->entries[index];
- if (entry == EMPTY_ENTRY)
- goto empty_entry;
- else if (entry == DELETED_ENTRY)
- first_deleted_slot = &htab->entries[index];
- else if ((*htab->eq_f) (entry, element))
- return &htab->entries[index];
-
- hash2 = 1 + hash % (size - 2);
- for (;;)
- {
- htab->collisions++;
- index += hash2;
- if (index >= size)
- index -= size;
-
- entry = htab->entries[index];
- if (entry == EMPTY_ENTRY)
- goto empty_entry;
- else if (entry == DELETED_ENTRY)
- {
- if (!first_deleted_slot)
- first_deleted_slot = &htab->entries[index];
- }
- else if ((*htab->eq_f) (entry, element))
- return &htab->entries[index];
- }
-
- empty_entry:
- if (insert == NO_INSERT)
- return NULL;
-
- if (first_deleted_slot)
- {
- htab->n_deleted--;
- *first_deleted_slot = EMPTY_ENTRY;
- return first_deleted_slot;
- }
-
- htab->n_elements++;
- return &htab->entries[index];
-}
-
-/* Like htab_find_slot_with_hash, but compute the hash value from the
- element. */
-
-PTR *
-htab_find_slot (htab, element, insert)
- htab_t htab;
- const PTR element;
- enum insert_option insert;
-{
- return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element),
- insert);
-}
-
-/* This function deletes an element with the given value from hash
- table. If there is no matching element in the hash table, this
- function does nothing. */
-
-void
-htab_remove_elt (htab, element)
- htab_t htab;
- PTR element;
-{
- PTR *slot;
-
- slot = htab_find_slot (htab, element, NO_INSERT);
- if (*slot == EMPTY_ENTRY)
- return;
-
- if (htab->del_f)
- (*htab->del_f) (*slot);
-
- *slot = DELETED_ENTRY;
- htab->n_deleted++;
-}
-
-/* This function clears a specified slot in a hash table. It is
- useful when you've already done the lookup and don't want to do it
- again. */
-
-void
-htab_clear_slot (htab, slot)
- htab_t htab;
- PTR *slot;
-{
- if (slot < htab->entries || slot >= htab->entries + htab->size
- || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY)
- abort ();
-
- if (htab->del_f)
- (*htab->del_f) (*slot);
-
- *slot = DELETED_ENTRY;
- htab->n_deleted++;
-}
-
-/* This function scans over the entire hash table calling
- CALLBACK for each live entry. If CALLBACK returns false,
- the iteration stops. INFO is passed as CALLBACK's second
- argument. */
-
-void
-htab_traverse_noresize (htab, callback, info)
- htab_t htab;
- htab_trav callback;
- PTR info;
-{
- PTR *slot;
- PTR *limit;
-
- slot = htab->entries;
- limit = slot + htab->size;
-
- do
- {
- PTR x = *slot;
-
- if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
- if (!(*callback) (slot, info))
- break;
- }
- while (++slot < limit);
-}
-
-/* Like htab_traverse_noresize, but does resize the table when it is
- too empty to improve effectivity of subsequent calls. */
-
-void
-htab_traverse (htab, callback, info)
- htab_t htab;
- htab_trav callback;
- PTR info;
-{
- if ((htab->n_elements - htab->n_deleted) * 8 < htab->size)
- htab_expand (htab);
-
- htab_traverse_noresize (htab, callback, info);
-}
-
-/* Return the current size of given hash table. */
-
-size_t
-htab_size (htab)
- htab_t htab;
-{
- return htab->size;
-}
-
-/* Return the current number of elements in given hash table. */
-
-size_t
-htab_elements (htab)
- htab_t htab;
-{
- return htab->n_elements - htab->n_deleted;
-}
-
-/* Return the fraction of fixed collisions during all work with given
- hash table. */
-
-double
-htab_collisions (htab)
- htab_t htab;
-{
- if (htab->searches == 0)
- return 0.0;
-
- return (double) htab->collisions / (double) htab->searches;
-}
-
-/* Hash P as a null-terminated string.
-
- Copied from gcc/hashtable.c. Zack had the following to say with respect
- to applicability, though note that unlike hashtable.c, this hash table
- implementation re-hashes rather than chain buckets.
-
- http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01021.html
- From: Zack Weinberg <zackw@panix.com>
- Date: Fri, 17 Aug 2001 02:15:56 -0400
-
- I got it by extracting all the identifiers from all the source code
- I had lying around in mid-1999, and testing many recurrences of
- the form "H_n = H_{n-1} * K + c_n * L + M" where K, L, M were either
- prime numbers or the appropriate identity. This was the best one.
- I don't remember exactly what constituted "best", except I was
- looking at bucket-length distributions mostly.
-
- So it should be very good at hashing identifiers, but might not be
- as good at arbitrary strings.
-
- I'll add that it thoroughly trounces the hash functions recommended
- for this use at http://burtleburtle.net/bob/hash/index.html, both
- on speed and bucket distribution. I haven't tried it against the
- function they just started using for Perl's hashes. */
-
-hashval_t
-htab_hash_string (p)
- const PTR p;
-{
- const unsigned char *str = (const unsigned char *) p;
- hashval_t r = 0;
- unsigned char c;
-
- while ((c = *str++) != 0)
- r = r * 67 + c - 113;
-
- return r;
-}
-
-/* DERIVED FROM:
---------------------------------------------------------------------
-lookup2.c, by Bob Jenkins, December 1996, Public Domain.
-hash(), hash2(), hash3, and mix() are externally useful functions.
-Routines to test the hash are included if SELF_TEST is defined.
-You can use this free for any purpose. It has no warranty.
---------------------------------------------------------------------
-*/
-
-/*
---------------------------------------------------------------------
-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.
---------------------------------------------------------------------
-*/
-/* same, but slower, works on systems that might have 8 byte hashval_t's */
-#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&0xffffffff)>>13); \
- a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
- b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
- c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
- a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
- b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
- c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
-}
-
-/*
---------------------------------------------------------------------
-hash() -- hash a variable-length key into a 32-bit value
- k : the key (the unaligned variable-length array of bytes)
- len : the length of the key, counting by bytes
- level : can be any 4-byte value
-Returns a 32-bit value. Every bit of the key affects every bit of
-the return value. Every 1-bit and 2-bit delta achieves avalanche.
-About 36+6len instructions.
-
-The best hash table sizes are powers of 2. There is no need to do
-mod a prime (mod is sooo slow!). If you need less than 32 bits,
-use a bitmask. For example, if you need only 10 bits, do
- h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-
-If you are hashing n strings (ub1 **)k, do it like this:
- for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
-
-By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
-code any way you wish, private, educational, or commercial. It's free.
-
-See http://burtleburtle.net/bob/hash/evahash.html
-Use for hash table lookup, or anything where one collision in 2^32 is
-acceptable. Do NOT use for cryptographic purposes.
---------------------------------------------------------------------
-*/
-
-hashval_t iterative_hash (k_in, length, initval)
- const PTR k_in; /* the key */
- register size_t length; /* the length of the key */
- register hashval_t initval; /* the previous hash, or an arbitrary value */
-{
- register const unsigned char *k = (const unsigned char *)k_in;
- register hashval_t a,b,c,len;
-
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = initval; /* the previous hash value */
-
- /*---------------------------------------- handle most of the key */
-#ifndef WORDS_BIGENDIAN
- /* On a little-endian machine, if the data is 4-byte aligned we can hash
- by word for better speed. This gives nondeterministic results on
- big-endian machines. */
- if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
- while (len >= 12) /* aligned */
- {
- a += *(hashval_t *)(k+0);
- b += *(hashval_t *)(k+4);
- c += *(hashval_t *)(k+8);
- mix(a,b,c);
- k += 12; len -= 12;
- }
- else /* unaligned */
-#endif
- while (len >= 12)
- {
- a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
- b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
- c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
- mix(a,b,c);
- k += 12; len -= 12;
- }
-
- /*------------------------------------- handle the last 11 bytes */
- c += length;
- switch(len) /* all the case statements fall through */
- {
- case 11: c+=((hashval_t)k[10]<<24);
- case 10: c+=((hashval_t)k[9]<<16);
- case 9 : c+=((hashval_t)k[8]<<8);
- /* the first byte of c is reserved for the length */
- case 8 : b+=((hashval_t)k[7]<<24);
- case 7 : b+=((hashval_t)k[6]<<16);
- case 6 : b+=((hashval_t)k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=((hashval_t)k[3]<<24);
- case 3 : a+=((hashval_t)k[2]<<16);
- case 2 : a+=((hashval_t)k[1]<<8);
- case 1 : a+=k[0];
- /* case 0: nothing left to add */
- }
- mix(a,b,c);
- /*-------------------------------------------- report the result */
- return c;
-}
OpenPOWER on IntegriCloud