1 ! Copyright (C) 2005, 2007 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays kernel kernel.private slots.private math assocs
4 math.private sequences sequences.private vectors ;
9 : wrap ( i array -- n )
10 array-capacity 1 fixnum-fast fixnum-bitand ; inline
12 : hash@ ( key array -- i )
13 >r hashcode >fixnum dup fixnum+fast r> wrap ; inline
15 : probe ( array i -- array i )
16 2 fixnum+fast over wrap ; inline
18 : (key@) ( key keys i -- array n ? )
22 = [ rot drop t ] [ probe (key@) ] if
25 : key@ ( key hash -- array n ? )
26 hash-array 2dup hash@ (key@) ; inline
28 : <hash-array> ( n -- array )
29 1+ next-power-of-2 4 * ((empty)) <array> ; inline
31 : init-hash ( hash -- )
32 0 over set-hash-count 0 swap set-hash-deleted ;
34 : reset-hash ( n hash -- )
35 swap <hash-array> over set-hash-array init-hash ;
37 : (new-key@) ( key keys i -- keys n empty? )
38 3dup swap array-nth dup ((empty)) eq? [
48 : new-key@ ( key hash -- array n empty? )
49 hash-array 2dup hash@ (new-key@) ; inline
51 : nth-pair ( n seq -- key value )
52 swap 2 fixnum+fast 2dup slot -rot 1 fixnum+fast slot ;
55 : set-nth-pair ( value key seq n -- )
56 2 fixnum+fast [ set-slot ] 2keep
57 1 fixnum+fast set-slot ; inline
59 : hash-count+ ( hash -- )
60 dup hash-count 1+ swap set-hash-count ; inline
62 : hash-deleted+ ( hash -- )
63 dup hash-deleted 1+ swap set-hash-deleted ; inline
65 : (set-hash) ( value key hash -- new? )
67 [ rot hash-count+ set-nth-pair t ]
68 [ rot drop set-nth-pair f ] if ; inline
70 : find-pair-next >r 2 fixnum+fast r> ; inline
72 : (find-pair) ( quot i array -- key value ? )
73 2dup array-capacity eq? [
76 2dup array-nth tombstone? [
77 find-pair-next (find-pair)
79 [ nth-pair rot call ] 3keep roll [
82 find-pair-next (find-pair)
87 : find-pair ( array quot -- key value ? )
88 0 rot (find-pair) ; inline
90 : (rehash) ( hash array -- )
91 [ swap pick (set-hash) drop f ] find-pair 2drop 2drop ;
93 : hash-large? ( hash -- ? )
94 [ hash-count 3 fixnum*fast ]
95 [ hash-array array-capacity ] bi > ;
97 : hash-stale? ( hash -- ? )
98 [ hash-deleted 10 fixnum*fast ] [ hash-count ] bi fixnum> ;
100 : grow-hash ( hash -- )
101 [ dup hash-array swap assoc-size 1+ ] keep
105 : ?grow-hash ( hash -- )
118 : <hashtable> ( n -- hash )
119 hashtable new [ reset-hash ] keep ;
121 M: hashtable at* ( key hash -- value ? )
122 key@ [ 3 fixnum+fast slot t ] [ 2drop f f ] if ;
124 M: hashtable clear-assoc ( hash -- )
125 dup init-hash hash-array [ drop ((empty)) ] change-each ;
127 M: hashtable delete-at ( key hash -- )
129 >r >r ((tombstone)) dup r> r> set-nth-pair
135 M: hashtable assoc-size ( hash -- n )
136 dup hash-count swap hash-deleted - ;
140 dup length ((empty)) <array> pick set-hash-array
141 0 pick set-hash-count
142 0 pick set-hash-deleted
145 M: hashtable set-at ( value key hash -- )
146 dup >r (set-hash) [ r> ?grow-hash ] [ r> drop ] if ;
148 : associate ( value key -- hash )
149 2 <hashtable> [ set-at ] keep ;
151 M: hashtable assoc-find ( hash quot -- key value ? )
152 >r hash-array r> find-pair ;
155 (clone) dup hash-array clone over set-hash-array ;
159 2dup [ assoc-size ] bi@ number=
160 [ assoc= ] [ 2drop f ] if
164 M: assoc new-assoc drop <hashtable> ;
166 M: f new-assoc drop <hashtable> ;
168 : >hashtable ( assoc -- hashtable )
169 H{ } assoc-clone-like ;
171 M: hashtable assoc-like
172 drop dup hashtable? [ >hashtable ] unless ;
174 : ?set-at ( value key assoc/f -- assoc )
175 [ [ set-at ] keep ] [ associate ] if* ;
177 INSTANCE: hashtable assoc