Merge branch 'master' of git://factorcode.org/git/factor
commit
1d708f35f1
|
@ -32,7 +32,7 @@ HELP: assoc>disjoint-set
|
||||||
"4 5 pick equiv? ."
|
"4 5 pick equiv? ."
|
||||||
"1 5 pick equiv? ."
|
"1 5 pick equiv? ."
|
||||||
"drop"
|
"drop"
|
||||||
"t\nt\nf\n"
|
"t\nt\nf"
|
||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
IN: io.windows.launcher.nt.tests
|
IN: io.windows.launcher.nt.tests
|
||||||
USING: io.launcher tools.test calendar accessors
|
USING: io.launcher tools.test calendar accessors
|
||||||
namespaces kernel system arrays io io.files io.encodings.ascii
|
namespaces kernel system arrays io io.files io.encodings.ascii
|
||||||
sequences parser assocs hashtables math continuations ;
|
sequences parser assocs hashtables math continuations eval ;
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
<process>
|
<process>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: kernel assocs ;
|
||||||
|
IN: persistent.assocs
|
||||||
|
|
||||||
|
GENERIC: new-at ( value key assoc -- assoc' )
|
||||||
|
|
||||||
|
M: assoc new-at clone [ set-at ] keep ;
|
||||||
|
|
||||||
|
GENERIC: pluck-at ( key assoc -- assoc' )
|
||||||
|
|
||||||
|
M: assoc pluck-at clone [ delete-at ] keep ;
|
||||||
|
|
||||||
|
: changed-at ( key assoc quot -- assoc' )
|
||||||
|
[ [ at ] dip call ] [ drop new-at ] 3bi ; inline
|
||||||
|
|
||||||
|
: conjoined ( key assoc -- assoc' )
|
||||||
|
dupd new-at ;
|
|
@ -0,0 +1 @@
|
||||||
|
Persistent associative mapping protocol
|
|
@ -0,0 +1 @@
|
||||||
|
Slava Pestov
|
|
@ -0,0 +1,8 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: layouts kernel parser math ;
|
||||||
|
IN: persistent.hashtables.config
|
||||||
|
|
||||||
|
: radix-bits ( -- n ) << cell 4 = 4 5 ? parsed >> ; foldable
|
||||||
|
: radix-mask ( -- n ) radix-bits 2^ 1- ; foldable
|
||||||
|
: full-bitmap-mask ( -- n ) radix-bits 2^ 2^ 1- ; inline
|
|
@ -0,0 +1,110 @@
|
||||||
|
IN: persistent.hashtables.tests
|
||||||
|
USING: persistent.hashtables persistent.assocs hashtables assocs
|
||||||
|
tools.test kernel namespaces random math.ranges sequences fry ;
|
||||||
|
|
||||||
|
[ t ] [ PH{ } assoc-empty? ] unit-test
|
||||||
|
|
||||||
|
[ PH{ { "A" "B" } } ] [ PH{ } "B" "A" rot new-at ] unit-test
|
||||||
|
|
||||||
|
[ "B" ] [ "A" PH{ { "A" "B" } } at ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ "X" PH{ { "A" "B" } } at ] unit-test
|
||||||
|
|
||||||
|
TUPLE: hash-0-a ;
|
||||||
|
|
||||||
|
M: hash-0-a hashcode* 2drop 0 ;
|
||||||
|
|
||||||
|
TUPLE: hash-0-b ;
|
||||||
|
|
||||||
|
M: hash-0-b hashcode* 2drop 0 ;
|
||||||
|
|
||||||
|
[ ] [
|
||||||
|
PH{ }
|
||||||
|
"a" T{ hash-0-a } rot new-at
|
||||||
|
"b" T{ hash-0-b } rot new-at
|
||||||
|
"ph" set
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
H{
|
||||||
|
{ T{ hash-0-a } "a" }
|
||||||
|
{ T{ hash-0-b } "b" }
|
||||||
|
}
|
||||||
|
] [ "ph" get >hashtable ] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
H{
|
||||||
|
{ T{ hash-0-b } "b" }
|
||||||
|
}
|
||||||
|
] [ "ph" get T{ hash-0-a } swap pluck-at >hashtable ] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
H{
|
||||||
|
{ T{ hash-0-a } "a" }
|
||||||
|
}
|
||||||
|
] [ "ph" get T{ hash-0-b } swap pluck-at >hashtable ] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
H{
|
||||||
|
{ T{ hash-0-a } "a" }
|
||||||
|
{ T{ hash-0-b } "b" }
|
||||||
|
}
|
||||||
|
] [ "ph" get "X" swap pluck-at >hashtable ] unit-test
|
||||||
|
|
||||||
|
[ ] [
|
||||||
|
PH{ }
|
||||||
|
"B" "A" rot new-at
|
||||||
|
"D" "C" rot new-at
|
||||||
|
"ph" set
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ H{ { "A" "B" } { "C" "D" } } ] [
|
||||||
|
"ph" get >hashtable
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ H{ { "C" "D" } } ] [
|
||||||
|
"ph" get "A" swap pluck-at >hashtable
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ H{ { "A" "B" } { "C" "D" } { "E" "F" } } ] [
|
||||||
|
"ph" get "F" "E" rot new-at >hashtable
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ H{ { "C" "D" } { "E" "F" } } ] [
|
||||||
|
"ph" get "F" "E" rot new-at "A" swap pluck-at >hashtable
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
: random-string ( -- str )
|
||||||
|
1000000 random ; ! [ CHAR: a CHAR: z [a,b] random ] "" replicate-as ;
|
||||||
|
|
||||||
|
: random-assocs ( -- hash phash )
|
||||||
|
[ random-string ] replicate
|
||||||
|
[ H{ } clone [ '[ swap , set-at ] each-index ] keep ]
|
||||||
|
[ PH{ } clone swap [ spin new-at ] each-index ]
|
||||||
|
bi ;
|
||||||
|
|
||||||
|
: ok? ( assoc1 assoc2 -- ? )
|
||||||
|
[ assoc= ] [ [ assoc-size ] bi@ = ] 2bi and ;
|
||||||
|
|
||||||
|
: test-persistent-hashtables-1 ( n -- )
|
||||||
|
random-assocs ok? ;
|
||||||
|
|
||||||
|
[ t ] [ 10 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 20 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 30 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 50 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 100 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 500 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 1000 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 5000 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 10000 test-persistent-hashtables-1 ] unit-test
|
||||||
|
[ t ] [ 50000 test-persistent-hashtables-1 ] unit-test
|
||||||
|
|
||||||
|
: test-persistent-hashtables-2 ( n -- )
|
||||||
|
random-assocs
|
||||||
|
dup keys [
|
||||||
|
[ nip over delete-at ] [ swap pluck-at nip ] 3bi
|
||||||
|
2dup ok?
|
||||||
|
] all? 2nip ;
|
||||||
|
|
||||||
|
[ t ] [ 6000 test-persistent-hashtables-2 ] unit-test
|
|
@ -0,0 +1,48 @@
|
||||||
|
! Based on Clojure's PersistentHashMap by Rich Hickey.
|
||||||
|
|
||||||
|
USING: kernel math accessors assocs fry combinators parser
|
||||||
|
prettyprint.backend namespaces
|
||||||
|
persistent.assocs
|
||||||
|
persistent.hashtables.nodes
|
||||||
|
persistent.hashtables.nodes.empty
|
||||||
|
persistent.hashtables.nodes.leaf
|
||||||
|
persistent.hashtables.nodes.full
|
||||||
|
persistent.hashtables.nodes.bitmap
|
||||||
|
persistent.hashtables.nodes.collision ;
|
||||||
|
IN: persistent.hashtables
|
||||||
|
|
||||||
|
TUPLE: persistent-hash
|
||||||
|
{ root read-only initial: empty-node }
|
||||||
|
{ count fixnum read-only } ;
|
||||||
|
|
||||||
|
M: persistent-hash assoc-size count>> ;
|
||||||
|
|
||||||
|
M: persistent-hash at*
|
||||||
|
[ dup hashcode >fixnum ] [ root>> ] bi* (entry-at)
|
||||||
|
dup [ value>> t ] [ f ] if ;
|
||||||
|
|
||||||
|
M: persistent-hash new-at ( value key assoc -- assoc' )
|
||||||
|
[
|
||||||
|
{ [ 0 ] [ ] [ dup hashcode >fixnum ] [ root>> ] } spread
|
||||||
|
(new-at) 1 0 ?
|
||||||
|
] [ count>> ] bi +
|
||||||
|
persistent-hash boa ;
|
||||||
|
|
||||||
|
M: persistent-hash pluck-at
|
||||||
|
[ [ dup hashcode >fixnum ] [ root>> ] bi* (pluck-at) ] keep
|
||||||
|
{
|
||||||
|
{ [ 2dup root>> eq? ] [ nip ] }
|
||||||
|
{ [ over not ] [ 2drop T{ persistent-hash } ] }
|
||||||
|
[ count>> 1- persistent-hash boa ]
|
||||||
|
} cond ;
|
||||||
|
|
||||||
|
M: persistent-hash >alist [ root>> >alist% ] { } make ;
|
||||||
|
|
||||||
|
: >persistent-hash ( assoc -- phash )
|
||||||
|
T{ persistent-hash } swap [ spin new-at ] assoc-each ;
|
||||||
|
|
||||||
|
: PH{ \ } [ >persistent-hash ] parse-literal ; parsing
|
||||||
|
|
||||||
|
M: persistent-hash pprint-delims drop \ PH{ \ } ;
|
||||||
|
|
||||||
|
M: persistent-hash >pprint-sequence >alist ;
|
|
@ -0,0 +1,86 @@
|
||||||
|
! Based on Clojure's PersistentHashMap by Rich Hickey.
|
||||||
|
|
||||||
|
USING: math math.bit-count arrays kernel accessors locals sequences
|
||||||
|
sequences.private sequences.lib
|
||||||
|
persistent.sequences
|
||||||
|
persistent.hashtables.config
|
||||||
|
persistent.hashtables.nodes ;
|
||||||
|
IN: persistent.hashtables.nodes.bitmap
|
||||||
|
|
||||||
|
: index ( bit bitmap -- n ) [ 1- ] dip bitand bit-count ; inline
|
||||||
|
|
||||||
|
M:: bitmap-node (entry-at) ( key hashcode bitmap-node -- entry )
|
||||||
|
[let* | shift [ bitmap-node shift>> ]
|
||||||
|
bit [ hashcode shift bitpos ]
|
||||||
|
bitmap [ bitmap-node bitmap>> ]
|
||||||
|
nodes [ bitmap-node nodes>> ] |
|
||||||
|
bitmap bit bitand 0 eq? [ f ] [
|
||||||
|
key hashcode
|
||||||
|
bit bitmap index nodes nth-unsafe
|
||||||
|
(entry-at)
|
||||||
|
] if
|
||||||
|
] ;
|
||||||
|
|
||||||
|
M:: bitmap-node (new-at) ( shift value key hashcode bitmap-node -- node' added-leaf )
|
||||||
|
[let* | shift [ bitmap-node shift>> ]
|
||||||
|
bit [ hashcode shift bitpos ]
|
||||||
|
bitmap [ bitmap-node bitmap>> ]
|
||||||
|
idx [ bit bitmap index ]
|
||||||
|
nodes [ bitmap-node nodes>> ] |
|
||||||
|
bitmap bit bitand 0 eq? [
|
||||||
|
[let | new-leaf [ value key hashcode <leaf-node> ] |
|
||||||
|
bitmap bit bitor
|
||||||
|
new-leaf idx nodes insert-nth
|
||||||
|
shift
|
||||||
|
<bitmap-node>
|
||||||
|
new-leaf
|
||||||
|
]
|
||||||
|
] [
|
||||||
|
[let | n [ idx nodes nth ] |
|
||||||
|
shift radix-bits + value key hashcode n (new-at)
|
||||||
|
[let | new-leaf [ ] n' [ ] |
|
||||||
|
n n' eq? [
|
||||||
|
bitmap-node
|
||||||
|
] [
|
||||||
|
bitmap
|
||||||
|
n' idx nodes new-nth
|
||||||
|
shift
|
||||||
|
<bitmap-node>
|
||||||
|
] if
|
||||||
|
new-leaf
|
||||||
|
]
|
||||||
|
]
|
||||||
|
] if
|
||||||
|
] ;
|
||||||
|
|
||||||
|
M:: bitmap-node (pluck-at) ( key hashcode bitmap-node -- node' )
|
||||||
|
[let | bit [ hashcode bitmap-node shift>> bitpos ]
|
||||||
|
bitmap [ bitmap-node bitmap>> ]
|
||||||
|
nodes [ bitmap-node nodes>> ]
|
||||||
|
shift [ bitmap-node shift>> ] |
|
||||||
|
bit bitmap bitand 0 eq? [ bitmap-node ] [
|
||||||
|
[let* | idx [ bit bitmap index ]
|
||||||
|
n [ idx nodes nth-unsafe ]
|
||||||
|
n' [ key hashcode n (pluck-at) ] |
|
||||||
|
n n' eq? [
|
||||||
|
bitmap-node
|
||||||
|
] [
|
||||||
|
n' [
|
||||||
|
bitmap
|
||||||
|
n' idx nodes new-nth
|
||||||
|
shift
|
||||||
|
<bitmap-node>
|
||||||
|
] [
|
||||||
|
bitmap bit eq? [ f ] [
|
||||||
|
bitmap bit bitnot bitand
|
||||||
|
idx nodes remove-nth
|
||||||
|
shift
|
||||||
|
<bitmap-node>
|
||||||
|
] if
|
||||||
|
] if
|
||||||
|
] if
|
||||||
|
]
|
||||||
|
] if
|
||||||
|
] ;
|
||||||
|
|
||||||
|
M: bitmap-node >alist% ( node -- ) nodes>> >alist-each% ;
|
|
@ -0,0 +1,59 @@
|
||||||
|
! Based on Clojure's PersistentHashMap by Rich Hickey.
|
||||||
|
|
||||||
|
USING: kernel accessors math arrays fry sequences sequences.lib
|
||||||
|
locals persistent.sequences
|
||||||
|
persistent.hashtables.config
|
||||||
|
persistent.hashtables.nodes
|
||||||
|
persistent.hashtables.nodes.leaf ;
|
||||||
|
IN: persistent.hashtables.nodes.collision
|
||||||
|
|
||||||
|
: find-index ( key hashcode collision-node -- n leaf-node )
|
||||||
|
leaves>> -rot '[ , , _ matching-key? ] find ; inline
|
||||||
|
|
||||||
|
M:: collision-node (entry-at) ( key hashcode collision-node -- leaf-node )
|
||||||
|
key hashcode collision-node find-index nip ;
|
||||||
|
|
||||||
|
M:: collision-node (pluck-at) ( key hashcode collision-node -- leaf-node )
|
||||||
|
hashcode collision-node hashcode>> eq? [
|
||||||
|
[let | idx [ key hashcode collision-node find-index drop ] |
|
||||||
|
idx [
|
||||||
|
idx collision-node leaves>> smash [
|
||||||
|
collision-node hashcode>>
|
||||||
|
<collision-node>
|
||||||
|
] when
|
||||||
|
] [ collision-node ] if
|
||||||
|
]
|
||||||
|
] [ collision-node ] if ;
|
||||||
|
|
||||||
|
M:: collision-node (new-at) ( shift value key hashcode collision-node -- node' added-leaf )
|
||||||
|
hashcode collision-node hashcode>> eq? [
|
||||||
|
key hashcode collision-node find-index
|
||||||
|
[let | leaf-node [ ] idx [ ] |
|
||||||
|
idx [
|
||||||
|
value leaf-node value>> = [
|
||||||
|
collision-node f
|
||||||
|
] [
|
||||||
|
hashcode
|
||||||
|
value key hashcode <leaf-node>
|
||||||
|
idx
|
||||||
|
collision-node leaves>>
|
||||||
|
new-nth
|
||||||
|
<collision-node>
|
||||||
|
f
|
||||||
|
] if
|
||||||
|
] [
|
||||||
|
[let | new-leaf-node [ value key hashcode <leaf-node> ] |
|
||||||
|
hashcode
|
||||||
|
collision-node leaves>>
|
||||||
|
new-leaf-node
|
||||||
|
suffix
|
||||||
|
<collision-node>
|
||||||
|
new-leaf-node
|
||||||
|
]
|
||||||
|
] if
|
||||||
|
]
|
||||||
|
] [
|
||||||
|
shift collision-node value key hashcode make-bitmap-node
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
M: collision-node >alist% leaves>> >alist-each% ;
|
|
@ -0,0 +1,15 @@
|
||||||
|
! Based on Clojure's PersistentHashMap by Rich Hickey.
|
||||||
|
|
||||||
|
USING: accessors kernel locals persistent.hashtables.nodes ;
|
||||||
|
IN: persistent.hashtables.nodes.empty
|
||||||
|
|
||||||
|
M: empty-node (entry-at) 3drop f ;
|
||||||
|
|
||||||
|
M: empty-node (pluck-at) 2nip ;
|
||||||
|
|
||||||
|
M:: empty-node (new-at) ( shift value key hashcode node -- node' added-leaf )
|
||||||
|
value key hashcode <leaf-node> dup ;
|
||||||
|
|
||||||
|
M: empty-node >alist% drop ;
|
||||||
|
|
||||||
|
M: empty-node hashcode>> drop 0 ;
|
|
@ -0,0 +1,51 @@
|
||||||
|
! Based on Clojure's PersistentHashMap by Rich Hickey.
|
||||||
|
|
||||||
|
USING: math accessors kernel arrays sequences sequences.private
|
||||||
|
locals sequences.lib
|
||||||
|
persistent.sequences
|
||||||
|
persistent.hashtables.config
|
||||||
|
persistent.hashtables.nodes ;
|
||||||
|
IN: persistent.hashtables.nodes.full
|
||||||
|
|
||||||
|
M:: full-node (new-at) ( shift value key hashcode full-node -- node' added-leaf )
|
||||||
|
[let* | nodes [ full-node nodes>> ]
|
||||||
|
idx [ hashcode full-node shift>> mask ]
|
||||||
|
n [ idx nodes nth-unsafe ] |
|
||||||
|
shift radix-bits + value key hashcode n (new-at)
|
||||||
|
[let | new-leaf [ ] n' [ ] |
|
||||||
|
n n' eq? [
|
||||||
|
full-node
|
||||||
|
] [
|
||||||
|
n' idx nodes new-nth shift <full-node>
|
||||||
|
] if
|
||||||
|
new-leaf
|
||||||
|
]
|
||||||
|
] ;
|
||||||
|
|
||||||
|
M:: full-node (pluck-at) ( key hashcode full-node -- node' )
|
||||||
|
[let* | idx [ hashcode full-node shift>> mask ]
|
||||||
|
n [ idx full-node nodes>> nth ]
|
||||||
|
n' [ key hashcode n (pluck-at) ] |
|
||||||
|
n n' eq? [
|
||||||
|
full-node
|
||||||
|
] [
|
||||||
|
n' [
|
||||||
|
n' idx full-node nodes>> new-nth
|
||||||
|
full-node shift>>
|
||||||
|
<full-node>
|
||||||
|
] [
|
||||||
|
hashcode full-node shift>> bitpos bitnot full-bitmap-mask bitand
|
||||||
|
idx full-node nodes>> remove-nth
|
||||||
|
full-node shift>>
|
||||||
|
<bitmap-node>
|
||||||
|
] if
|
||||||
|
] if
|
||||||
|
] ;
|
||||||
|
|
||||||
|
M:: full-node (entry-at) ( key hashcode full-node -- node' )
|
||||||
|
key hashcode
|
||||||
|
hashcode full-node shift>> mask
|
||||||
|
full-node nodes>> nth-unsafe
|
||||||
|
(entry-at) ;
|
||||||
|
|
||||||
|
M: full-node >alist% nodes>> >alist-each% ;
|
|
@ -0,0 +1,28 @@
|
||||||
|
! Based on Clojure's PersistentHashMap by Rich Hickey.
|
||||||
|
|
||||||
|
USING: kernel accessors locals math arrays namespaces
|
||||||
|
persistent.hashtables.config
|
||||||
|
persistent.hashtables.nodes ;
|
||||||
|
IN: persistent.hashtables.nodes.leaf
|
||||||
|
|
||||||
|
: matching-key? ( key hashcode leaf-node -- ? )
|
||||||
|
tuck hashcode>> eq? [ key>> = ] [ 2drop f ] if ; inline
|
||||||
|
|
||||||
|
M: leaf-node (entry-at) [ matching-key? ] keep and ;
|
||||||
|
|
||||||
|
M: leaf-node (pluck-at) [ matching-key? not ] keep and ;
|
||||||
|
|
||||||
|
M:: leaf-node (new-at) ( shift value key hashcode leaf-node -- node' added-leaf )
|
||||||
|
hashcode leaf-node hashcode>> eq? [
|
||||||
|
key leaf-node key>> = [
|
||||||
|
value leaf-node value>> =
|
||||||
|
[ leaf-node f ] [ value key hashcode <leaf-node> f ] if
|
||||||
|
] [
|
||||||
|
[let | new-leaf [ value key hashcode <leaf-node> ] |
|
||||||
|
hashcode leaf-node new-leaf 2array <collision-node>
|
||||||
|
new-leaf
|
||||||
|
]
|
||||||
|
] if
|
||||||
|
] [ shift leaf-node value key hashcode make-bitmap-node ] if ;
|
||||||
|
|
||||||
|
M: leaf-node >alist% [ key>> ] [ value>> ] bi 2array , ;
|
|
@ -0,0 +1,64 @@
|
||||||
|
! Based on Clojure's PersistentHashMap by Rich Hickey.
|
||||||
|
|
||||||
|
USING: math arrays kernel sequences sequences.lib
|
||||||
|
accessors locals persistent.hashtables.config ;
|
||||||
|
IN: persistent.hashtables.nodes
|
||||||
|
|
||||||
|
SINGLETON: empty-node
|
||||||
|
|
||||||
|
TUPLE: leaf-node
|
||||||
|
{ value read-only }
|
||||||
|
{ key read-only }
|
||||||
|
{ hashcode fixnum read-only } ;
|
||||||
|
|
||||||
|
C: <leaf-node> leaf-node
|
||||||
|
|
||||||
|
TUPLE: collision-node
|
||||||
|
{ hashcode fixnum read-only }
|
||||||
|
{ leaves array read-only } ;
|
||||||
|
|
||||||
|
C: <collision-node> collision-node
|
||||||
|
|
||||||
|
TUPLE: full-node
|
||||||
|
{ nodes array read-only }
|
||||||
|
{ shift fixnum read-only }
|
||||||
|
{ hashcode fixnum read-only } ;
|
||||||
|
|
||||||
|
: <full-node> ( nodes shift -- node )
|
||||||
|
over first hashcode>> full-node boa ;
|
||||||
|
|
||||||
|
TUPLE: bitmap-node
|
||||||
|
{ bitmap fixnum read-only }
|
||||||
|
{ nodes array read-only }
|
||||||
|
{ shift fixnum read-only }
|
||||||
|
{ hashcode fixnum read-only } ;
|
||||||
|
|
||||||
|
: <bitmap-node> ( bitmap nodes shift -- node )
|
||||||
|
pick full-bitmap-mask =
|
||||||
|
[ <full-node> nip ]
|
||||||
|
[ over first hashcode>> bitmap-node boa ] if ;
|
||||||
|
|
||||||
|
GENERIC: (entry-at) ( key hashcode node -- entry )
|
||||||
|
|
||||||
|
GENERIC: (new-at) ( shift value key hashcode node -- node' added-leaf )
|
||||||
|
|
||||||
|
GENERIC: (pluck-at) ( key hashcode node -- node' )
|
||||||
|
|
||||||
|
GENERIC: >alist% ( node -- )
|
||||||
|
|
||||||
|
: >alist-each% ( nodes -- ) [ >alist% ] each ;
|
||||||
|
|
||||||
|
: mask ( hash shift -- n ) neg shift radix-mask bitand ; inline
|
||||||
|
|
||||||
|
: bitpos ( hash shift -- n ) mask 2^ ; inline
|
||||||
|
|
||||||
|
: smash ( idx seq -- seq/elt ? )
|
||||||
|
dup length 2 = [ [ 1 = ] dip first2 ? f ] [ remove-nth t ] if ; inline
|
||||||
|
|
||||||
|
:: make-bitmap-node ( shift branch value key hashcode -- node' added-leaf )
|
||||||
|
shift value key hashcode
|
||||||
|
branch hashcode>> shift bitpos
|
||||||
|
branch 1array
|
||||||
|
shift
|
||||||
|
<bitmap-node>
|
||||||
|
(new-at) ; inline
|
|
@ -0,0 +1 @@
|
||||||
|
Persistent hashtables with O(1) insertion, removal and lookup
|
|
@ -1,5 +1,5 @@
|
||||||
USING: help.syntax help.markup kernel arrays assocs ;
|
USING: help.syntax help.markup kernel arrays assocs ;
|
||||||
IN: persistent-heaps
|
IN: persistent.heaps
|
||||||
|
|
||||||
HELP: <persistent-heap>
|
HELP: <persistent-heap>
|
||||||
{ $values { "heap" "a persistent heap" } }
|
{ $values { "heap" "a persistent heap" } }
|
|
@ -1,5 +1,5 @@
|
||||||
USING: persistent-heaps tools.test ;
|
USING: persistent.heaps tools.test ;
|
||||||
IN: persistent-heaps.tests
|
IN: persistent.heaps.tests
|
||||||
|
|
||||||
: test-input
|
: test-input
|
||||||
{ { "hello" 3 } { "goodbye" 2 } { "whatever" 5 }
|
{ { "hello" 3 } { "goodbye" 2 } { "whatever" 5 }
|
|
@ -1,6 +1,6 @@
|
||||||
USING: kernel accessors multi-methods locals combinators math arrays
|
USING: kernel accessors multi-methods locals combinators math arrays
|
||||||
assocs namespaces sequences ;
|
assocs namespaces sequences ;
|
||||||
IN: persistent-heaps
|
IN: persistent.heaps
|
||||||
! These are minheaps
|
! These are minheaps
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
|
@ -0,0 +1 @@
|
||||||
|
collections
|
|
@ -0,0 +1 @@
|
||||||
|
Slava Pestov
|
|
@ -0,0 +1,17 @@
|
||||||
|
IN: persistent.sequences
|
||||||
|
USING: help.markup help.syntax math sequences kernel ;
|
||||||
|
|
||||||
|
HELP: new-nth
|
||||||
|
{ $values { "val" object } { "i" integer } { "seq" sequence } { "seq'" sequence } }
|
||||||
|
{ $contract "Persistent analogue of " { $link set-nth } ". Outputs a new sequence with the " { $snippet "i" } "th element replaced by " { $snippet "val" } "." }
|
||||||
|
{ $notes "This operation runs in " { $snippet "O(log_32 n)" } " time on " { $link "persistent.vectors" } " and " { $snippet "O(n)" } " time on all other sequences." } ;
|
||||||
|
|
||||||
|
HELP: ppush
|
||||||
|
{ $values { "val" object } { "seq" sequence } { "seq'" sequence } }
|
||||||
|
{ $contract "Persistent analogue of " { $link push } ". Outputs a new sequence with all elements of " { $snippet "seq" } " together with " { $snippet "val" } " added at the end." }
|
||||||
|
{ $notes "This operation runs in amortized " { $snippet "O(1)" } " time on " { $link "persistent.vectors" } " and " { $snippet "O(n)" } " time on all other sequences." } ;
|
||||||
|
|
||||||
|
HELP: ppop
|
||||||
|
{ $values { "seq" sequence } { "seq'" sequence } }
|
||||||
|
{ $contract "Persistent analogue of " { $link pop* } ". Outputs a new sequence with all elements of " { $snippet "seq" } " except for the final element." }
|
||||||
|
{ $notes "This operation runs in amortized " { $snippet "O(1)" } " time on " { $link "persistent.vectors" } " and " { $snippet "O(n)" } " time on all other sequences." } ;
|
|
@ -0,0 +1,16 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: sequences kernel ;
|
||||||
|
IN: persistent.sequences
|
||||||
|
|
||||||
|
GENERIC: ppush ( val seq -- seq' )
|
||||||
|
|
||||||
|
M: sequence ppush swap suffix ;
|
||||||
|
|
||||||
|
GENERIC: ppop ( seq -- seq' )
|
||||||
|
|
||||||
|
M: sequence ppop 1 head* ;
|
||||||
|
|
||||||
|
GENERIC: new-nth ( val i seq -- seq' )
|
||||||
|
|
||||||
|
M: sequence new-nth clone [ set-nth ] keep ;
|
|
@ -0,0 +1 @@
|
||||||
|
Persistent sequence protocol
|
|
@ -0,0 +1 @@
|
||||||
|
collections
|
|
@ -0,0 +1 @@
|
||||||
|
Slava Pestov
|
|
@ -0,0 +1 @@
|
||||||
|
Immutable vectors with O(log_32 n) random access, push, and pop
|
|
@ -0,0 +1 @@
|
||||||
|
collections
|
|
@ -1,21 +1,6 @@
|
||||||
USING: help.markup help.syntax kernel math sequences ;
|
USING: help.markup help.syntax kernel math sequences ;
|
||||||
IN: persistent-vectors
|
IN: persistent-vectors
|
||||||
|
|
||||||
HELP: new-nth
|
|
||||||
{ $values { "val" object } { "i" integer } { "seq" sequence } { "seq'" sequence } }
|
|
||||||
{ $contract "Persistent analogue of " { $link set-nth } ". Outputs a new sequence with the " { $snippet "i" } "th element replaced by " { $snippet "val" } "." }
|
|
||||||
{ $notes "This operation runs in " { $snippet "O(log_32 n)" } " time on " { $link persistent-vector } " instances and " { $snippet "O(n)" } " time on all other sequences." } ;
|
|
||||||
|
|
||||||
HELP: ppush
|
|
||||||
{ $values { "val" object } { "seq" sequence } { "seq'" sequence } }
|
|
||||||
{ $contract "Persistent analogue of " { $link push } ". Outputs a new sequence with all elements of " { $snippet "seq" } " together with " { $snippet "val" } " added at the end." }
|
|
||||||
{ $notes "This operation runs in amortized " { $snippet "O(1)" } " time on " { $link persistent-vector } " instances and " { $snippet "O(n)" } " time on all other sequences." } ;
|
|
||||||
|
|
||||||
HELP: ppop
|
|
||||||
{ $values { "seq" sequence } { "seq'" sequence } }
|
|
||||||
{ $contract "Persistent analogue of " { $link pop* } ". Outputs a new sequence with all elements of " { $snippet "seq" } " except for the final element." }
|
|
||||||
{ $notes "This operation runs in amortized " { $snippet "O(1)" } " time on " { $link persistent-vector } " instances and " { $snippet "O(n)" } " time on all other sequences." } ;
|
|
||||||
|
|
||||||
HELP: PV{
|
HELP: PV{
|
||||||
{ $syntax "elements... }" }
|
{ $syntax "elements... }" }
|
||||||
{ $description "Parses a literal " { $link persistent-vector } "." } ;
|
{ $description "Parses a literal " { $link persistent-vector } "." } ;
|
|
@ -1,6 +1,7 @@
|
||||||
IN: persistent-vectors.tests
|
IN: persistent-vectors.tests
|
||||||
USING: accessors tools.test persistent-vectors sequences kernel
|
USING: accessors tools.test persistent.vectors
|
||||||
arrays random namespaces vectors math math.order ;
|
persistent.sequences sequences kernel arrays random namespaces
|
||||||
|
vectors math math.order ;
|
||||||
|
|
||||||
\ new-nth must-infer
|
\ new-nth must-infer
|
||||||
\ ppush must-infer
|
\ ppush must-infer
|
|
@ -1,8 +1,9 @@
|
||||||
! Based on Clojure's PersistentVector by Rich Hickey.
|
! Based on Clojure's PersistentVector by Rich Hickey.
|
||||||
|
|
||||||
USING: math accessors kernel sequences.private sequences arrays
|
USING: math accessors kernel sequences.private sequences arrays
|
||||||
combinators combinators.short-circuit parser prettyprint.backend ;
|
combinators combinators.short-circuit parser prettyprint.backend
|
||||||
IN: persistent-vectors
|
persistent.sequences ;
|
||||||
|
IN: persistent.vectors
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
|
@ -12,18 +13,6 @@ PRIVATE>
|
||||||
|
|
||||||
ERROR: empty-error pvec ;
|
ERROR: empty-error pvec ;
|
||||||
|
|
||||||
GENERIC: ppush ( val seq -- seq' )
|
|
||||||
|
|
||||||
M: sequence ppush swap suffix ;
|
|
||||||
|
|
||||||
GENERIC: ppop ( seq -- seq' )
|
|
||||||
|
|
||||||
M: sequence ppop 1 head* ;
|
|
||||||
|
|
||||||
GENERIC: new-nth ( val i seq -- seq' )
|
|
||||||
|
|
||||||
M: sequence new-nth clone [ set-nth ] keep ;
|
|
||||||
|
|
||||||
TUPLE: persistent-vector
|
TUPLE: persistent-vector
|
||||||
{ count fixnum }
|
{ count fixnum }
|
||||||
{ root node initial: T{ node f { } 1 } }
|
{ root node initial: T{ node f { } 1 } }
|
|
@ -212,7 +212,7 @@ HELP: bit?
|
||||||
|
|
||||||
HELP: log2
|
HELP: log2
|
||||||
{ $values { "x" "a positive integer" } { "n" integer } }
|
{ $values { "x" "a positive integer" } { "n" integer } }
|
||||||
{ $description "Outputs the largest integer " { $snippet "n" } " such that " { $snippet "2^n" } " is less than " { $snippet "x" } "." }
|
{ $description "Outputs the largest integer " { $snippet "n" } " such that " { $snippet "2^n" } " is less than or equal to " { $snippet "x" } "." }
|
||||||
{ $errors "Throws an error if " { $snippet "x" } " is zero or negative." } ;
|
{ $errors "Throws an error if " { $snippet "x" } " is zero or negative." } ;
|
||||||
|
|
||||||
HELP: 1+
|
HELP: 1+
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
USING: help.markup help.syntax ;
|
||||||
|
IN: extra.animations
|
||||||
|
|
||||||
|
HELP: animate ( quot duration -- )
|
||||||
|
{ $values
|
||||||
|
{ "quot" "a quot which uses " { $link progress } }
|
||||||
|
{ "duration" "a duration of time" }
|
||||||
|
}
|
||||||
|
{ $description { $link animate } " calls " { $link reset-progress } " , then continously calls the given quot until the duration of time has elapsed. The quot should use " { $link progress } " at least once." }
|
||||||
|
{ $example
|
||||||
|
"USING: extra.animations calendar threads prettyprint ;"
|
||||||
|
"[ 1 sleep progress unparse write \" ms elapsed\" print ] 1/20 seconds animate ;"
|
||||||
|
"46 ms elapsed\n17 ms elapsed"
|
||||||
|
} ;
|
||||||
|
|
||||||
|
HELP: reset-progress ( -- )
|
||||||
|
{ $description "Initiates the timer. Call this before using a loop which makes use of " { $link progress } "." } ;
|
||||||
|
|
||||||
|
HELP: progress ( -- time )
|
||||||
|
{ $values { "time" "an integer" } }
|
||||||
|
{ $description "Gives the time elapsed since the last time this word was called, in milliseconds." }
|
||||||
|
{ $example
|
||||||
|
"USING: extra.animations threads prettyprint ;"
|
||||||
|
"reset-progress 3 [ 1 sleep progress unparse write \"ms elapsed\" print ] times ;"
|
||||||
|
"31 ms elapsed\n18 ms elapsed\n16 ms elapsed"
|
||||||
|
} ;
|
||||||
|
|
||||||
|
ARTICLE: "extra.animations" "Animations"
|
||||||
|
"Provides a lightweight framework for properly simulating continuous functions of real time. This framework helps one create animations that use rates which do not change across platforms. The speed of the computer should correlate with the smoothness of the animation, not the speed of the animation!"
|
||||||
|
{ $subsection animate }
|
||||||
|
{ $subsection reset-progress }
|
||||||
|
{ $subsection progress }
|
||||||
|
{ $link progress } " specifically provides the length of time since " { $link reset-progress } " was called, and also calls " { $link reset-progress } " as its last action. This can be directly used when one's quote runs for a specific number of iterations, instead of a length of time. If the animation is like most, and is expected to run for a specific length of time, " { $link animate } " should be used." ;
|
||||||
|
ABOUT: "extra.animations"
|
|
@ -0,0 +1,12 @@
|
||||||
|
! Small library for cross-platform continuous functions of real time
|
||||||
|
|
||||||
|
USING: kernel shuffle system locals
|
||||||
|
prettyprint math io namespaces threads calendar ;
|
||||||
|
IN: extra.animations
|
||||||
|
|
||||||
|
SYMBOL: last-loop
|
||||||
|
: reset-progress ( -- ) millis last-loop set ;
|
||||||
|
: progress ( -- progress ) millis last-loop get - reset-progress ;
|
||||||
|
: set-end ( duration -- end-time ) dt>milliseconds millis + ;
|
||||||
|
: loop ( quot end -- ) dup millis > [ [ dup call ] dip loop ] [ 2drop ] if ;
|
||||||
|
: animate ( quot duration -- ) reset-progress set-end loop ;
|
|
@ -0,0 +1 @@
|
||||||
|
Reginald Keith Ford II
|
|
@ -4,12 +4,16 @@
|
||||||
! Simple CSV Parser
|
! Simple CSV Parser
|
||||||
! Phil Dawes phil@phildawes.net
|
! Phil Dawes phil@phildawes.net
|
||||||
|
|
||||||
USING: kernel sequences io namespaces combinators unicode.categories vars ;
|
USING: kernel sequences io namespaces combinators unicode.categories ;
|
||||||
IN: csv
|
IN: csv
|
||||||
|
|
||||||
DEFER: quoted-field
|
SYMBOL: delimiter
|
||||||
|
|
||||||
VAR: delimiter
|
CHAR: , delimiter set-global
|
||||||
|
|
||||||
|
: delimiter> delimiter get ; inline
|
||||||
|
|
||||||
|
DEFER: quoted-field ( -- endchar )
|
||||||
|
|
||||||
! trims whitespace from either end of string
|
! trims whitespace from either end of string
|
||||||
: trim-whitespace ( str -- str )
|
: trim-whitespace ( str -- str )
|
||||||
|
@ -44,7 +48,7 @@ VAR: delimiter
|
||||||
|
|
||||||
: (row) ( -- sep )
|
: (row) ( -- sep )
|
||||||
field ,
|
field ,
|
||||||
dup delimiter> = [ drop (row) ] when ;
|
dup delimiter get = [ drop (row) ] when ;
|
||||||
|
|
||||||
: row ( -- eof? array[string] )
|
: row ( -- eof? array[string] )
|
||||||
[ (row) ] { } make ;
|
[ (row) ] { } make ;
|
||||||
|
@ -55,25 +59,18 @@ VAR: delimiter
|
||||||
: (csv) ( -- )
|
: (csv) ( -- )
|
||||||
row append-if-row-not-empty
|
row append-if-row-not-empty
|
||||||
[ (csv) ] when ;
|
[ (csv) ] when ;
|
||||||
|
|
||||||
: init-vars ( -- )
|
|
||||||
delimiter> [ CHAR: , >delimiter ] unless ; inline
|
|
||||||
|
|
||||||
: csv-row ( stream -- row )
|
: csv-row ( stream -- row )
|
||||||
init-vars
|
|
||||||
[ row nip ] with-input-stream ;
|
[ row nip ] with-input-stream ;
|
||||||
|
|
||||||
: csv ( stream -- rows )
|
: csv ( stream -- rows )
|
||||||
init-vars
|
|
||||||
[ [ (csv) ] { } make ] with-input-stream ;
|
[ [ (csv) ] { } make ] with-input-stream ;
|
||||||
|
|
||||||
: with-delimiter ( char quot -- )
|
: with-delimiter ( char quot -- )
|
||||||
delimiter swap with-variable ; inline
|
delimiter swap with-variable ; inline
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
: needs-escaping? ( cell -- ? )
|
: needs-escaping? ( cell -- ? )
|
||||||
[ "\n\"" delimiter> suffix member? ] contains? ; inline ! "
|
[ [ "\n\"" member? ] [ delimiter get = ] bi or ] contains? ; inline ! "
|
||||||
|
|
||||||
: escape-quotes ( cell -- cell' )
|
: escape-quotes ( cell -- cell' )
|
||||||
[ [ dup , CHAR: " = [ CHAR: " , ] when ] each ] "" make ; inline
|
[ [ dup , CHAR: " = [ CHAR: " , ] when ] each ] "" make ; inline
|
||||||
|
@ -85,8 +82,7 @@ VAR: delimiter
|
||||||
dup needs-escaping? [ escape-quotes enclose-in-quotes ] when ; inline
|
dup needs-escaping? [ escape-quotes enclose-in-quotes ] when ; inline
|
||||||
|
|
||||||
: write-row ( row -- )
|
: write-row ( row -- )
|
||||||
[ delimiter> write1 ] [ escape-if-required write ] interleave nl ; inline
|
[ delimiter get write1 ] [ escape-if-required write ] interleave nl ; inline
|
||||||
|
|
||||||
: write-csv ( rows outstream -- )
|
: write-csv ( rows outstream -- )
|
||||||
init-vars
|
|
||||||
[ [ write-row ] each ] with-output-stream ;
|
[ [ write-row ] each ] with-output-stream ;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: kernel math math.functions quotations words sequences
|
||||||
|
sequences.private combinators fry ;
|
||||||
|
IN: math.bit-count
|
||||||
|
|
||||||
|
<PRIVATE
|
||||||
|
|
||||||
|
DEFER: byte-bit-count
|
||||||
|
|
||||||
|
<<
|
||||||
|
|
||||||
|
\ byte-bit-count
|
||||||
|
256 [
|
||||||
|
0 swap [ [ 1+ ] when ] each-bit
|
||||||
|
] B{ } map-as '[ HEX: ff bitand , nth-unsafe ] define-inline
|
||||||
|
|
||||||
|
>>
|
||||||
|
|
||||||
|
GENERIC: (bit-count) ( x -- n )
|
||||||
|
|
||||||
|
M: fixnum (bit-count)
|
||||||
|
{
|
||||||
|
[ byte-bit-count ]
|
||||||
|
[ -8 shift byte-bit-count ]
|
||||||
|
[ -16 shift byte-bit-count ]
|
||||||
|
[ -24 shift byte-bit-count ]
|
||||||
|
} cleave + + + ;
|
||||||
|
|
||||||
|
M: bignum (bit-count)
|
||||||
|
dup 0 = [ drop 0 ] [
|
||||||
|
[ byte-bit-count ] [ -8 shift (bit-count) ] bi +
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
PRIVATE>
|
||||||
|
|
||||||
|
: bit-count ( x -- n )
|
||||||
|
dup 0 >= [ (bit-count) ] [ bitnot (bit-count) ] if ; inline
|
|
@ -3,7 +3,8 @@
|
||||||
USING: kernel math math.points math.function-tools ;
|
USING: kernel math math.points math.function-tools ;
|
||||||
IN: math.derivatives
|
IN: math.derivatives
|
||||||
|
|
||||||
: small-amount ( -- n ) 1.0e-12 ;
|
: small-amount ( -- n ) 1.0e-14 ;
|
||||||
: near ( x -- y ) small-amount + ;
|
: some-more ( x -- y ) small-amount + ;
|
||||||
: derivative ( x function -- m ) 2dup [ near ] dip [ eval ] 2bi@ slope ;
|
: some-less ( x -- y ) small-amount - ;
|
||||||
|
: derivative ( x function -- m ) [ [ some-more ] dip eval ] [ [ some-less ] dip eval ] 2bi slope ;
|
||||||
: derivative-func ( function -- function ) [ derivative ] curry ;
|
: derivative-func ( function -- function ) [ derivative ] curry ;
|
|
@ -1,8 +1,9 @@
|
||||||
! Copyright © 2008 Reginald Keith Ford II
|
! Copyright © 2008 Reginald Keith Ford II
|
||||||
! Tools for quickly comparing, transforming, and evaluating mathematical Factor functions
|
! Tools for quickly comparing, transforming, and evaluating mathematical Factor functions
|
||||||
|
|
||||||
USING: kernel math arrays ;
|
USING: kernel math arrays sequences sequences.lib ;
|
||||||
IN: math.function-tools
|
IN: math.function-tools
|
||||||
: difference-func ( func func -- func ) [ bi - ] 2curry ;
|
: difference-func ( func func -- func ) [ bi - ] 2curry ;
|
||||||
: eval ( x func -- pt ) dupd call 2array ;
|
: eval ( x func -- pt ) dupd call 2array ;
|
||||||
|
: eval-inverse ( y func -- pt ) dupd call swap 2array ;
|
||||||
: eval3d ( x y func -- pt ) [ 2dup ] dip call 3array ;
|
: eval3d ( x y func -- pt ) [ 2dup ] dip call 3array ;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright © 2008 Reginald Keith Ford II
|
! Copyright © 2008 Reginald Keith Ford II
|
||||||
! Newton's Method of approximating roots
|
! Newton's Method of approximating roots
|
||||||
|
|
||||||
USING: kernel math math.derivatives ;
|
USING: kernel math math.derivatives ;
|
||||||
|
@ -6,6 +6,6 @@ IN: math.newtons-method
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
: newton-step ( x function -- x2 ) dupd [ call ] [ derivative ] 2bi / - ;
|
: newton-step ( x function -- x2 ) dupd [ call ] [ derivative ] 2bi / - ;
|
||||||
: newton-precision ( -- n ) 7 ;
|
: newton-precision ( -- n ) 13 ;
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
: newton-method ( guess function -- x ) newton-precision [ [ newton-step ] keep ] times drop ;
|
: newtons-method ( guess function -- x ) newton-precision [ [ newton-step ] keep ] times drop ;
|
||||||
|
|
|
@ -7,8 +7,8 @@ IN: math.secant-method
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
: secant-solution ( x1 x2 function -- solution ) [ eval ] curry bi@ linear-solution ;
|
: secant-solution ( x1 x2 function -- solution ) [ eval ] curry bi@ linear-solution ;
|
||||||
: secant-step ( x1 x2 func -- x2 x3 func ) 2dup [ secant-solution ] 2dip swapd ;
|
: secant-step ( x1 x2 func -- x2 x3 func ) 2dup [ secant-solution ] 2dip swapd ;
|
||||||
: secant-precision ( -- n ) 11 ;
|
: secant-precision ( -- n ) 15 ;
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
: secant-method ( left right function -- x ) secant-precision [ secant-step ] times drop v+ 2 v*n ;
|
: secant-method ( left right function -- x ) secant-precision [ secant-step ] times drop + 2 / ;
|
||||||
! : close-enough? ( a b -- t/f ) - abs tiny-amount < ;
|
! : close-enough? ( a b -- t/f ) - abs tiny-amount < ;
|
||||||
! : secant-method2 ( left right function -- x ) 2over close-enough? [ drop average ] [ secant-step secant-method ] if ;
|
! : secant-method2 ( left right function -- x ) 2over close-enough? [ drop average ] [ secant-step secant-method ] if ;
|
|
@ -1 +0,0 @@
|
||||||
Immutable vectors with O(log_32 n) random access and amortized O(1) push/pop
|
|
|
@ -205,8 +205,11 @@ PRIVATE>
|
||||||
: nths ( seq indices -- seq' )
|
: nths ( seq indices -- seq' )
|
||||||
swap [ nth ] curry map ;
|
swap [ nth ] curry map ;
|
||||||
|
|
||||||
: remove-nth ( seq n -- seq' )
|
: remove-nth ( n seq -- seq' )
|
||||||
cut-slice rest-slice append ;
|
[ swap head-slice ] [ swap 1+ tail-slice ] 2bi append ;
|
||||||
|
|
||||||
|
: insert-nth ( elt n seq -- seq' )
|
||||||
|
swap cut-slice [ swap 1array ] dip 3append ;
|
||||||
|
|
||||||
: if-seq ( seq quot1 quot2 -- )
|
: if-seq ( seq quot1 quot2 -- )
|
||||||
[ f like ] 2dip if* ; inline
|
[ f like ] 2dip if* ; inline
|
||||||
|
|
|
@ -34,8 +34,13 @@ HELP: profile-vocab
|
||||||
{ $description "Annotates the words in the vocab with timing code then runs the quotation. Finally resets the words and prints the timings information."
|
{ $description "Annotates the words in the vocab with timing code then runs the quotation. Finally resets the words and prints the timings information."
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
HELP: wordtimer-call
|
||||||
|
{ $values { "quot" "a quotation to run" } }
|
||||||
|
{ $description "Resets the wordtimer hash and runs the quotation. After the quotation has run it prints out the timed words"
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
ARTICLE: "wordtimer" "Word Timer"
|
ARTICLE: "wordtimer" "Word Timer"
|
||||||
"The " { $vocab-link "wordtimer" } " vocabulary measures accumulated execution time for words. If you just want to profile the accumulated time taken by all words in a vocab you can use " { $vocab-link "profile-vocab" } ". If you need more fine grained control then do the following: First annotate individual words with the " { $link add-timer } " word or whole vocabularies with " { $link add-timers } ". Then reset the clock with " { $link reset-word-timer } " and execute your code. Finally you can view the timings with " { $link print-word-timings } ". If you have functions that are quick and called often you may want to " { $link correct-for-timing-overhead } ". To remove all the annotations in the vocab you can use " { $link reset-vocab } ". Alternatively if you just want to time the contents of a vocabulary you can use profile-vocab." ;
|
"The " { $vocab-link "wordtimer" } " vocabulary measures accumulated execution time for words. If you just want to profile the accumulated time taken by all words in a vocab you can use " { $vocab-link "profile-vocab" } ". If you need more fine grained control then do the following: First annotate individual words with the " { $link add-timer } " word or whole vocabularies with " { $link add-timers } ". Then use " { $link wordtimer-call } " to invoke a quotation and print out the timings." ;
|
||||||
|
|
||||||
ABOUT: "wordtimer"
|
ABOUT: "wordtimer"
|
||||||
|
|
|
@ -67,6 +67,12 @@ SYMBOL: *calling*
|
||||||
: print-word-timings ( -- )
|
: print-word-timings ( -- )
|
||||||
*wordtimes* get-global [ swap suffix ] { } assoc>map natural-sort reverse pprint ;
|
*wordtimes* get-global [ swap suffix ] { } assoc>map natural-sort reverse pprint ;
|
||||||
|
|
||||||
|
: wordtimer-call ( quot -- )
|
||||||
|
reset-word-timer
|
||||||
|
[ call ] micro-time >r
|
||||||
|
correct-for-timing-overhead
|
||||||
|
"total time:" write r> pprint nl
|
||||||
|
print-word-timings nl ;
|
||||||
|
|
||||||
: profile-vocab ( vocabspec quot -- )
|
: profile-vocab ( vocabspec quot -- )
|
||||||
"annotating vocab..." print flush
|
"annotating vocab..." print flush
|
||||||
|
|
|
@ -536,3 +536,15 @@ M: array iterate first t ;
|
||||||
[ V{ f } ] [
|
[ V{ f } ] [
|
||||||
[ 10 eq? [ drop 3 ] unless ] final-literals
|
[ 10 eq? [ drop 3 ] unless ] final-literals
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
GENERIC: bad-generic ( a -- b )
|
||||||
|
M: fixnum bad-generic 1 fixnum+fast ;
|
||||||
|
: bad-behavior 4 bad-generic ; inline recursive
|
||||||
|
|
||||||
|
[ V{ fixnum } ] [ [ bad-behavior ] final-classes ] unit-test
|
||||||
|
|
||||||
|
[ V{ number } ] [
|
||||||
|
[
|
||||||
|
0 10 [ bad-generic dup 123 bitand drop bad-generic 1 + ] times
|
||||||
|
] final-classes
|
||||||
|
] unit-test
|
||||||
|
|
Loading…
Reference in New Issue