On Sun, 21 Jan 2001, ts wrote:

> >>>>> "B" == Ben Tilly <ben_tilly / hotmail.com> writes:
> 
>  ruby version
> 
> B>   def hash (string)
> B>     hash_val = 0
> B>     for byte in string.each_byte do
> B>       hash_val = 33*hash_val + byte
>                     ^^
>                     997
> B>     end
> B>     hash_val += hash_val/32
> B>   end
> 
>  ruby can use the hash function given in the Dragon Book (compiled with
>  -DHASH_ELFHASH), perl hash function (compiled with -DHASH_PERL) or it's
>  own hash function.
> 
>  On /usr/share/dict/words the ruby hash function give less collisions
>  than the perl hash function. Compile ruby with -DHASH_LOG to know the
>  number of collisions.

Thanks Ben and Guy, for the extra information.

I thought it might be beneficial for someone to know the hash
functions for all classes (I could easily find), so here they are:

Array:
    h = RARRAY(ary)->len;
    for (i=0; i<RARRAY(ary)->len; i++) {
	h = (h<<1) | (h<0 ? 1 : 0);
	n = rb_hash(RARRAY(ary)->ptr[i]);
	h ^= NUM2LONG(n);
    }
    return INT2FIX(h);

Bignum:
    key = 0; digits = BDIGITS(x); len = RBIGNUM(x)->len;
    for (i=0; i<len; i++) {
	key ^= *digits++;
    }
    return INT2FIX(key);

Float:
    d = RFLOAT(num)->value;
    c = (char*)&d;
    for (hash=0, i=0; i<sizeof(double);i++) {
	hash += c[i] * 971;
    }
    if (hash < 0) hash = -hash;
    return INT2FIX(hash);

Time:
    GetTimeval(time, tobj);
    hash = tobj->tv.tv_sec ^ tobj->tv.tv_usec;
    return INT2FIX(hash);

String:
    register long len = RSTRING(str)->len;
    register char *p = RSTRING(str)->ptr;
    register int key = 0;

#ifdef HASH_ELFHASH
    register unsigned int g;

    while (len--) {
	key = (key << 4) + *p++;
	if (g = key & 0xF0000000)
	    key ^= g >> 24;
	key &= ~g;
    }
#elif HASH_PERL
    if (ruby_ignorecase) {
	while (len--) {
	    key = key*33 + toupper(*p);
	    p++;
	}
    }
    else {
	while (len--) {
	    key = key*33 + *p++;
	}
    }
    key = key + (key>>5);
#else
    if (ruby_ignorecase) {
	while (len--) {
	    key = key*65599 + toupper(*p);
	    p++;
	}
    }
    else {
	while (len--) {
	    key = key*65599 + *p;
	    p++;
	}
    }
    key = key + (key>>5);
#endif
    return key;




     - Aleksi