Deleted append/2, now available from library lists
[chr.git] / chr_hashtable_store.pl
bloba16e8637d967e51e7e2fec4f2b9d2fa9d89253bb
1 /* $Id$
3 Part of CHR (Constraint Handling Rules)
5 Author: Tom Schrijvers
6 E-mail: Tom.Schrijvers@cs.kuleuven.be
7 WWW: http://www.swi-prolog.org
8 Copyright (C): 2003-2004, K.U. Leuven
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 As a special exception, if you link this library with other files,
25 compiled with a Free Software compiler, to produce an executable, this
26 library does not by itself cause the resulting executable to be covered
27 by the GNU General Public License. This exception does not however
28 invalidate any other reasons why the executable file might be covered by
29 the GNU General Public License.
31 % author: Tom Schrijvers
32 % email: Tom.Schrijvers@cs.kuleuven.be
33 % copyright: K.U.Leuven, 2004
35 :- module(chr_hashtable_store,
36 [ new_ht/1,
37 lookup_ht/3,
38 insert_ht/3,
39 insert_ht/4,
40 delete_ht/3,
41 delete_first_ht/3,
42 value_ht/2
43 ]).
45 :- use_module(pairlist).
46 :- use_module(hprolog).
47 :- use_module(library(lists)).
49 :- multifile user:goal_expansion/2.
50 :- dynamic user:goal_expansion/2.
52 user:goal_expansion(term_hash(Term,Hash),hash_term(Term,Hash)).
54 % term_hash(Term,Hash) :-
55 % hash_term(Term,Hash).
56 initial_capacity(1).
58 new_ht(HT) :-
59 initial_capacity(Capacity),
60 new_ht(Capacity,HT).
62 new_ht(Capacity,HT) :-
63 functor(T1,t,Capacity),
64 HT = ht(Capacity,0,Table),
65 Table = T1.
67 lookup_ht(HT,Key,Values) :-
68 term_hash(Key,Hash),
69 HT = ht(Capacity,_,Table),
70 Index is (Hash mod Capacity) + 1,
71 arg(Index,Table,Bucket),
72 nonvar(Bucket),
73 ( Bucket = K-Vs ->
74 K == Key,
75 Values = Vs
77 lookup(Bucket,Key,Values)
80 lookup_pair_eq([P | KVs],Key,Pair) :-
81 P = K-_,
82 ( K == Key ->
83 P = Pair
85 lookup_pair_eq(KVs,Key,Pair)
88 insert_ht(HT,Key,Value) :-
89 term_hash(Key,Hash),
90 HT = ht(Capacity0,Load,Table0),
91 LookupIndex is (Hash mod Capacity0) + 1,
92 arg(LookupIndex,Table0,LookupBucket),
93 ( var(LookupBucket) ->
94 LookupBucket = Key - [Value]
95 ; LookupBucket = K-Values ->
96 ( K == Key ->
97 setarg(2,LookupBucket,[Value|Values])
99 setarg(LookupIndex,Table0,[Key-[Value],LookupBucket])
102 ( lookup_pair_eq(LookupBucket,Key,Pair) ->
103 Pair = _-Values,
104 setarg(2,Pair,[Value|Values])
106 setarg(LookupIndex,Table0,[Key-[Value]|LookupBucket])
109 NLoad is Load + 1,
110 setarg(2,HT,NLoad),
111 ( Load == Capacity0 ->
112 expand_ht(HT,_Capacity)
114 true
117 % LDK: insert version with extra argument denoting result
119 insert_ht(HT,Key,Value,Result) :-
120 HT = ht(Capacity,Load,Table),
121 term_hash(Key,Hash),
122 LookupIndex is (Hash mod Capacity) + 1,
123 arg(LookupIndex,Table,LookupBucket),
124 ( var(LookupBucket)
125 -> Result = [Value],
126 LookupBucket = Key - Result,
127 NewLoad is Load + 1
128 ; LookupBucket = K - V
129 -> ( K = Key
130 -> Result = [Value|V],
131 setarg(2,LookupBucket,Result),
132 NewLoad = Load
133 ; Result = [Value],
134 setarg(LookupIndex,Table,[Key - Result,LookupBucket]),
135 NewLoad is Load + 1
137 ; ( lookup_pair_eq(LookupBucket,Key,Pair)
138 -> Pair = _-Values,
139 Result = [Value|Values],
140 setarg(2,Pair,Result),
141 NewLoad = Load
142 ; Result = [Value],
143 setarg(LookupIndex,Table,[Key - Result|LookupBucket]),
144 NewLoad is Load + 1
147 setarg(2,HT,NewLoad),
148 ( NewLoad > Capacity
149 -> expand_ht(HT,_)
150 ; true
153 % LDK: deletion of the first element of a bucket
154 delete_first_ht(HT,Key,Values) :-
155 HT = ht(Capacity,Load,Table),
156 term_hash(Key,Hash),
157 Index is (Hash mod Capacity) + 1,
158 arg(Index,Table,Bucket),
159 ( Bucket = _-[_|Values]
160 -> ( Values = []
161 -> setarg(Index,Table,_),
162 NewLoad is Load - 1
163 ; setarg(2,Bucket,Values),
164 NewLoad = Load
166 ; lookup_pair_eq(Bucket,Key,Pair)
167 -> Pair = _-[_|Values],
168 ( Values = []
169 -> pairlist_delete_eq(Bucket,Key,NewBucket),
170 ( NewBucket = []
171 -> setarg(Index,Table,_)
172 ; NewBucket = [OtherPair]
173 -> setarg(Index,Table,OtherPair)
174 ; setarg(Index,Table,NewBucket)
176 NewLoad is Load - 1
177 ; setarg(2,Pair,Values),
178 NewLoad = Load
182 delete_ht(HT,Key,Value) :-
183 HT = ht(Capacity,Load,Table),
184 NLoad is Load - 1,
185 term_hash(Key,Hash),
186 Index is (Hash mod Capacity) + 1,
187 arg(Index,Table,Bucket),
188 ( var(Bucket) ->
189 true
191 ( Bucket = K-Vs ->
192 ( K == Key,
193 delete_first_fail(Vs,Value,NVs) ->
194 setarg(2,HT,NLoad),
195 ( NVs == [] ->
196 setarg(Index,Table,_)
198 setarg(2,Bucket,NVs)
201 true
204 ( lookup_pair_eq(Bucket,Key,Pair),
205 Pair = _-Vs,
206 delete_first_fail(Vs,Value,NVs) ->
207 setarg(2,HT,NLoad),
208 ( NVs == [] ->
209 pairlist_delete_eq(Bucket,Key,NBucket),
210 ( NBucket = [Singleton] ->
211 setarg(Index,Table,Singleton)
213 setarg(Index,Table,NBucket)
216 setarg(2,Pair,NVs)
219 true
224 delete_first_fail([X | Xs], Y, Zs) :-
225 ( X == Y ->
226 Zs = Xs
228 Zs = [X | Zs1],
229 delete_first_fail(Xs, Y, Zs1)
231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 value_ht(HT,Value) :-
233 HT = ht(Capacity,_,Table),
234 value_ht(1,Capacity,Table,Value).
236 value_ht(I,N,Table,Value) :-
237 I =< N,
238 arg(I,Table,Bucket),
240 nonvar(Bucket),
241 ( Bucket = _-Vs ->
242 true
244 member(_-Vs,Bucket)
246 member(Value,Vs)
248 J is I + 1,
249 value_ht(J,N,Table,Value)
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 expand_ht(HT,NewCapacity) :-
255 HT = ht(Capacity,_,Table),
256 NewCapacity is Capacity * 2,
257 functor(NewTable,t,NewCapacity),
258 setarg(1,HT,NewCapacity),
259 setarg(3,HT,NewTable),
260 expand_copy(Table,1,Capacity,NewTable,NewCapacity).
262 expand_copy(Table,I,N,NewTable,NewCapacity) :-
263 ( I > N ->
264 true
266 arg(I,Table,Bucket),
267 ( var(Bucket) ->
268 true
269 ; Bucket = Key - Value ->
270 expand_insert(NewTable,NewCapacity,Key,Value)
272 expand_inserts(Bucket,NewTable,NewCapacity)
274 J is I + 1,
275 expand_copy(Table,J,N,NewTable,NewCapacity)
278 expand_inserts([],_,_).
279 expand_inserts([K-V|R],Table,Capacity) :-
280 expand_insert(Table,Capacity,K,V),
281 expand_inserts(R,Table,Capacity).
283 expand_insert(Table,Capacity,K,V) :-
284 term_hash(K,Hash),
285 Index is (Hash mod Capacity) + 1,
286 arg(Index,Table,Bucket),
287 ( var(Bucket) ->
288 Bucket = K - V
289 ; Bucket = _-_ ->
290 setarg(Index,Table,[K-V,Bucket])
292 setarg(Index,Table,[K-V|Bucket])
294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%