[m-dev.] For review: hash table implementation

Ralph Becket rbeck at microsoft.com
Mon Feb 5 22:02:55 AEDT 2001


>From Fergus Henderson on 03/02/2001 19:44:00
> 
> It would be nice to fix that XXX.
> I think something like the following
> 
>             else if N >= int__bits_per_int then
>              throw("hash_table__new_hash_table: N >= int__bits_per_int")
> 
> should do the trick.

Done.

> > int_hash_pred =
> >     ( pred(N::in, H1::out, H2::out) is det :-
> >         H1 = N * N,
> >         H2 = N `xor` (N + N)
> >     ).
> 
> Why not just `H1 = N'?

I perceived (through highly unscientific testing) that this gave a
better spread where N is small.  It's a weak justification, so I'll
change it back if it offends people :)

I've also renamed those preds to `{int,string,generic}_double_hash'
and introduced generic_double_hash/3 which goes like this:

%
----------------------------------------------------------------------------
%

    % This, again, is straight off the top of my head.
    %
generic_double_hash(T, Ha, Hb) :-
    (      if dynamic_cast(T, Int) then
        int_double_hash(Int, Ha, Hb)
      else if dynamic_cast(T, String) then
        string_double_hash(String, Ha, Hb)
      else if dynamic_cast(T, Univ) then
        generic_double_hash(univ_value(Univ), Ha, Hb)
      else if dynamic_cast(T, Array) then
        {Ha, Hb} =
            array__foldl(
                ( func(X, {HA0, HB0}) = {HA, HB} :-
                    generic_double_hash(X, HXA, HXB),
                    HA = munge(munge_factor_a, HA0, HXA),
                    HB = munge(munge_factor_b, HB0, HXB)
                ),
                Array,
                {0, 0}
            )
      else
        deconstruct(T, FunctorName, Arity, Args),
        string_double_hash(FunctorName, Ha0, Hb0),
        Ha1 = munge(munge_factor_a, Ha0, Arity),
        Hb1 = munge(munge_factor_b, Hb0, Arity),
        list__foldl2(
            ( pred(U::in, HA0::in, HA::out, HB0::in, HB::out) is det :-
                generic_double_hash(U, HUA, HUB),
                HA = munge(munge_factor_a, HA0, HUA),
                HB = munge(munge_factor_b, HB0, HUB)
            ), 
            Args,
            Ha1, Ha, 
            Hb1, Hb
        )
    ).

%
----------------------------------------------------------------------------
%

:- func munge_factor_a = int.           munge_factor_a = 5.
:- func munge_factor_b = int.           munge_factor_b = 3.
    
    

:- func munge(int, int, int) = int.

munge(N, X, Y) =
    (X `unchecked_left_shift` N) `xor`
    (X `unchecked_right_shift` (int__bits_per_int - N)) `xor`
    Y.

%
----------------------------------------------------------------------------
%

    % XXX To go into std_util.m
    %
:- pred dynamic_cast(T1, T2).
:- mode dynamic_cast(in, out) is semidet.

dynamic_cast(T1, T2) :-
    univ_to_type(univ(T1), T2).

%
----------------------------------------------------------------------------
%




--
Ralph Becket      |      MSR Cambridge      |      rbeck at microsoft.com 

--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list