Merge branch 'master' of git://factorcode.org/git/factor

db4
Slava Pestov 2009-05-18 16:50:21 -05:00
commit 3eb058aa70
11 changed files with 174 additions and 129 deletions

View File

@ -4,7 +4,8 @@ USING: kernel io io.binary io.files io.streams.byte-array math
math.functions math.parser namespaces splitting grouping strings math.functions math.parser namespaces splitting grouping strings
sequences byte-arrays locals sequences.private macros fry sequences byte-arrays locals sequences.private macros fry
io.encodings.binary math.bitwise checksums accessors io.encodings.binary math.bitwise checksums accessors
checksums.common checksums.stream combinators combinators.smart ; checksums.common checksums.stream combinators combinators.smart
specialized-arrays.uint literals ;
IN: checksums.md5 IN: checksums.md5
SINGLETON: md5 SINGLETON: md5
@ -16,7 +17,7 @@ TUPLE: md5-state < checksum-state state old-state ;
: <md5-state> ( -- md5 ) : <md5-state> ( -- md5 )
md5-state new-checksum-state md5-state new-checksum-state
64 >>block-size 64 >>block-size
{ HEX: 67452301 HEX: efcdab89 HEX: 98badcfe HEX: 10325476 } uint-array{ HEX: 67452301 HEX: efcdab89 HEX: 98badcfe HEX: 10325476 }
[ clone >>state ] [ >>old-state ] bi ; [ clone >>state ] [ >>old-state ] bi ;
M: md5 initialize-checksum-state drop <md5-state> ; M: md5 initialize-checksum-state drop <md5-state> ;
@ -29,8 +30,10 @@ M: md5 initialize-checksum-state drop <md5-state> ;
[ state>> ] [ old-state>> v-w+ dup clone ] [ ] tri [ state>> ] [ old-state>> v-w+ dup clone ] [ ] tri
[ (>>old-state) ] [ (>>state) ] bi ; inline [ (>>old-state) ] [ (>>state) ] bi ; inline
: T ( N -- Y ) CONSTANT: T
sin abs 32 2^ * >integer ; inline $[
80 iota [ sin abs 32 2^ * >integer ] uint-array{ } map-as
]
:: F ( X Y Z -- FXYZ ) :: F ( X Y Z -- FXYZ )
#! F(X,Y,Z) = XY v not(X) Z #! F(X,Y,Z) = XY v not(X) Z
@ -70,22 +73,22 @@ CONSTANT: b 1
CONSTANT: c 2 CONSTANT: c 2
CONSTANT: d 3 CONSTANT: d 3
:: (ABCD) ( x V a b c d k s i quot -- ) :: (ABCD) ( x state a b c d k s i quot -- )
#! a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) #! a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
a V [ a state [
b V nth b state nth-unsafe
c V nth c state nth-unsafe
d V nth quot call w+ d state nth-unsafe quot call w+
k x nth w+ k x nth-unsafe w+
i T w+ i T nth-unsafe w+
s bitroll-32 s bitroll-32
b V nth w+ b state nth-unsafe w+ 32 bits
] change-nth ; inline ] change-nth-unsafe ; inline
MACRO: with-md5-round ( ops quot -- ) MACRO: with-md5-round ( ops quot -- )
'[ [ _ (ABCD) ] compose ] map '[ _ 2cleave ] ; '[ [ _ (ABCD) ] compose ] map '[ _ 2cleave ] ;
: (process-md5-block-F) ( block v -- ) : (process-md5-block-F) ( block state -- )
{ {
[ a b c d 0 S11 1 ] [ a b c d 0 S11 1 ]
[ d a b c 1 S12 2 ] [ d a b c 1 S12 2 ]
@ -105,7 +108,7 @@ MACRO: with-md5-round ( ops quot -- )
[ b c d a 15 S14 16 ] [ b c d a 15 S14 16 ]
} [ F ] with-md5-round ; inline } [ F ] with-md5-round ; inline
: (process-md5-block-G) ( block v -- ) : (process-md5-block-G) ( block state -- )
{ {
[ a b c d 1 S21 17 ] [ a b c d 1 S21 17 ]
[ d a b c 6 S22 18 ] [ d a b c 6 S22 18 ]
@ -125,7 +128,7 @@ MACRO: with-md5-round ( ops quot -- )
[ b c d a 12 S24 32 ] [ b c d a 12 S24 32 ]
} [ G ] with-md5-round ; inline } [ G ] with-md5-round ; inline
: (process-md5-block-H) ( block v -- ) : (process-md5-block-H) ( block state -- )
{ {
[ a b c d 5 S31 33 ] [ a b c d 5 S31 33 ]
[ d a b c 8 S32 34 ] [ d a b c 8 S32 34 ]
@ -145,7 +148,7 @@ MACRO: with-md5-round ( ops quot -- )
[ b c d a 2 S34 48 ] [ b c d a 2 S34 48 ]
} [ H ] with-md5-round ; inline } [ H ] with-md5-round ; inline
: (process-md5-block-I) ( block v -- ) : (process-md5-block-I) ( block state -- )
{ {
[ a b c d 0 S41 49 ] [ a b c d 0 S41 49 ]
[ d a b c 7 S42 50 ] [ d a b c 7 S42 50 ]
@ -167,7 +170,7 @@ MACRO: with-md5-round ( ops quot -- )
M: md5-state checksum-block ( block state -- ) M: md5-state checksum-block ( block state -- )
[ [
[ 4 <groups> [ le> ] map ] [ state>> ] bi* { [ byte-array>uint-array ] [ state>> ] bi* {
[ (process-md5-block-F) ] [ (process-md5-block-F) ]
[ (process-md5-block-G) ] [ (process-md5-block-G) ]
[ (process-md5-block-H) ] [ (process-md5-block-H) ]
@ -177,8 +180,7 @@ M: md5-state checksum-block ( block state -- )
nip update-md5 nip update-md5
] 2bi ; ] 2bi ;
: md5>checksum ( md5 -- bytes ) : md5>checksum ( md5 -- bytes ) state>> underlying>> ;
state>> [ 4 >le ] map B{ } concat-as ;
M: md5-state clone ( md5 -- new-md5 ) M: md5-state clone ( md5 -- new-md5 )
call-next-method call-next-method

View File

@ -33,7 +33,7 @@ ARTICLE: { "lists.lazy" "construction" } "Constructing lazy lists"
{ $subsection 1lazy-list } { $subsection 1lazy-list }
{ $subsection 2lazy-list } { $subsection 2lazy-list }
{ $subsection 3lazy-list } { $subsection 3lazy-list }
{ $subsection seq>list } { $subsection sequence-tail>list }
{ $subsection >list } { $subsection >list }
{ $subsection lfrom } ; { $subsection lfrom } ;
@ -105,15 +105,15 @@ HELP: lfrom
{ $values { "n" "an integer" } { "list" "a lazy list of integers" } } { $values { "n" "an integer" } { "list" "a lazy list of integers" } }
{ $description "Return an infinite lazy list of incrementing integers starting from n." } ; { $description "Return an infinite lazy list of incrementing integers starting from n." } ;
HELP: seq>list HELP: sequence-tail>list
{ $values { "index" "an integer 0 or greater" } { "seq" "a sequence" } { "list" "a list" } } { $values { "index" "an integer 0 or greater" } { "seq" "a sequence" } { "list" "a list" } }
{ $description "Convert the sequence into a list, starting from " { $snippet "index" } "." } { $description "Convert the sequence into a list, starting from " { $snippet "index" } "." }
{ $see-also >list } ; { $see-also >list } ;
HELP: >list HELP: >list
{ $values { "object" "an object" } { "list" "a list" } } { $values { "object" "an object" } { "list" "a list" } }
{ $description "Convert the object into a list. Existing lists are passed through intact, sequences are converted using " { $link seq>list } " and other objects cause an error to be thrown." } { $description "Convert the object into a list. Existing lists are passed through intact, sequences are converted using " { $link sequence-tail>list } " and other objects cause an error to be thrown." }
{ $see-also seq>list } ; { $see-also sequence-tail>list } ;
{ leach foldl lazy-map ltake lfilter lappend lfrom lfrom-by lconcat lcartesian-product lcartesian-product* lcomp lcomp* lmerge lwhile luntil } related-words { leach foldl lazy-map ltake lfilter lappend lfrom lfrom-by lconcat lcartesian-product lcartesian-product* lcomp lcomp* lmerge lwhile luntil } related-words

View File

@ -1,6 +1,7 @@
! Copyright (C) 2006 Matthew Willis and Chris Double. ! Copyright (C) 2006 Matthew Willis and Chris Double.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: lists lists.lazy tools.test kernel math io sequences ; USING: io io.encodings.utf8 io.files kernel lists lists.lazy
math sequences tools.test ;
IN: lists.lazy.tests IN: lists.lazy.tests
[ { 1 2 3 4 } ] [ [ { 1 2 3 4 } ] [
@ -33,3 +34,6 @@ IN: lists.lazy.tests
[ [ drop ] foldl ] must-infer [ [ drop ] foldl ] must-infer
[ [ drop ] leach ] must-infer [ [ drop ] leach ] must-infer
[ lnth ] must-infer [ lnth ] must-infer
[ ] [ "resource:license.txt" utf8 <file-reader> llines list>array drop ] unit-test
[ ] [ "resource:license.txt" utf8 <file-reader> lcontents list>array drop ] unit-test

View File

@ -1,7 +1,7 @@
! Copyright (C) 2004, 2008 Chris Double, Matthew Willis, James Cash. ! Copyright (C) 2004, 2008 Chris Double, Matthew Willis, James Cash.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences math vectors arrays namespaces make USING: accessors arrays combinators io kernel lists math
quotations promises combinators io lists accessors ; promises quotations sequences summary vectors ;
IN: lists.lazy IN: lists.lazy
M: promise car ( promise -- car ) M: promise car ( promise -- car )
@ -10,16 +10,16 @@ M: promise car ( promise -- car )
M: promise cdr ( promise -- cdr ) M: promise cdr ( promise -- cdr )
force cdr ; force cdr ;
M: promise nil? ( cons -- bool ) M: promise nil? ( cons -- ? )
force nil? ; force nil? ;
! Both 'car' and 'cdr' are promises ! Both 'car' and 'cdr' are promises
TUPLE: lazy-cons car cdr ; TUPLE: lazy-cons car cdr ;
: lazy-cons ( car cdr -- promise ) : lazy-cons ( car cdr -- promise )
[ T{ promise f f t f } clone ] 2dip
[ promise ] bi@ \ lazy-cons boa [ promise ] bi@ \ lazy-cons boa
T{ promise f f t f } clone >>value ;
swap >>value ;
M: lazy-cons car ( lazy-cons -- car ) M: lazy-cons car ( lazy-cons -- car )
car>> force ; car>> force ;
@ -27,7 +27,7 @@ M: lazy-cons car ( lazy-cons -- car )
M: lazy-cons cdr ( lazy-cons -- cdr ) M: lazy-cons cdr ( lazy-cons -- cdr )
cdr>> force ; cdr>> force ;
M: lazy-cons nil? ( lazy-cons -- bool ) M: lazy-cons nil? ( lazy-cons -- ? )
nil eq? ; nil eq? ;
: 1lazy-list ( a -- lazy-cons ) : 1lazy-list ( a -- lazy-cons )
@ -41,11 +41,9 @@ M: lazy-cons nil? ( lazy-cons -- bool )
TUPLE: memoized-cons original car cdr nil? ; TUPLE: memoized-cons original car cdr nil? ;
: not-memoized ( -- obj ) : not-memoized ( -- obj ) { } ;
{ } ;
: not-memoized? ( obj -- bool ) : not-memoized? ( obj -- ? ) not-memoized eq? ;
not-memoized eq? ;
: <memoized-cons> ( cons -- memoized-cons ) : <memoized-cons> ( cons -- memoized-cons )
not-memoized not-memoized not-memoized not-memoized not-memoized not-memoized
@ -65,7 +63,7 @@ M: memoized-cons cdr ( memoized-cons -- cdr )
cdr>> cdr>>
] if ; ] if ;
M: memoized-cons nil? ( memoized-cons -- bool ) M: memoized-cons nil? ( memoized-cons -- ? )
dup nil?>> not-memoized? [ dup nil?>> not-memoized? [
dup original>> nil? [ >>nil? drop ] keep dup original>> nil? [ >>nil? drop ] keep
] [ ] [
@ -80,14 +78,12 @@ C: <lazy-map> lazy-map
over nil? [ 2drop nil ] [ <lazy-map> <memoized-cons> ] if ; over nil? [ 2drop nil ] [ <lazy-map> <memoized-cons> ] if ;
M: lazy-map car ( lazy-map -- car ) M: lazy-map car ( lazy-map -- car )
[ cons>> car ] keep [ cons>> car ] [ quot>> call( old -- new ) ] bi ;
quot>> call( old -- new ) ;
M: lazy-map cdr ( lazy-map -- cdr ) M: lazy-map cdr ( lazy-map -- cdr )
[ cons>> cdr ] keep [ cons>> cdr ] [ quot>> lazy-map ] bi ;
quot>> lazy-map ;
M: lazy-map nil? ( lazy-map -- bool ) M: lazy-map nil? ( lazy-map -- ? )
cons>> nil? ; cons>> nil? ;
TUPLE: lazy-take n cons ; TUPLE: lazy-take n cons ;
@ -104,12 +100,8 @@ M: lazy-take cdr ( lazy-take -- cdr )
[ n>> 1- ] keep [ n>> 1- ] keep
cons>> cdr ltake ; cons>> cdr ltake ;
M: lazy-take nil? ( lazy-take -- bool ) M: lazy-take nil? ( lazy-take -- ? )
dup n>> zero? [ dup n>> zero? [ drop t ] [ cons>> nil? ] if ;
drop t
] [
cons>> nil?
] if ;
TUPLE: lazy-until cons quot ; TUPLE: lazy-until cons quot ;
@ -125,7 +117,7 @@ M: lazy-until cdr ( lazy-until -- cdr )
[ cons>> unswons ] keep quot>> tuck call( elt -- ? ) [ cons>> unswons ] keep quot>> tuck call( elt -- ? )
[ 2drop nil ] [ luntil ] if ; [ 2drop nil ] [ luntil ] if ;
M: lazy-until nil? ( lazy-until -- bool ) M: lazy-until nil? ( lazy-until -- ? )
drop f ; drop f ;
TUPLE: lazy-while cons quot ; TUPLE: lazy-while cons quot ;
@ -141,7 +133,7 @@ M: lazy-while car ( lazy-while -- car )
M: lazy-while cdr ( lazy-while -- cdr ) M: lazy-while cdr ( lazy-while -- cdr )
[ cons>> cdr ] keep quot>> lwhile ; [ cons>> cdr ] keep quot>> lwhile ;
M: lazy-while nil? ( lazy-while -- bool ) M: lazy-while nil? ( lazy-while -- ? )
[ car ] keep quot>> call( elt -- ? ) not ; [ car ] keep quot>> call( elt -- ? ) not ;
TUPLE: lazy-filter cons quot ; TUPLE: lazy-filter cons quot ;
@ -167,7 +159,7 @@ M: lazy-filter cdr ( lazy-filter -- cdr )
dup skip cdr dup skip cdr
] if ; ] if ;
M: lazy-filter nil? ( lazy-filter -- bool ) M: lazy-filter nil? ( lazy-filter -- ? )
dup cons>> nil? [ dup cons>> nil? [
drop t drop t
] [ ] [
@ -189,10 +181,9 @@ M: lazy-append car ( lazy-append -- car )
list1>> car ; list1>> car ;
M: lazy-append cdr ( lazy-append -- cdr ) M: lazy-append cdr ( lazy-append -- cdr )
[ list1>> cdr ] keep [ list1>> cdr ] [ list2>> ] bi lappend ;
list2>> lappend ;
M: lazy-append nil? ( lazy-append -- bool ) M: lazy-append nil? ( lazy-append -- ? )
drop f ; drop f ;
TUPLE: lazy-from-by n quot ; TUPLE: lazy-from-by n quot ;
@ -209,7 +200,7 @@ M: lazy-from-by cdr ( lazy-from-by -- cdr )
[ n>> ] keep [ n>> ] keep
quot>> [ call( old -- new ) ] keep lfrom-by ; quot>> [ call( old -- new ) ] keep lfrom-by ;
M: lazy-from-by nil? ( lazy-from-by -- bool ) M: lazy-from-by nil? ( lazy-from-by -- ? )
drop f ; drop f ;
TUPLE: lazy-zip list1 list2 ; TUPLE: lazy-zip list1 list2 ;
@ -226,14 +217,14 @@ M: lazy-zip car ( lazy-zip -- car )
M: lazy-zip cdr ( lazy-zip -- cdr ) M: lazy-zip cdr ( lazy-zip -- cdr )
[ list1>> cdr ] keep list2>> cdr lzip ; [ list1>> cdr ] keep list2>> cdr lzip ;
M: lazy-zip nil? ( lazy-zip -- bool ) M: lazy-zip nil? ( lazy-zip -- ? )
drop f ; drop f ;
TUPLE: sequence-cons index seq ; TUPLE: sequence-cons index seq ;
C: <sequence-cons> sequence-cons C: <sequence-cons> sequence-cons
: seq>list ( index seq -- list ) : sequence-tail>list ( index seq -- list )
2dup length >= [ 2dup length >= [
2drop nil 2drop nil
] [ ] [
@ -241,21 +232,24 @@ C: <sequence-cons> sequence-cons
] if ; ] if ;
M: sequence-cons car ( sequence-cons -- car ) M: sequence-cons car ( sequence-cons -- car )
[ index>> ] keep [ index>> ] [ seq>> nth ] bi ;
seq>> nth ;
M: sequence-cons cdr ( sequence-cons -- cdr ) M: sequence-cons cdr ( sequence-cons -- cdr )
[ index>> 1+ ] keep [ index>> 1+ ] [ seq>> sequence-tail>list ] bi ;
seq>> seq>list ;
M: sequence-cons nil? ( sequence-cons -- bool ) M: sequence-cons nil? ( sequence-cons -- ? )
drop f ; drop f ;
ERROR: list-conversion-error object ;
M: list-conversion-error summary
drop "Could not convert object to list" ;
: >list ( object -- list ) : >list ( object -- list )
{ {
{ [ dup sequence? ] [ 0 swap seq>list ] } { [ dup sequence? ] [ 0 swap sequence-tail>list ] }
{ [ dup list? ] [ ] } { [ dup list? ] [ ] }
[ "Could not convert object to a list" throw ] [ list-conversion-error ]
} cond ; } cond ;
TUPLE: lazy-concat car cdr ; TUPLE: lazy-concat car cdr ;
@ -265,18 +259,10 @@ C: <lazy-concat> lazy-concat
DEFER: lconcat DEFER: lconcat
: (lconcat) ( car cdr -- list ) : (lconcat) ( car cdr -- list )
over nil? [ over nil? [ nip lconcat ] [ <lazy-concat> ] if ;
nip lconcat
] [
<lazy-concat>
] if ;
: lconcat ( list -- result ) : lconcat ( list -- result )
dup nil? [ dup nil? [ drop nil ] [ uncons (lconcat) ] if ;
drop nil
] [
uncons (lconcat)
] if ;
M: lazy-concat car ( lazy-concat -- car ) M: lazy-concat car ( lazy-concat -- car )
car>> car ; car>> car ;
@ -284,12 +270,8 @@ M: lazy-concat car ( lazy-concat -- car )
M: lazy-concat cdr ( lazy-concat -- cdr ) M: lazy-concat cdr ( lazy-concat -- cdr )
[ car>> cdr ] keep cdr>> (lconcat) ; [ car>> cdr ] keep cdr>> (lconcat) ;
M: lazy-concat nil? ( lazy-concat -- bool ) M: lazy-concat nil? ( lazy-concat -- ? )
dup car>> nil? [ dup car>> nil? [ cdr>> nil? ] [ drop f ] if ;
cdr>> nil?
] [
drop f
] if ;
: lcartesian-product ( list1 list2 -- result ) : lcartesian-product ( list1 list2 -- result )
swap [ swap [ 2array ] with lazy-map ] with lazy-map lconcat ; swap [ swap [ 2array ] with lazy-map ] with lazy-map lconcat ;
@ -298,7 +280,9 @@ M: lazy-concat nil? ( lazy-concat -- bool )
dup nil? [ dup nil? [
drop nil drop nil
] [ ] [
[ car ] keep cdr [ car lcartesian-product ] keep cdr list>array swap [ [ car ] [ cdr ] bi
[ car lcartesian-product ] [ cdr ] bi
list>array swap [
swap [ swap [ suffix ] with lazy-map ] with lazy-map lconcat swap [ swap [ suffix ] with lazy-map ] with lazy-map lconcat
] reduce ] reduce
] if ; ] if ;
@ -338,30 +322,29 @@ C: <lazy-io> lazy-io
f f [ stream-readln ] <lazy-io> ; f f [ stream-readln ] <lazy-io> ;
M: lazy-io car ( lazy-io -- car ) M: lazy-io car ( lazy-io -- car )
dup car>> dup [ dup car>> [
nip nip
] [ ] [
drop dup stream>> over quot>> [ ] [ stream>> ] [ quot>> ] tri
call( stream -- value ) call( stream -- value ) [ >>car ] [ drop nil ] if*
>>car ] if* ;
] if ;
M: lazy-io cdr ( lazy-io -- cdr ) M: lazy-io cdr ( lazy-io -- cdr )
dup cdr>> dup [ dup cdr>> dup [
nip nip
] [ ] [
drop dup drop dup
[ stream>> ] keep [ stream>> ]
[ quot>> ] keep [ quot>> ]
car [ [ car ] tri [
[ f f ] dip <lazy-io> [ >>cdr drop ] keep [ f f ] dip <lazy-io> [ >>cdr drop ] keep
] [ ] [
3drop nil 3drop nil
] if ] if
] if ; ] if ;
M: lazy-io nil? ( lazy-io -- bool ) M: lazy-io nil? ( lazy-io -- ? )
car not ; car nil? ;
INSTANCE: sequence-cons list INSTANCE: sequence-cons list
INSTANCE: memoized-cons list INSTANCE: memoized-cons list

View File

@ -2,26 +2,26 @@ USING: help.markup help.syntax debugger ;
IN: math.statistics IN: math.statistics
HELP: geometric-mean HELP: geometric-mean
{ $values { "seq" "a sequence of numbers" } { "n" "a non-negative real number"} } { $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the geometric mean of all elements in " { $snippet "seq" } ". The geometric mean measures the central tendency of a data set that minimizes the effects of extreme values." } { $description "Computes the geometric mean of all elements in " { $snippet "seq" } ". The geometric mean measures the central tendency of a data set that minimizes the effects of extreme values." }
{ $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } geometric-mean ." "1.81712059283214" } } { $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } geometric-mean ." "1.81712059283214" } }
{ $errors "Throws a " { $link signal-error. } " (square-root of 0) if the sequence is empty." } ; { $errors "Throws a " { $link signal-error. } " (square-root of 0) if the sequence is empty." } ;
HELP: harmonic-mean HELP: harmonic-mean
{ $values { "seq" "a sequence of numbers" } { "n" "a non-negative real number"} } { $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the harmonic mean of the elements in " { $snippet "seq" } ". The harmonic mean is appropriate when the average of rates is desired." } { $description "Computes the harmonic mean of the elements in " { $snippet "seq" } ". The harmonic mean is appropriate when the average of rates is desired." }
{ $notes "Positive reals only." } { $notes "Positive reals only." }
{ $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } harmonic-mean ." "6/11" } } { $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } harmonic-mean ." "6/11" } }
{ $errors "Throws a " { $link signal-error. } " (divide by zero) if the sequence is empty." } ; { $errors "Throws a " { $link signal-error. } " (divide by zero) if the sequence is empty." } ;
HELP: mean HELP: mean
{ $values { "seq" "a sequence of numbers" } { "n" "a non-negative real number"} } { $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the arithmetic mean of all elements in " { $snippet "seq" } "." } { $description "Computes the arithmetic mean of all elements in " { $snippet "seq" } "." }
{ $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } mean ." "2" } } { $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } mean ." "2" } }
{ $errors "Throws a " { $link signal-error. } " (divide by zero) if the sequence is empty." } ; { $errors "Throws a " { $link signal-error. } " (divide by zero) if the sequence is empty." } ;
HELP: median HELP: median
{ $values { "seq" "a sequence of numbers" } { "n" "a non-negative real number"} } { $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the median of " { $snippet "seq" } " by sorting the sequence from lowest value to highest and outputting the middle one. If there is an even number of elements in the sequence, the median is not unique, so the mean of the two middle values is outputted." } { $description "Computes the median of " { $snippet "seq" } " by sorting the sequence from lowest value to highest and outputting the middle one. If there is an even number of elements in the sequence, the median is not unique, so the mean of the two middle values is outputted." }
{ $examples { $examples
{ $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } median ." "2" } { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } median ." "2" }
@ -29,7 +29,7 @@ HELP: median
{ $errors "Throws a " { $link signal-error. } " (divide by zero) if the sequence is empty." } ; { $errors "Throws a " { $link signal-error. } " (divide by zero) if the sequence is empty." } ;
HELP: range HELP: range
{ $values { "seq" "a sequence of numbers" } { "n" "a non-negative real number"} } { $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the distance of the maximum and minimum values in " { $snippet "seq" } "." } { $description "Computes the distance of the maximum and minimum values in " { $snippet "seq" } "." }
{ $examples { $examples
{ $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } range ." "2" } { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } range ." "2" }

View File

@ -13,6 +13,24 @@ IN: math.statistics.tests
[ 2 ] [ { 1 2 3 } median ] unit-test [ 2 ] [ { 1 2 3 } median ] unit-test
[ 5/2 ] [ { 1 2 3 4 } median ] unit-test [ 5/2 ] [ { 1 2 3 4 } median ] unit-test
[ { } median ] must-fail
[ { } upper-median ] must-fail
[ { } lower-median ] must-fail
[ 2 ] [ { 1 2 3 4 } lower-median ] unit-test
[ 3 ] [ { 1 2 3 4 } upper-median ] unit-test
[ 3 ] [ { 1 2 3 4 5 } lower-median ] unit-test
[ 3 ] [ { 1 2 3 4 5 } upper-median ] unit-test
[ 1 ] [ { 1 } lower-median ] unit-test
[ 1 ] [ { 1 } upper-median ] unit-test
[ 1 ] [ { 1 } median ] unit-test
[ 1 ] [ { 1 2 } lower-median ] unit-test
[ 2 ] [ { 1 2 } upper-median ] unit-test
[ 3/2 ] [ { 1 2 } median ] unit-test
[ 1 ] [ { 1 2 3 } var ] unit-test [ 1 ] [ { 1 2 3 } var ] unit-test
[ 1.0 ] [ { 1 2 3 } std ] unit-test [ 1.0 ] [ { 1 2 3 } std ] unit-test
[ t ] [ { 1 2 3 4 } ste 0.6454972243679028 - .0001 < ] unit-test [ t ] [ { 1 2 3 4 } ste 0.6454972243679028 - .0001 < ] unit-test

View File

@ -1,30 +1,66 @@
! Copyright (C) 2008 Doug Coleman, Michael Judge. ! Copyright (C) 2008 Doug Coleman, Michael Judge.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays combinators kernel math math.analysis USING: arrays combinators kernel math math.analysis
math.functions math.order sequences sorting ; math.functions math.order sequences sorting locals
sequences.private ;
IN: math.statistics IN: math.statistics
: mean ( seq -- n ) : mean ( seq -- x )
[ sum ] [ length ] bi / ; [ sum ] [ length ] bi / ;
: geometric-mean ( seq -- n ) : geometric-mean ( seq -- x )
[ length ] [ product ] bi nth-root ; [ length ] [ product ] bi nth-root ;
: harmonic-mean ( seq -- n ) : harmonic-mean ( seq -- x )
[ recip ] sigma recip ; [ recip ] sigma recip ;
: median ( seq -- n ) :: kth-smallest ( seq k -- elt )
natural-sort dup length even? [ #! Wirth's method, Algorithm's + Data structues = Programs p. 84
[ midpoint@ dup 1 - 2array ] keep nths mean #! The algorithm modifiers seq, so we clone it
] [ seq clone :> seq
[ midpoint@ ] keep nth 0 :> i!
] if ; 0 :> j!
0 :> l!
0 :> x!
seq length 1 - :> m!
[ l m < ]
[
k seq nth x!
l i!
m j!
[ i j <= ]
[
[ i seq nth-unsafe x < ] [ i 1 + i! ] while
[ x j seq nth-unsafe < ] [ j 1 - j! ] while
i j <= [
i j seq exchange
i 1 + i!
j 1 - j!
] when
] do while
j k < [ i l! ] when
k i < [ j m! ] when
] while
k seq nth ; inline
: lower-median ( seq -- elt )
dup dup length odd? [ midpoint@ ] [ midpoint@ 1 - ] if kth-smallest ;
: upper-median ( seq -- elt )
dup midpoint@ kth-smallest ;
: medians ( seq -- lower upper )
[ lower-median ] [ upper-median ] bi ;
: median ( seq -- x )
dup length odd? [ lower-median ] [ medians + 2 / ] if ;
: minmax ( seq -- min max ) : minmax ( seq -- min max )
#! find the min and max of a seq in one pass #! find the min and max of a seq in one pass
[ 1/0. -1/0. ] dip [ [ min ] [ max ] bi-curry bi* ] each ; [ 1/0. -1/0. ] dip [ [ min ] [ max ] bi-curry bi* ] each ;
: range ( seq -- n ) : range ( seq -- x )
minmax swap - ; minmax swap - ;
: var ( seq -- x ) : var ( seq -- x )
@ -32,15 +68,13 @@ IN: math.statistics
dup length 1 <= [ dup length 1 <= [
drop 0 drop 0
] [ ] [
[ [ mean ] keep [ - sq ] with sigma ] keep [ [ mean ] keep [ - sq ] with sigma ]
length 1 - / [ length 1 - ] bi /
] if ; ] if ;
: std ( seq -- x ) : std ( seq -- x ) var sqrt ;
var sqrt ;
: ste ( seq -- x ) : ste ( seq -- x ) [ std ] [ length ] bi sqrt / ;
[ std ] [ length ] bi sqrt / ;
: ((r)) ( mean(x) mean(y) {x} {y} -- (r) ) : ((r)) ( mean(x) mean(y) {x} {y} -- (r) )
! finds sigma((xi-mean(x))(yi-mean(y)) ! finds sigma((xi-mean(x))(yi-mean(y))
@ -64,4 +98,3 @@ IN: math.statistics
[ (r) ] 2keep ! stack is mean(x) mean(y) r sx sy [ (r) ] 2keep ! stack is mean(x) mean(y) r sx sy
swap / * ! stack is mean(x) mean(y) beta swap / * ! stack is mean(x) mean(y) beta
[ swapd * - ] keep ; [ swapd * - ] keep ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2004, 2006 Chris Double, Matthew Willis. ! Copyright (C) 2004, 2006 Chris Double, Matthew Willis.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays kernel sequences math arrays namespaces USING: accessors arrays effects fry generalizations kernel math
parser effects generalizations fry words accessors ; namespaces parser sequences words ;
IN: promises IN: promises
TUPLE: promise quot forced? value ; TUPLE: promise quot forced? value ;

View File

@ -1,17 +1,17 @@
! Copyright (c) 2008 Slava Pestov ! Copyright (c) 2008 Slava Pestov
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors io io.backend io.files kernel math math.parser USING: accessors io io.backend io.files kernel math math.parser
sequences vectors quotations ; sequences byte-arrays byte-vectors quotations ;
IN: checksums IN: checksums
MIXIN: checksum MIXIN: checksum
TUPLE: checksum-state bytes-read block-size bytes ; TUPLE: checksum-state
{ bytes-read integer } { block-size integer } { bytes byte-vector } ;
: new-checksum-state ( class -- checksum-state ) : new-checksum-state ( class -- checksum-state )
new new
0 >>bytes-read BV{ } clone >>bytes ; inline
V{ } clone >>bytes ; inline
M: checksum-state clone M: checksum-state clone
call-next-method call-next-method
@ -27,11 +27,13 @@ GENERIC: get-checksum ( checksum -- value )
over bytes>> [ push-all ] keep over bytes>> [ push-all ] keep
[ dup length pick block-size>> >= ] [ dup length pick block-size>> >= ]
[ [
64 cut-slice [ 64 cut-slice [ >byte-array ] dip [
over [ checksum-block ] over [ checksum-block ]
[ [ 64 + ] change-bytes-read drop ] bi [ [ 64 + ] change-bytes-read drop ] bi
] dip ] dip
] while >vector [ >>bytes ] [ length [ + ] curry change-bytes-read ] bi ; ] while
>byte-vector
[ >>bytes ] [ length [ + ] curry change-bytes-read ] bi ;
: add-checksum-stream ( checksum-state stream -- checksum-state ) : add-checksum-stream ( checksum-state stream -- checksum-state )
[ [

View File

@ -88,6 +88,9 @@ M: sequence set-nth bounds-check set-nth-unsafe ;
M: sequence nth-unsafe nth ; M: sequence nth-unsafe nth ;
M: sequence set-nth-unsafe set-nth ; M: sequence set-nth-unsafe set-nth ;
: change-nth-unsafe ( i seq quot -- )
[ [ nth-unsafe ] dip call ] 3keep drop set-nth-unsafe ; inline
! The f object supports the sequence protocol trivially ! The f object supports the sequence protocol trivially
M: f length drop 0 ; M: f length drop 0 ;
M: f nth-unsafe nip ; M: f nth-unsafe nip ;

View File

@ -172,7 +172,7 @@ M: or-parser parse ( input parser1 -- list )
#! Return the combined list resulting from the parses #! Return the combined list resulting from the parses
#! of parser1 and parser2 being applied to the same #! of parser1 and parser2 being applied to the same
#! input. This implements the choice parsing operator. #! input. This implements the choice parsing operator.
parsers>> 0 swap seq>list parsers>> sequence>list
[ parse ] with lazy-map lconcat ; [ parse ] with lazy-map lconcat ;
: trim-head-slice ( string -- string ) : trim-head-slice ( string -- string )