| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | %% -*- Prolog -*- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | /*  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This code implements hash-arrays. | 
					
						
							|  |  |  | It requires the hash key to be a ground term. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It relies on dynamic array code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | :- source. | 
					
						
							|  |  |  | :- yap_flag(unknown,error). | 
					
						
							|  |  |  | :- style_check(all). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | :- module(b_hash, [   b_hash_new/1, | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 		      b_hash_new/2, | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 		      b_hash_new/4, | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 		      b_hash_lookup/3, | 
					
						
							|  |  |  | 		      b_hash_update/3, | 
					
						
							|  |  |  | 		      b_hash_update/4, | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 		      b_hash_insert_new/4, | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | 		      b_hash_insert/4, | 
					
						
							|  |  |  | 		      b_hash_size/2, | 
					
						
							|  |  |  | 		      b_hash_code/2, | 
					
						
							|  |  |  | 		      is_b_hash/1, | 
					
						
							|  |  |  |         	      b_hash_to_list/2, | 
					
						
							|  |  |  | 		      b_hash_values_to_list/2, | 
					
						
							|  |  |  | 		      b_hash_keys_to_list/2 | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 		    ]). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :- use_module(library(terms), [ term_hash/4 ]). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | :- meta_predicate(b_hash_new(-,+,3,2)). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | array_default_size(2048). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | is_b_hash(V) :- var(V), !, fail. | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | is_b_hash(hash(_,_,_,_,_)). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | b_hash_new(hash(Keys, Vals, Size, N, _, _)) :- | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array_default_size(Size), | 
					
						
							|  |  |  | 	array(Keys, Size), | 
					
						
							|  |  |  | 	array(Vals, Size), | 
					
						
							|  |  |  | 	create_mutable(0, N). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | b_hash_new(hash(Keys, Vals, Size, N, _, _), Size) :- | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array(Keys, Size), | 
					
						
							|  |  |  | 	array(Vals, Size), | 
					
						
							|  |  |  | 	create_mutable(0, N). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | b_hash_new(hash(Keys,Vals, Size, N, HashF, CmpF), Size, HashF, CmpF) :- | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array(Keys, Size), | 
					
						
							|  |  |  | 	array(Vals, Size), | 
					
						
							|  |  |  | 	create_mutable(0, N). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | b_hash_size(hash(_, _, Size, _, _, _), Size). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | b_hash_lookup(Key, Val, hash(Keys, Vals, Size, _, F, CmpF)):- | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	hash_f(Key, Size, Index, F), | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	fetch_key(Keys, Index, Size, Key, CmpF, ActualIndex), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array_element(Vals, ActualIndex, Mutable), | 
					
						
							|  |  |  | 	get_mutable(Val, Mutable). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | fetch_key(Keys, Index, Size, Key, CmpF, ActualIndex) :- | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array_element(Keys, Index, El), | 
					
						
							|  |  |  | 	nonvar(El), | 
					
						
							|  |  |  | 	( | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	    cmp_f(CmpF, El, Key) | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	-> | 
					
						
							|  |  |  | 	    Index = ActualIndex | 
					
						
							|  |  |  | 	; | 
					
						
							|  |  |  | 	    I1 is (Index+1) mod Size, | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	    fetch_key(Keys, I1, Size, Key, CmpF, ActualIndex) | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | b_hash_update(Hash, Key, NewVal):- | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	Hash = hash(Keys, Vals, Size, _, F, CmpF), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	hash_f(Key,Size,Index,F), | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	fetch_key(Keys, Index, Size, Key, CmpF, ActualIndex), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array_element(Vals, ActualIndex, Mutable), | 
					
						
							|  |  |  | 	update_mutable(NewVal, Mutable). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | b_hash_update(Hash, Key, OldVal, NewVal):- | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	Hash = hash(Keys, Vals, Size, _, F, CmpF), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	hash_f(Key,Size,Index,F), | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	fetch_key(Keys, Index, Size, Key, CmpF, ActualIndex), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array_element(Vals, ActualIndex, Mutable), | 
					
						
							|  |  |  | 	get_mutable(OldVal, Mutable), | 
					
						
							|  |  |  | 	update_mutable(NewVal, Mutable). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | b_hash_insert(Hash, Key, NewVal, NewHash):- | 
					
						
							|  |  |  | 	Hash = hash(Keys, Vals, Size, N, F, CmpF), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	hash_f(Key,Size,Index,F), | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	find_or_insert(Keys, Index, Size, N, CmpF, Vals, Key, NewVal, Hash, NewHash). | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | find_or_insert(Keys, Index, Size, N, CmpF, Vals, Key, NewVal, Hash, NewHash) :- | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	array_element(Keys, Index, El), | 
					
						
							|  |  |  | 	( | 
					
						
							|  |  |  | 	    var(El) | 
					
						
							|  |  |  | 	-> | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	    add_element(Keys, Index, Size, N, Vals, Key, NewVal, Hash, NewHash) | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	; | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	    cmp_f(CmpF, El, Key) | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	-> | 
					
						
							|  |  |  | 	     % do rb_update | 
					
						
							|  |  |  | 	    array_element(Vals, Index, Mutable), | 
					
						
							| 
									
										
										
										
											2012-03-22 12:07:38 +00:00
										 |  |  | 	    update_mutable(NewVal, Mutable), | 
					
						
							|  |  |  | 	    Hash = NewHash | 
					
						
							| 
									
										
										
										
											2008-11-18 11:29:08 +00:00
										 |  |  |         ; | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	    I1 is (Index+1) mod Size, | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	    find_or_insert(Keys, I1, Size, N, CmpF, Vals, Key, NewVal, Hash, NewHash) | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | b_hash_insert_new(Hash, Key, NewVal, NewHash):- | 
					
						
							|  |  |  | 	Hash = hash(Keys, Vals, Size, N, F, CmpF), | 
					
						
							|  |  |  | 	hash_f(Key,Size,Index,F), | 
					
						
							|  |  |  | 	find_or_insert_new(Keys, Index, Size, N, CmpF, Vals, Key, NewVal, Hash, NewHash). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | find_or_insert_new(Keys, Index, Size, N, CmpF, Vals, Key, NewVal, Hash, NewHash) :- | 
					
						
							|  |  |  | 	array_element(Keys, Index, El), | 
					
						
							|  |  |  | 	( | 
					
						
							|  |  |  | 	    var(El) | 
					
						
							|  |  |  | 	-> | 
					
						
							|  |  |  | 	    add_element(Keys, Index, Size, N, Vals, Key, NewVal, Hash, NewHash) | 
					
						
							|  |  |  | 	; | 
					
						
							|  |  |  | 	    cmp_f(CmpF, El, Key) | 
					
						
							|  |  |  | 	-> | 
					
						
							|  |  |  | 	    fail | 
					
						
							|  |  |  |         ; | 
					
						
							|  |  |  | 	    I1 is (Index+1) mod Size, | 
					
						
							|  |  |  | 	    find_or_insert_new(Keys, I1, Size, N, CmpF, Vals, Key, NewVal, Hash, NewHash) | 
					
						
							|  |  |  | 	). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | add_element(Keys, Index, Size, N, Vals, Key, NewVal, Hash, NewHash) :- | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	get_mutable(NEls, N), | 
					
						
							|  |  |  | 	NN is NEls+1, | 
					
						
							|  |  |  | 	update_mutable(NN, N), | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | 	array_element(Keys, Index, Key), | 
					
						
							|  |  |  | 	update_mutable(NN, N), | 
					
						
							|  |  |  | 	array_element(Vals, Index, Mutable), | 
					
						
							|  |  |  | 	create_mutable(NewVal, Mutable), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	( | 
					
						
							| 
									
										
										
										
											2008-11-18 11:29:08 +00:00
										 |  |  | 	    NN > Size/3 | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	-> | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	    expand_array(Hash, NewHash) | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	; | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	    Hash = NewHash | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | 	). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | expand_array(Hash, NewHash) :- | 
					
						
							|  |  |  | 	Hash == NewHash, !, | 
					
						
							|  |  |  | 	Hash = hash(Keys, Vals, Size, _X, F, _CmpF), | 
					
						
							|  |  |  | 	new_size(Size, NewSize), | 
					
						
							|  |  |  | 	array(NewKeys, NewSize), | 
					
						
							|  |  |  | 	array(NewVals, NewSize), | 
					
						
							|  |  |  | 	copy_hash_table(Size, Keys, Vals, F, NewSize, NewKeys, NewVals), | 
					
						
							|  |  |  | 	/* overwrite in place */ | 
					
						
							|  |  |  | 	setarg(1, Hash, NewKeys), | 
					
						
							|  |  |  | 	setarg(2, Hash, NewVals), | 
					
						
							|  |  |  | 	setarg(3, Hash, NewSize). | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | expand_array(Hash, hash(NewKeys, NewVals, NewSize, X, F, CmpF)) :- | 
					
						
							|  |  |  | 	Hash = hash(Keys, Vals, Size, X, F, CmpF), | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	new_size(Size, NewSize), | 
					
						
							|  |  |  | 	array(NewKeys, NewSize), | 
					
						
							|  |  |  | 	array(NewVals, NewSize), | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | 	copy_hash_table(Size, Keys, Vals, F, NewSize, NewKeys, NewVals). | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | new_size(Size, NewSize) :- | 
					
						
							|  |  |  | 	Size > 1048576, !, | 
					
						
							|  |  |  | 	NewSize is Size+1048576. | 
					
						
							|  |  |  | new_size(Size, NewSize) :- | 
					
						
							|  |  |  | 	NewSize is Size*2. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | copy_hash_table(0, _, _, _, _, _, _) :- !. | 
					
						
							|  |  |  | copy_hash_table(I1, Keys, Vals, F, Size, NewKeys, NewVals) :- | 
					
						
							|  |  |  | 	I is I1-1, | 
					
						
							|  |  |  | 	array_element(Keys, I, Key), | 
					
						
							|  |  |  | 	nonvar(Key), !, | 
					
						
							|  |  |  | 	array_element(Vals, I, Val), | 
					
						
							|  |  |  | 	insert_el(Key, Val, Size, F, NewKeys, NewVals), | 
					
						
							|  |  |  | 	copy_hash_table(I, Keys, Vals, F, Size, NewKeys, NewVals). | 
					
						
							|  |  |  | copy_hash_table(I1, Keys, Vals, F, Size, NewKeys, NewVals) :- | 
					
						
							|  |  |  | 	I is I1-1, | 
					
						
							|  |  |  | 	copy_hash_table(I, Keys, Vals, F, Size, NewKeys, NewVals). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | insert_el(Key, Val, Size, F, NewKeys, NewVals) :- | 
					
						
							|  |  |  | 	hash_f(Key,Size,Index, F), | 
					
						
							|  |  |  | 	find_free(Index, Size, NewKeys, TrueIndex), | 
					
						
							|  |  |  | 	array_element(NewKeys, TrueIndex, Key), | 
					
						
							|  |  |  | 	array_element(NewVals, TrueIndex, Val). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | find_free(Index, Size, Keys, NewIndex) :- | 
					
						
							|  |  |  | 	array_element(Keys, Index, El), | 
					
						
							|  |  |  | 	( | 
					
						
							|  |  |  | 	    var(El) | 
					
						
							|  |  |  | 	-> | 
					
						
							|  |  |  | 	    NewIndex = Index | 
					
						
							|  |  |  | 	; | 
					
						
							|  |  |  | 	    I1 is (Index+1) mod Size, | 
					
						
							| 
									
										
										
										
											2008-11-18 11:29:08 +00:00
										 |  |  | 	    find_free(I1, Size, Keys, NewIndex) | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | 	). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hash_f(Key, Size, Index, F) :- | 
					
						
							|  |  |  | 	var(F), !, | 
					
						
							| 
									
										
										
										
											2009-11-23 23:43:12 +00:00
										 |  |  | 	term_hash(Key,-1,Size,Index). | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:04 +00:00
										 |  |  | hash_f(Key, Size, Index, F) :- | 
					
						
							|  |  |  | 	call(F, Key, Size, Index). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-04 23:57:46 +01:00
										 |  |  | cmp_f(F, A, B) :- | 
					
						
							|  |  |  | 	var(F), !, | 
					
						
							|  |  |  | 	A == B. | 
					
						
							|  |  |  | cmp_f(F, A, B) :- | 
					
						
							|  |  |  | 	call(F, A, B). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | b_hash_to_list(hash(Keys, Vals, _, _, _, _), LKeyVals) :- | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | 	Keys =.. (_.LKs), | 
					
						
							|  |  |  | 	Vals =.. (_.LVs), | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | 	mklistpairs(LKs, LVs, LKeyVals). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | b_hash_keys_to_list(hash(Keys, _, _, _, _, _), LKeys) :- | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | 	Keys =.. (_.LKs), | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | 	mklistels(LKs, LKeys). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | b_hash_values_to_list(hash(_, Vals, _, _, _, _), LVals) :- | 
					
						
							|  |  |  | 	Vals =.. (_.LVs), | 
					
						
							|  |  |  | 	mklistvals(LVs, LVals). | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | mklistpairs([], [], []). | 
					
						
							|  |  |  | mklistpairs(V.LKs, _.LVs, KeyVals) :- var(V), !, | 
					
						
							|  |  |  | 	mklistpairs(LKs, LVs, KeyVals). | 
					
						
							|  |  |  | mklistpairs(K.LKs, V.LVs, (K-VV).KeyVals) :-  | 
					
						
							|  |  |  |         get_mutable(VV, V), | 
					
						
							|  |  |  | 	mklistpairs(LKs, LVs, KeyVals). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | mklistels([],  []). | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | mklistels(V.Els, NEls) :- var(V), !, | 
					
						
							|  |  |  | 	mklistels(Els, NEls). | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | mklistels(K.Els, K.NEls) :-  | 
					
						
							|  |  |  | 	mklistels(Els, NEls). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | mklistvals([],  []). | 
					
						
							| 
									
										
										
										
											2011-11-03 07:44:38 +09:00
										 |  |  | mklistvals(V.Vals, NVals) :- var(V), !, | 
					
						
							|  |  |  | 	mklistvals(Vals, NVals). | 
					
						
							| 
									
										
										
										
											2011-10-24 22:49:42 +01:00
										 |  |  | mklistvals(K.Vals, KK.NVals) :-  | 
					
						
							|  |  |  | 	get_mutable(KK, K), | 
					
						
							|  |  |  | 	mklistvals(Vals, NVals). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |