/*
 * hashfn.c
 *
 * Identification:
 *	$Header: RCS/hashfn.c,v 1.3 91/07/25 15:13:05 mer Exp $
 *
 */
#include "utils/hsearch.h"

/*
	Assume that we've already split the bucket to which this
	key hashes, calculate that bucket, and check that in fact
	we did already split it.
*/
int
string_hash(key,keysize)
char *	key;
int	keysize;
{
	int h;
	register unsigned char *k = (unsigned char *) key;

	h = 0;
	/*
	 * Convert string to integer
	 */
	while (*k)
		h = h * PRIME1 ^ (*k++ - ' ');
	h %= PRIME2;

	return (h);
}


tag_hash(key,keysize)
int *	key;
int	keysize;
{
	int h;

	/*
	 * Convert tag to integer;  Use four byte chunks so we can
	 * go a little faster.
	 */
	for(h = 0;keysize > (sizeof(int)-1);keysize -= sizeof(int),key++) {
	  h = h * PRIME1 ^ (*key);
	}
        /*
         * now let's grab the last few bytes of the tag if the tag
         * has (size % 4) != 0 (which it sometimes will on a sun3).
         */
        if (keysize) {
          char *keytmp = (char *)key;

          switch (keysize) {
          case 3:
            h = h * PRIME1 ^ (*keytmp);
            keytmp++;
            /* fall through */
          case 2:
            h = h * PRIME1 ^ (*keytmp);
            keytmp++;
            /* fall through */
          case 1:
            h = h * PRIME1 ^ (*keytmp);
            break;
          }
        }
	h %= PRIME2;
	return (h);
}

/*
 * This is INCREDIBLY ugly, but fast.
 * We break the string up into 8 byte units.  On the first time
 * through the loop we get the "leftover bytes" (strlen % 8).
 * On every other iteration, we perform 8 HASHC's so we handle
 * all 8 bytes.  Essentially, this saves us 7 cmp & branch
 * instructions.  If this routine is heavily used enough, it's
 * worth the ugly coding
 */
int
disk_hash(key)
char *key;
{
        register int n = 0;
	register char *str = key;
	register int len = strlen(key);
	register int loop;

#define HASHC   n = *str++ + 65599 * n

        if (len > 0) {
                loop = (len + 8 - 1) >> 3;

                switch(len & (8 - 1)) {
			case 0: do {		/* All fall throughs */
					HASHC;  
				case 7: HASHC;
				case 6: HASHC;  
				case 5: HASHC;
				case 4: HASHC;  
				case 3: HASHC;
				case 2: HASHC;  
				case 1: HASHC;
                        } while (--loop);
                }

        }
	return(n);
}


