1 ! Copyright (C) 2009 Jason W. Merrill.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel math math.functions math.derivatives accessors
4 macros words effects vocabs sequences generalizations fry
5 combinators.smart generic compiler.units ;
9 TUPLE: dual ordinary-part epsilon-part ;
13 ! Ordinary numbers implement the dual protocol by returning
14 ! themselves as the ordinary part, and 0 as the epsilon part.
15 M: number ordinary-part>> ;
17 M: number epsilon-part>> drop 0 ;
19 : unpack-dual ( dual -- ordinary-part epsilon-part )
20 [ ordinary-part>> ] [ epsilon-part>> ] bi ;
24 : input-length ( word -- n ) stack-effect in>> length ;
26 MACRO: ordinary-op ( word -- o )
28 '[ [ ordinary-part>> ] _ napply _ execute ] ;
30 ! Takes N dual numbers <o1,e1> <o2,e2> ... <oN,eN> and weaves
31 ! their ordinary and epsilon parts to produce
32 ! e1 o1 o2 ... oN e2 o1 o2 ... oN ... eN o1 o2 ... oN
33 ! This allows a set of partial derivatives each to be evaluated
35 MACRO: duals>nweave ( n -- )
38 [ [ epsilon-part>> ] _ napply ]
40 [ ordinary-part>> ] _ napply
44 MACRO: chain-rule ( word -- e )
45 [ input-length '[ _ duals>nweave ] ]
46 [ "derivative" word-prop ]
47 [ input-length 1+ '[ _ nspread ] ]
49 '[ [ @ _ @ ] sum-outputs ] ;
53 MACRO: dual-op ( word -- )
54 [ '[ _ ordinary-op ] ]
55 [ input-length '[ _ nkeep ] ]
60 : define-dual ( word -- )
63 [ name>> "d" prepend "math.dual" create ]
64 bi [ set-stack-effect ] keep
67 '[ _ dual-op ] define ;
69 ! Specialize math functions to operate on dual numbers.
70 [ all-words [ "derivative" word-prop ] filter
71 [ define-dual ] each ] with-compilation-unit