| 
									
										
										
										
											2008-06-09 06:22:21 -04:00
										 |  |  | ! Copyright (C) 2005, 2008 Slava Pestov. | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  | USING: accessors arrays kernel kernel.private slots.private math | 
					
						
							| 
									
										
										
										
											2008-11-12 00:03:50 -05:00
										 |  |  | assocs math.private sequences sequences.private vectors ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | IN: hashtables | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  | TUPLE: hashtable | 
					
						
							| 
									
										
										
										
											2008-06-29 22:37:57 -04:00
										 |  |  | { count array-capacity } | 
					
						
							|  |  |  | { deleted array-capacity } | 
					
						
							|  |  |  | { array array } ;
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : wrap ( i array -- n )
 | 
					
						
							| 
									
										
										
										
											2008-07-16 17:48:09 -04:00
										 |  |  |     length>> 1 fixnum-fast fixnum-bitand ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : hash@ ( key array -- i )
 | 
					
						
							|  |  |  |     >r hashcode >fixnum dup fixnum+fast r> wrap ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : probe ( array i -- array i )
 | 
					
						
							|  |  |  |     2 fixnum+fast over wrap ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  | : no-key ( key array -- array n ? ) nip f f ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (key@) ( key array i -- array n ? )
 | 
					
						
							| 
									
										
										
										
											2008-03-06 12:28:49 -05:00
										 |  |  |     3dup swap array-nth | 
					
						
							|  |  |  |     dup ((empty)) eq?
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  |     [ 3drop no-key ] [ | 
					
						
							| 
									
										
										
										
											2008-03-29 21:28:07 -04:00
										 |  |  |         = [ rot drop t ] [ probe (key@) ] if
 | 
					
						
							| 
									
										
										
										
											2008-07-18 20:22:59 -04:00
										 |  |  |     ] if ; inline recursive
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : key@ ( key hash -- array n ? )
 | 
					
						
							| 
									
										
										
										
											2008-07-16 17:48:09 -04:00
										 |  |  |     array>> dup length>> 0 eq?
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  |     [ no-key ] [ 2dup hash@ (key@) ] if ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : <hash-array> ( n -- array )
 | 
					
						
							|  |  |  |     1+ next-power-of-2 4 * ((empty)) <array> ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : init-hash ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     0 >>count 0 >>deleted drop ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : reset-hash ( n hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     swap <hash-array> >>array init-hash ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (new-key@) ( key keys i -- keys n empty? )
 | 
					
						
							|  |  |  |     3dup swap array-nth dup ((empty)) eq? [ | 
					
						
							|  |  |  |         2drop rot drop t
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         = [ | 
					
						
							|  |  |  |             rot drop f
 | 
					
						
							|  |  |  |         ] [ | 
					
						
							|  |  |  |             probe (new-key@) | 
					
						
							|  |  |  |         ] if
 | 
					
						
							| 
									
										
										
										
											2008-07-18 20:22:59 -04:00
										 |  |  |     ] if ; inline recursive
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : new-key@ ( key hash -- array n empty? )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     array>> 2dup hash@ (new-key@) ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-04 18:45:06 -04:00
										 |  |  | : set-nth-pair ( value key seq n -- )
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     2 fixnum+fast [ set-slot ] 2keep
 | 
					
						
							|  |  |  |     1 fixnum+fast set-slot ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : hash-count+ ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     [ 1+ ] change-count drop ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : hash-deleted+ ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     [ 1+ ] change-deleted drop ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-09 06:22:21 -04:00
										 |  |  | : (rehash) ( hash alist -- )
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  |     swap [ swapd set-at ] curry assoc-each ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : hash-large? ( hash -- ? )
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  |     [ count>> 3 fixnum*fast 1 fixnum+fast ] | 
					
						
							| 
									
										
										
										
											2008-07-16 17:48:09 -04:00
										 |  |  |     [ array>> length>> ] bi fixnum> ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : hash-stale? ( hash -- ? )
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  |     [ deleted>> 10 fixnum*fast ] [ count>> ] bi fixnum> ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : grow-hash ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-06-09 06:22:21 -04:00
										 |  |  |     [ dup >alist swap assoc-size 1+ ] keep
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     [ reset-hash ] keep
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  |     swap (rehash) ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : ?grow-hash ( hash -- )
 | 
					
						
							|  |  |  |     dup hash-large? [ | 
					
						
							|  |  |  |         grow-hash | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         dup hash-stale? [ | 
					
						
							|  |  |  |             grow-hash | 
					
						
							|  |  |  |         ] [ | 
					
						
							|  |  |  |             drop
 | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] if ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <hashtable> ( n -- hash )
 | 
					
						
							| 
									
										
										
										
											2008-04-13 16:06:09 -04:00
										 |  |  |     hashtable new [ reset-hash ] keep ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable at* ( key hash -- value ? )
 | 
					
						
							|  |  |  |     key@ [ 3 fixnum+fast slot t ] [ 2drop f f ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: hashtable clear-assoc ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     [ init-hash ] [ array>> [ drop ((empty)) ] change-each ] bi ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable delete-at ( key hash -- )
 | 
					
						
							|  |  |  |     tuck key@ [ | 
					
						
							| 
									
										
										
										
											2007-10-04 18:45:06 -04:00
										 |  |  |         >r >r ((tombstone)) dup r> r> set-nth-pair | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         hash-deleted+ | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         3drop
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: hashtable assoc-size ( hash -- n )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     [ count>> ] [ deleted>> ] bi - ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : rehash ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     dup >alist >r | 
					
						
							|  |  |  |     dup clear-assoc
 | 
					
						
							|  |  |  |     r> (rehash) ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable set-at ( value key hash -- )
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  |     dup ?grow-hash | 
					
						
							|  |  |  |     2dup new-key@ | 
					
						
							|  |  |  |     [ rot hash-count+ set-nth-pair ] | 
					
						
							|  |  |  |     [ rot drop set-nth-pair ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : associate ( value key -- hash )
 | 
					
						
							|  |  |  |     2 <hashtable> [ set-at ] keep ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 01:10:50 -05:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : push-unsafe ( elt seq -- )
 | 
					
						
							|  |  |  |     [ length ] keep
 | 
					
						
							|  |  |  |     [ underlying>> set-array-nth ] | 
					
						
							|  |  |  |     [ >r 1+ r> (>>length) ] | 
					
						
							|  |  |  |     2bi ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-09 06:22:21 -04:00
										 |  |  | M: hashtable >alist | 
					
						
							| 
									
										
										
										
											2008-11-12 01:10:50 -05:00
										 |  |  |     [ array>> [ length 2/ ] keep ] [ assoc-size <vector> ] bi [ | 
					
						
							| 
									
										
										
										
											2008-11-12 00:03:50 -05:00
										 |  |  |         [ | 
					
						
							|  |  |  |             >r | 
					
						
							|  |  |  |             >r 1 fixnum-shift-fast r> | 
					
						
							|  |  |  |             [ array-nth ] [ >r 1 fixnum+fast r> array-nth ] 2bi r> | 
					
						
							| 
									
										
										
										
											2008-11-12 01:10:50 -05:00
										 |  |  |             pick tombstone? [ 3drop ] [ [ 2array ] dip push-unsafe ] if
 | 
					
						
							| 
									
										
										
										
											2008-11-12 00:03:50 -05:00
										 |  |  |         ] 2curry each
 | 
					
						
							| 
									
										
										
										
											2008-11-12 01:10:50 -05:00
										 |  |  |     ] keep { } like ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable clone | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  |     (clone) [ clone ] change-array ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable equal? | 
					
						
							| 
									
										
										
										
											2008-02-14 02:03:57 -05:00
										 |  |  |     over hashtable? [ | 
					
						
							| 
									
										
										
										
											2008-11-12 00:03:50 -05:00
										 |  |  |         2dup [ assoc-size ] bi@ eq?
 | 
					
						
							| 
									
										
										
										
											2008-02-14 02:03:57 -05:00
										 |  |  |         [ assoc= ] [ 2drop f ] if
 | 
					
						
							|  |  |  |     ] [ 2drop f ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Default method | 
					
						
							|  |  |  | M: assoc new-assoc drop <hashtable> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: f new-assoc drop <hashtable> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : >hashtable ( assoc -- hashtable )
 | 
					
						
							|  |  |  |     H{ } assoc-clone-like ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: hashtable assoc-like | 
					
						
							|  |  |  |     drop dup hashtable? [ >hashtable ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ?set-at ( value key assoc/f -- assoc )
 | 
					
						
							|  |  |  |     [ [ set-at ] keep ] [ associate ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | INSTANCE: hashtable assoc |