/utilhash.txt
\ Dynamic hash lists--definitions and allocation                     vandys
\ This file has a stillborn implementation of a list of values.  Set has
\  replaced it, so all that remains here are generic hashing functions
\  used by other places which use hash-based techniques.
only extensions definitions

37 constant (#INITHASH)
100 constant (BINLEN) Local

0 [if]
Collection -> subclass: Hash ivars:
   intcell #hash   intcell bucks   endivars
\ Each slot in "bucks" is a "List" instance of values

Hash -> class -> :method new ( self -- hash )   super-> new ( hash )
   (#INITHASH)   over Hash>#hash !
   (#INITHASH) cells bkzalloc   over Hash>bucks !   method;
[then]







\ Dynamic hash lists--hashing                                        vandys

: (>hash) ( ptr -- u )   5 rshift   dup 16 rshift xor ;
0 [if]
: (>bin) { idx self -- idx' }
   idx (>hash)   self Hash>#hash @ mod ; Local
[then]


















\ Dynamic hash lists--growth of bucket size                          vandys

: prime? ( u -- bool )   dup 2/ 1+   3 do   dup i mod 0= if
      unloop drop false exit   then
   2 +loop   drop true ; scrLocal

: (>newhash) ( u -- u' )   2* 1+ begin   dup prime? not   while
   2 +   repeat ;
0 [if]
: (put) ( hash val -- )   swap -> ! ; scrLocal

Hash -> :method grow { self -- }
   self Hash>#hash @   self Hash>bucks @ { old# oldbucks }
   old# (>newhash) { new# }   new# cells bkzalloc { newbucks }
   new# self Hash>#hash !   newbucks self Hash>bucks !
   oldbucks   old# 0 do   @+ ?dup if ( 'buck+ buck )
      self   ['] (put)   rot -> do   then   loop drop
   oldbucks bkfree   method;
[then]






\ Dynamic hash lists--insertion                                      vandys
0 [if]
Hash -> :method add { val self -- }
   val self (>bin) cells   self Hash>bucks @ + { 'bin }
   'bin @ ?dup 0= if
      List -> new   dup 'bin !   val swap -> add   exit then
   { bin } val bin -> in? if   exit   then
   bin -> size (BINLEN) >= if   self -> grow   then   method;
[then]
















\ Dynamic hash lists--testing & display                              vandys
0 [if]
Hash -> :method in? { key self -- T | F }   key self (>bin) ( buckidx )
   cells   self Hash>bucks @ + @   dup 0= if exit then
   { buck }   key buck -> in?   method;

Hash -> :method . { self -- }   ." Hash {"
   self Hash>bucks @   self Hash>#hash @ 0 do
      @+ ?dup if   ( 'buck+ buck ) -> .   then
   loop   drop   ." }" method;
[then]