| 
									
										
										
										
											2011-11-12 18:35:19 -05:00
										 |  |  | ! Copyright (C) 2005, 2011 John Benediktsson, Slava Pestov. | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2013-03-05 13:34:47 -05:00
										 |  |  | USING: accessors arrays assocs kernel kernel.private math | 
					
						
							|  |  |  | math.private sequences sequences.private slots.private vectors ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | IN: hashtables | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 03:36:20 -04:00
										 |  |  | TUPLE: hashtable | 
					
						
							| 
									
										
										
										
											2016-05-30 12:40:09 -04:00
										 |  |  |     { count array-capacity } | 
					
						
							|  |  |  |     { deleted array-capacity } | 
					
						
							| 
									
										
										
										
											2016-10-06 14:18:41 -04:00
										 |  |  |     { 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 )
 | 
					
						
							| 
									
										
										
										
											2008-11-23 03:44:56 -05:00
										 |  |  |     [ hashcode >fixnum dup fixnum+fast ] dip wrap ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-02 20:49:11 -04:00
										 |  |  | : probe ( array i probe# -- array i probe# )
 | 
					
						
							| 
									
										
										
										
											2011-10-02 16:47:51 -04:00
										 |  |  |     2 fixnum+fast [ fixnum+fast over wrap ] keep ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 00:26:20 -04:00
										 |  |  | : no-key ( key array -- array n ? ) nip f f ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-02 16:47:51 -04:00
										 |  |  | : (key@) ( key array i probe# -- array n ? )
 | 
					
						
							| 
									
										
										
										
											2016-03-25 04:52:07 -04:00
										 |  |  |     [ 3dup swap array-nth ] dip over +empty+ eq?
 | 
					
						
							| 
									
										
										
										
											2012-10-23 15:26:14 -04:00
										 |  |  |     [ 4drop no-key ] [ | 
					
						
							| 
									
										
										
										
											2011-10-02 16:47:51 -04:00
										 |  |  |         [ = ] dip swap
 | 
					
						
							|  |  |  |         [ drop 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 ? )
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:18:35 -04:00
										 |  |  |     array>> dup length>> 0 eq?
 | 
					
						
							|  |  |  |     [ no-key ] [ 2dup hash@ 0 (key@) ] if ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : <hash-array> ( n -- array )
 | 
					
						
							| 
									
										
										
										
											2016-03-25 04:52:07 -04:00
										 |  |  |     3 * 1 + 2/ next-power-of-2 2 * +empty+ <array> ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : 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-12-06 16:31:35 -05:00
										 |  |  |     swap <hash-array> >>array init-hash ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  | : hash-count+ ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2011-11-12 18:35:19 -05:00
										 |  |  |     [ 1 fixnum+fast ] change-count drop ; inline
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : hash-deleted+ ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2011-11-12 18:35:19 -05:00
										 |  |  |     [ 1 fixnum+fast ] change-deleted drop ; inline
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : hash-deleted- ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2011-11-12 18:35:19 -05:00
										 |  |  |     [ 1 fixnum-fast ] change-deleted drop ; inline
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! i = first-empty-or-found | 
					
						
							|  |  |  | ! j = first-deleted | 
					
						
							| 
									
										
										
										
											2011-11-12 18:35:19 -05:00
										 |  |  | ! empty? = if true, key was not found | 
					
						
							|  |  |  | !
 | 
					
						
							|  |  |  | ! if empty? is f: | 
					
						
							|  |  |  | ! - we want to store into i | 
					
						
							| 
									
										
										
										
											2014-10-31 04:14:31 -04:00
										 |  |  | !
 | 
					
						
							| 
									
										
										
										
											2011-11-12 18:35:19 -05:00
										 |  |  | ! if empty? is t: | 
					
						
							|  |  |  | ! - we want to store into j if j is not f | 
					
						
							|  |  |  | ! - otherwise we want to store into i | 
					
						
							|  |  |  | ! - ... and increment count | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  | : (new-key@) ( key array i probe# j -- array i j empty? )
 | 
					
						
							|  |  |  |     [ 2dup swap array-nth ] 2dip pick tombstone? | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2016-03-25 04:52:07 -04:00
										 |  |  |         rot +empty+ eq?
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  |         [ nip [ drop ] 3dip t ] | 
					
						
							|  |  |  |         [ pick or [ probe ] dip (new-key@) ] | 
					
						
							|  |  |  |         if
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         [ [ pick ] dip = ] 2dip rot
 | 
					
						
							|  |  |  |         [ nip [ drop ] 3dip f ] | 
					
						
							|  |  |  |         [ [ probe ] dip (new-key@) ] | 
					
						
							| 
									
										
										
										
											2011-10-02 16:47:51 -04:00
										 |  |  |         if
 | 
					
						
							| 
									
										
										
										
											2008-07-18 20:22:59 -04:00
										 |  |  |     ] if ; inline recursive
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  | : new-key@ ( key hash -- array n )
 | 
					
						
							| 
									
										
										
										
											2011-11-12 18:35:19 -05:00
										 |  |  |     [ array>> 2dup hash@ 0 f (new-key@) ] keep swap
 | 
					
						
							|  |  |  |     [ over [ hash-deleted- ] [ hash-count+ ] if swap or ] [ 2drop ] if ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 21:32:40 -04:00
										 |  |  | : set-nth-pair ( value key array n -- )
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     2 fixnum+fast [ set-slot ] 2keep
 | 
					
						
							|  |  |  |     1 fixnum+fast set-slot ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-08 01:01:50 -05:00
										 |  |  | : (set-at) ( value key hash -- )
 | 
					
						
							|  |  |  |     dupd new-key@ set-nth-pair ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (rehash) ( alist hash -- )
 | 
					
						
							|  |  |  |     [ swapd (set-at) ] curry assoc-each ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : hash-large? ( hash -- ? )
 | 
					
						
							| 
									
										
										
										
											2015-07-14 21:32:40 -04:00
										 |  |  |     [ count>> 1 fixnum+fast 3 fixnum*fast ] | 
					
						
							| 
									
										
										
										
											2014-01-06 02:08:53 -05:00
										 |  |  |     [ array>> length>> ] bi fixnum>= ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 01:39:43 -05:00
										 |  |  | : each-pair ( ... array quot: ( ... key value -- ... ) -- ... )
 | 
					
						
							| 
									
										
										
										
											2013-03-21 02:02:40 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         [ length 2/ ] keep [ | 
					
						
							|  |  |  |             [ 1 fixnum-shift-fast ] dip [ array-nth ] 2keep
 | 
					
						
							|  |  |  |             pick tombstone? [ 3drop ] | 
					
						
							|  |  |  |         ] curry
 | 
					
						
							|  |  |  |     ] dip [ [ 1 fixnum+fast ] dip array-nth ] prepose
 | 
					
						
							|  |  |  |     [ if ] curry compose each-integer ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | : grow-hash ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2013-03-07 23:51:46 -05:00
										 |  |  |     { hashtable } declare [ | 
					
						
							| 
									
										
										
										
											2013-03-21 02:02:40 -04:00
										 |  |  |         [ array>> ] | 
					
						
							| 
									
										
										
										
											2013-03-07 23:51:46 -05:00
										 |  |  |         [ assoc-size 1 + ] | 
					
						
							|  |  |  |         [ reset-hash ] tri
 | 
					
						
							| 
									
										
										
										
											2013-03-21 02:02:40 -04:00
										 |  |  |     ] keep [ swapd (set-at) ] curry each-pair ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : ?grow-hash ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2011-11-10 15:37:14 -05:00
										 |  |  |     dup hash-large? [ grow-hash ] [ drop ] if ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <hashtable> ( n -- hash )
 | 
					
						
							| 
									
										
										
										
											2015-07-14 21:32:40 -04:00
										 |  |  |     integer>fixnum-strict
 | 
					
						
							| 
									
										
										
										
											2014-01-08 12:56:00 -05:00
										 |  |  |     [ 0 0 ] dip <hash-array> hashtable boa ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-23 19:56:17 -04:00
										 |  |  | M: hashtable at* | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     key@ [ 3 fixnum+fast slot t ] [ 2drop f f ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-23 19:56:17 -04:00
										 |  |  | M: hashtable clear-assoc | 
					
						
							| 
									
										
										
										
											2016-03-25 04:52:07 -04:00
										 |  |  |     [ init-hash ] [ array>> [ drop +empty+ ] map! drop ] bi ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-23 19:56:17 -04:00
										 |  |  | M: hashtable delete-at | 
					
						
							| 
									
										
										
										
											2009-01-23 19:20:47 -05:00
										 |  |  |     [ nip ] [ key@ ] 2bi [ | 
					
						
							| 
									
										
										
										
											2016-03-25 04:52:07 -04:00
										 |  |  |         [ +tombstone+ dup ] 2dip set-nth-pair | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         hash-deleted+ | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         3drop
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-23 19:56:17 -04:00
										 |  |  | M: hashtable assoc-size | 
					
						
							| 
									
										
										
										
											2009-08-17 23:32:21 -04:00
										 |  |  |     [ count>> ] [ deleted>> ] bi - ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : rehash ( hash -- )
 | 
					
						
							| 
									
										
										
										
											2013-03-08 01:01:50 -05:00
										 |  |  |     [ >alist ] [ clear-assoc ] [ (rehash) ] tri ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-23 19:56:17 -04:00
										 |  |  | M: hashtable set-at | 
					
						
							| 
									
										
										
										
											2013-03-08 01:01:50 -05:00
										 |  |  |     dup ?grow-hash (set-at) ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : associate ( value key -- hash )
 | 
					
						
							| 
									
										
										
										
											2014-02-07 01:39:43 -05:00
										 |  |  |     [ 1 0 ] 2dip 1 <hash-array> | 
					
						
							|  |  |  |     [ 2dup hash@ set-nth-pair ] keep
 | 
					
						
							|  |  |  |     hashtable boa ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 01:10:50 -05:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:36:39 -04:00
										 |  |  | : collect-pairs ( hash quot: ( key value -- elt ) -- seq )
 | 
					
						
							| 
									
										
										
										
											2014-02-07 01:39:43 -05:00
										 |  |  |     [ [ array>> 0 swap ] [ assoc-size f <array> ] bi ] dip swap [ | 
					
						
							|  |  |  |         [ [ over ] dip set-nth-unsafe 1 + ] curry compose each-pair | 
					
						
							|  |  |  |     ] keep nip ; inline
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:36:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 01:10:50 -05:00
										 |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:36:39 -04:00
										 |  |  | M: hashtable >alist [ 2array ] collect-pairs ;
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:20:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:36:39 -04:00
										 |  |  | M: hashtable keys [ drop ] collect-pairs ;
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:20:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:36:39 -04:00
										 |  |  | M: hashtable values [ nip ] collect-pairs ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable clone | 
					
						
							| 
									
										
										
										
											2009-08-17 23:32:21 -04:00
										 |  |  |     (clone) [ clone ] change-array ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable equal? | 
					
						
							| 
									
										
										
										
											2011-01-03 23:37:17 -05:00
										 |  |  |     over hashtable? [ assoc= ] [ 2drop f ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Default method | 
					
						
							| 
									
										
										
										
											2009-08-17 23:32:21 -04:00
										 |  |  | M: assoc new-assoc drop <hashtable> ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-17 23:32:21 -04:00
										 |  |  | M: f new-assoc drop <hashtable> ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : >hashtable ( assoc -- hashtable )
 | 
					
						
							| 
									
										
										
										
											2013-03-08 01:01:50 -05:00
										 |  |  |     [ >alist ] [ assoc-size <hashtable> ] bi [ (rehash) ] keep ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: hashtable assoc-like | 
					
						
							| 
									
										
										
										
											2009-08-17 23:32:21 -04:00
										 |  |  |     drop dup hashtable? [ >hashtable ] unless ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : ?set-at ( value key assoc/f -- assoc )
 | 
					
						
							|  |  |  |     [ [ set-at ] keep ] [ associate ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-02 23:28:51 -04:00
										 |  |  | ! borrowed from boost::hash_combine, but the | 
					
						
							|  |  |  | ! magic number is 2^29/phi instead of 2^32/phi | 
					
						
							|  |  |  | ! due to max fixnum value on 32-bit machines | 
					
						
							| 
									
										
										
										
											2015-06-09 19:08:48 -04:00
										 |  |  | : hash-combine ( hash1 hash2 -- newhash )
 | 
					
						
							| 
									
										
										
										
											2015-06-11 23:33:47 -04:00
										 |  |  |     [ 0x13c6ef37 + ] dip [ 6 shift ] [ -2 shift ] bi + + ; inline
 | 
					
						
							| 
									
										
										
										
											2015-06-09 19:08:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-24 18:00:33 -04:00
										 |  |  | ERROR: malformed-hashtable-pair seq pair ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-hashtable ( seq -- seq )
 | 
					
						
							| 
									
										
										
										
											2015-08-13 19:13:05 -04:00
										 |  |  |     dup [ dup length 2 = [ drop ] [ malformed-hashtable-pair ] if ] each ;
 | 
					
						
							| 
									
										
										
										
											2012-08-24 18:00:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : parse-hashtable ( seq -- hashtable )
 | 
					
						
							|  |  |  |     check-hashtable H{ } assoc-clone-like ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | INSTANCE: hashtable assoc |