\ -*- mode: forth -*-
\ $Id: moments.gforth,v 1.1 2001/06/03 12:10:25 doug Exp $
\ http://www.bagley.org/~doug/shootout/
\ from Anton Ertl
1024 constant max-line
create line max-line 2 + allot
: input-floats
>r 0e begin
line max-line r@ read-line throw
while
line swap >float 0= abort" float expected"
fdup f, f+
repeat
rdrop drop ;
: compute-loop
dup 0 d>f fdup { f: n } f/ { f: mean }
0e fdup fdup fdup
floats bounds do { f: avg-deviation f: variance f: skew f: kurtosis }
i f@ mean f- { f: deviation }
deviation fabs avg-deviation f+
deviation fdup f* fdup variance f+
fswap deviation f* fdup skew f+
fswap deviation f* kurtosis f+
float +loop
frot n 1e f- f/ to variance
frot to avg-deviation
variance fsqrt { f: standard-deviation }
variance f0<> if
n variance fdup f* f* f/ 3e f-
fswap n variance f* standard-deviation f* f/ fswap
endif
fswap variance standard-deviation avg-deviation n f/ mean ;
float- -1 floats ,
: partition { first last -- last-smaller first-larger }
\ partition array addr1 u1 into all elements less than pivot and all
\ others, addr1 u2 and addr3 u3 are the two partitions.
\ lessthan-xt ( elemptr1 elemptr2 -- f ) compares the two elements
first last + 1 rshift faligned f@ { f: pivot }
first last begin
begin
pivot dup f@ f< over first u> and
while
float-
repeat
swap begin
dup last u< over f@ pivot f< and
while
float+
repeat
2dup u>=
while
dup f@ over f@ dup f! over f!
float+ swap float-
repeat ;
: quantile recursive
\ sorts the array [first,last] such that the contained part of
\ [quant-low,quant-high] is the same as in the fully sorted array.
{ quant-low quant-high }
begin { first last }
first quant-high u< quant-low last u< and
while
first last partition
last quant-low quant-high quantile
first swap
repeat ;
: median { addr u -- rmedian }
addr u 1- 2/ floats + addr u 2/ floats +
addr addr u 1- floats + 2over quantile
f@ f@ f+ f2/ ;
: ff.
f$ dup >r 0<
IF '0 emit ELSE scratch r@ min type r@ precision - zeros ENDIF
'. emit
r@ negate zeros
scratch r> 0 max /string 0 max type ;
create nums \ s" moments.input" r/o open-file throw input-floats
stdin input-floats
nums here over - float /
." n: " dup 0 .r cr
compute-loop
nums here over - float / median 9 set-precision
." median: " ff. cr
." mean: " ff. cr
." average_deviation: " ff. cr
." standard_deviation: " ff. cr 11 set-precision
." variance: " ff. cr 7 set-precision
." skew: " ff. cr
." kurtosis: " ff. cr
bye