232 lines
4.4 KiB
Perl
232 lines
4.4 KiB
Perl
|
% author: Tom Schrijvers
|
||
|
% email: Tom.Schrijvers@cs.kuleuven.ac.be
|
||
|
% copyright: K.U.Leuven, 2004
|
||
|
|
||
|
:- module(chr_hashtable_store,
|
||
|
[ new_ht/1,
|
||
|
lookup_ht/3,
|
||
|
insert_ht/3,
|
||
|
delete_ht/3,
|
||
|
value_ht/2
|
||
|
]).
|
||
|
|
||
|
:- use_module(pairlist).
|
||
|
:- use_module(hprolog).
|
||
|
%:- use_module(library(lists)).
|
||
|
|
||
|
initial_capacity(1).
|
||
|
|
||
|
new_ht(HT) :-
|
||
|
initial_capacity(Capacity),
|
||
|
new_ht(Capacity,HT).
|
||
|
|
||
|
new_ht(Capacity,HT) :-
|
||
|
functor(T1,t,Capacity),
|
||
|
HT = ht(Capacity,0,Table),
|
||
|
Table = T1.
|
||
|
|
||
|
lookup_ht(HT,Key,Values) :-
|
||
|
term_hash(Key,Hash),
|
||
|
HT = ht(Capacity,_,Table),
|
||
|
Index is (Hash mod Capacity) + 1,
|
||
|
arg(Index,Table,Bucket),
|
||
|
nonvar(Bucket),
|
||
|
( Bucket = K-Vs ->
|
||
|
K == Key,
|
||
|
Values = Vs
|
||
|
;
|
||
|
lookup_eq(Bucket,Key,Values)
|
||
|
).
|
||
|
|
||
|
lookup_pair_eq([P | KVs],Key,Pair) :-
|
||
|
P = K-_,
|
||
|
( K == Key ->
|
||
|
P = Pair
|
||
|
;
|
||
|
lookup_pair_eq(KVs,Key,Pair)
|
||
|
).
|
||
|
|
||
|
insert_ht(HT,Key,Value) :-
|
||
|
term_hash(Key,Hash),
|
||
|
HT = ht(Capacity0,Load,Table0),
|
||
|
LookupIndex is (Hash mod Capacity0) + 1,
|
||
|
arg(LookupIndex,Table0,LookupBucket),
|
||
|
( var(LookupBucket) ->
|
||
|
Inc = yes,
|
||
|
LookupBucket = Key - [Value]
|
||
|
; LookupBucket = K-Values ->
|
||
|
( K == Key ->
|
||
|
( hprolog:memberchk_eq(Value,Values) ->
|
||
|
true
|
||
|
;
|
||
|
Inc = yes,
|
||
|
setarg(2,LookupBucket,[Value|Values])
|
||
|
)
|
||
|
;
|
||
|
Inc = yes,
|
||
|
setarg(LookupIndex,Table0,[Key-[Value],LookupBucket])
|
||
|
)
|
||
|
;
|
||
|
( lookup_pair_eq(LookupBucket,Key,Pair) ->
|
||
|
Pair = _-Values,
|
||
|
( hprolog:memberchk_eq(Value,Values) ->
|
||
|
true
|
||
|
;
|
||
|
Inc = yes,
|
||
|
setarg(2,Pair,[Value|Values])
|
||
|
)
|
||
|
;
|
||
|
Inc = yes,
|
||
|
setarg(LookupIndex,Table0,[Key-[Value]|LookupBucket])
|
||
|
)
|
||
|
),
|
||
|
( Inc == yes ->
|
||
|
NLoad is Load + 1,
|
||
|
setarg(2,HT,NLoad),
|
||
|
( Load == Capacity0 ->
|
||
|
expand_ht(HT,_Capacity)
|
||
|
;
|
||
|
true
|
||
|
)
|
||
|
;
|
||
|
true
|
||
|
).
|
||
|
|
||
|
delete_ht(HT,Key,Value) :-
|
||
|
HT = ht(Capacity,Load,Table),
|
||
|
NLoad is Load - 1,
|
||
|
term_hash(Key,Hash),
|
||
|
Index is (Hash mod Capacity) + 1,
|
||
|
arg(Index,Table,Bucket),
|
||
|
( var(Bucket) ->
|
||
|
true
|
||
|
;
|
||
|
( Bucket = K-Vs ->
|
||
|
( K == Key,
|
||
|
delete_first_fail(Vs,Value,NVs) ->
|
||
|
setarg(2,HT,NLoad),
|
||
|
( NVs == [] ->
|
||
|
setarg(Index,Table,_)
|
||
|
;
|
||
|
setarg(2,Bucket,NVs)
|
||
|
)
|
||
|
;
|
||
|
true
|
||
|
)
|
||
|
;
|
||
|
( lookup_pair_eq(Bucket,Key,Pair),
|
||
|
Pair = _-Vs,
|
||
|
delete_first_fail(Vs,Value,NVs) ->
|
||
|
setarg(2,HT,NLoad),
|
||
|
( NVs == [] ->
|
||
|
pairlist_delete_eq(Bucket,Key,NBucket),
|
||
|
setarg(Index,Table,NBucket)
|
||
|
;
|
||
|
setarg(2,Pair,NVs)
|
||
|
)
|
||
|
;
|
||
|
true
|
||
|
)
|
||
|
)
|
||
|
).
|
||
|
|
||
|
delete_first_fail([X | Xs], Y, Zs) :-
|
||
|
( X == Y ->
|
||
|
Zs = Xs
|
||
|
;
|
||
|
Zs = [X | Zs1],
|
||
|
delete_first_fail(Xs, Y, Zs1)
|
||
|
).
|
||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
|
value_ht(HT,Value) :-
|
||
|
HT = ht(Capacity,_,Table),
|
||
|
value_ht(1,Capacity,Table,Value).
|
||
|
|
||
|
value_ht(I,N,Table,Value) :-
|
||
|
I =< N,
|
||
|
arg(I,Table,Bucket),
|
||
|
(
|
||
|
nonvar(Bucket),
|
||
|
( Bucket = _-Vs ->
|
||
|
true
|
||
|
;
|
||
|
member(_-Vs,Bucket)
|
||
|
),
|
||
|
member(Value,Vs)
|
||
|
;
|
||
|
J is I + 1,
|
||
|
value_ht(J,N,Table,Value)
|
||
|
).
|
||
|
|
||
|
values_ht(HT,Values) :-
|
||
|
HT = ht(Capacity,_,Table),
|
||
|
values_ht(1,Capacity,Table,Values).
|
||
|
values_ht(I,N,Table,Values) :-
|
||
|
( I =< N ->
|
||
|
arg(I,Table,Bucket),
|
||
|
( nonvar(Bucket) ->
|
||
|
( Bucket = _-Vs ->
|
||
|
append(Vs,Tail,Values)
|
||
|
;
|
||
|
append_snd(Bucket,Tail,Values)
|
||
|
)
|
||
|
;
|
||
|
Values = Tail
|
||
|
),
|
||
|
J is I + 1,
|
||
|
values_ht(J,N,Table,Tail)
|
||
|
;
|
||
|
Values = []
|
||
|
).
|
||
|
|
||
|
append_snd([],L,L).
|
||
|
append_snd([_-H|Ps],L,NL) :-
|
||
|
append(H,T,NL),
|
||
|
append_snd(Ps,L,T).
|
||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
|
|
||
|
expand_ht(HT,NewCapacity) :-
|
||
|
HT = ht(Capacity,_,Table),
|
||
|
NewCapacity is Capacity * 2,
|
||
|
functor(NewTable,t,NewCapacity),
|
||
|
setarg(1,HT,NewCapacity),
|
||
|
setarg(3,HT,NewTable),
|
||
|
expand_copy(Table,1,Capacity,NewTable,NewCapacity).
|
||
|
|
||
|
expand_copy(Table,I,N,NewTable,NewCapacity) :-
|
||
|
( I > N ->
|
||
|
true
|
||
|
;
|
||
|
arg(I,Table,Bucket),
|
||
|
( var(Bucket) ->
|
||
|
true
|
||
|
; Bucket = Key - Value ->
|
||
|
expand_insert(NewTable,NewCapacity,Key,Value)
|
||
|
;
|
||
|
expand_inserts(Bucket,NewTable,NewCapacity)
|
||
|
),
|
||
|
J is I + 1,
|
||
|
expand_copy(Table,J,N,NewTable,NewCapacity)
|
||
|
).
|
||
|
|
||
|
expand_inserts([],_,_).
|
||
|
expand_inserts([K-V|R],Table,Capacity) :-
|
||
|
expand_insert(Table,Capacity,K,V),
|
||
|
expand_inserts(R,Table,Capacity).
|
||
|
|
||
|
expand_insert(Table,Capacity,K,V) :-
|
||
|
term_hash(K,Hash),
|
||
|
Index is (Hash mod Capacity) + 1,
|
||
|
arg(Index,Table,Bucket),
|
||
|
( var(Bucket) ->
|
||
|
Bucket = K - V
|
||
|
; Bucket = _-_ ->
|
||
|
setarg(Index,Table,[K-V,Bucket])
|
||
|
;
|
||
|
setarg(Index,Table,[K-V|Bucket])
|
||
|
).
|
||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
|
term_hash(Term,Hash) :-
|
||
|
hash_term(Term,Hash).
|
||
|
|