factor/core/hashtables/hashtables.factor

158 lines
3.7 KiB
Factor
Raw Normal View History

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.
USING: accessors arrays kernel kernel.private slots.private math
assocs math.private sequences sequences.private vectors grouping ;
2007-09-20 18:09:08 -04:00
IN: hashtables
TUPLE: hashtable
2008-06-29 22:37:57 -04:00
{ count array-capacity }
{ deleted array-capacity }
{ array array } ;
2007-09-20 18:09:08 -04:00
<PRIVATE
: wrap ( i array -- n )
array-capacity 1 fixnum-fast fixnum-bitand ; inline
: 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
] if ; inline
2007-09-20 18:09:08 -04:00
: key@ ( key hash -- array n ? )
2008-07-14 00:26:20 -04:00
array>> dup array-capacity 0 eq?
[ 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 -- )
0 >>count 0 >>deleted drop ; inline
2007-09-20 18:09:08 -04:00
: reset-hash ( n hash -- )
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
] if ; inline
: new-key@ ( key hash -- array n empty? )
array>> 2dup hash@ (new-key@) ; inline
2007-09-20 18:09:08 -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 -- )
[ 1+ ] change-count drop ; inline
2007-09-20 18:09:08 -04:00
: hash-deleted+ ( hash -- )
[ 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 ]
[ array>> array-capacity ] 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 )
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 -- )
[ init-hash ] [ array>> [ drop ((empty)) ] change-each ] bi ;
2007-09-20 18:09:08 -04:00
M: hashtable delete-at ( key hash -- )
tuck key@ [
>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 )
[ count>> ] [ deleted>> ] bi - ;
2007-09-20 18:09:08 -04:00
: rehash ( hash -- )
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-06-09 06:22:21 -04:00
M: hashtable >alist
array>> 2 <groups> [ first tombstone? not ] filter ;
2007-09-20 18:09:08 -04:00
M: hashtable clone
(clone) [ clone ] change-array ;
2007-09-20 18:09:08 -04:00
M: hashtable equal?
over hashtable? [
2008-03-29 21:36:58 -04:00
2dup [ assoc-size ] bi@ number=
[ 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