Hi all, Those of you interested in numerical computing should take a look at my implementation of the "nbody" benchmark from the language shootout:
http://gitweb.factorcode.org/gitweb.cgi?p=factor/.git;a=blob;f=extra/benchmark/nbody/nbody.factor;hb=HEAD Here are implementations in other languages: http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=all The Factor version is a lot more elegant because I'm using the words in the math.vectors vocabulary instead of doing everything with explicit x/y/z values. The other implementations juggle 12 local variables in a single function whereas the Factor version just uses vector objects with at most 1 or 2 values on the stack. This makes the Factor version clearer and shorter. Two of the words use locals, one of them is a combinator that abstracts out a pattern which appears twice: :: each-pair ( bodies pair-quot: ( other-body body -- ) each-quot: ( body -- ) -- ) bodies [| body i | body each-quot call bodies i 1+ tail-slice [ body pair-quot call ] each ] each-index ; inline The other one is the inner loop of the benchmark: :: update-velocity ( other-body body dt -- ) dt body other-body mag [ [ body ] 2dip '[ other-body mass>> _ * _ n*v v- ] change-velocity drop ] [ [ other-body ] 2dip '[ body mass>> _ * _ n*v v+ ] change-velocity drop ] 2bi ; I found the combined usage of locals and fry interesting, although perhaps it would have been better to just use [let, or rewrite it without locals and only using fry. The utility of the math.vectors words cannot be underestimated. For example, look at the following three words; to me, they're the most beautiful in this entire program: : inertia ( body -- e ) [ mass>> ] [ velocity>> norm-sq ] bi * 0.5 * ; : newton's-law ( other-body body -- e ) [ [ mass>> ] bi@ * ] [ [ location>> ] bi@ distance ] 2bi / ; : energy ( system -- x ) [ 0.0 ] dip bodies>> [ newton's-law - ] [ inertia + ] each-pair ; inline Compare this with some Scheme code from the shootout which does the same thing: (define (energy) (let loop-o ([o *system*] [e 0.0]) (if (null? o) e (let* ([o1 (car o)] [e (+ e (* (* 0.5 (body-mass o1)) (+ (+ (* (body-vx o1) (body-vx o1)) (* (body-vy o1) (body-vy o1))) (* (body-vz o1) (body-vz o1)))))]) (let loop-i ([i (cdr o)] [e e]) (if (null? i) (loop-o (cdr o) e) (let* ([i1 (car i)] [dx (- (body-x o1) (body-x i1))] [dy (- (body-y o1) (body-y i1))] [dz (- (body-z o1) (body-z i1))] [dist (sqrt (+ (+ (* dx dx) (* dy dy)) (* dz dz)))] [e (- e (/ (* (body-mass o1) (body-mass i1)) dist))]) (loop-i (cdr i) e)))))))) Gross! Slava ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ Factor-talk mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/factor-talk
