f(x) = f odd (x)+f even (x)



f odd (x) = (f(x)-f(-x))/2, f even (x) = (f(x)+f(-x))/2



odd

odd

odd

> import Prelude hiding (odd) > odd f x = let s = sqrt x in 0.5*(f s - f (-s))/s

> f x = x*(1+x*(2+x*(3+7*x))) > test0 = odd f 3

f

odd f

odd

odd

1 -> 0 x -> 1 x2 -> 0 x3 -> x x2n -> 0 x2n+1 -> xn

0 1 x 0

a b c d

> data O a = O a a a deriving (Show, Eq) > instance Num a => Num (O a) where > O a b c + O a' b' c' = O (a+a') (b+b') (c+c') > O a b c * O a' b' c' = O (a*a'+b*c') (a*b'+b*a') (c*a'+a*c') > fromInteger n = let i = fromInteger n in O i 0 0 > negate (O a b c) = O (negate a) (negate b) (negate c)

> instance Fractional a => Fractional (O a) where > fromRational n = let i = fromRational n in O i 0 0 > recip (O a b c) = let idet = recip (a*a-b*c) in O (idet*a) (idet*negate b) (idet*negate c)

odd

> transition x = O 0 1 x > odd' f x = let O _ fx _ = f (transition x) in fx > test1 = odd' f 3

> test3 = odd' (\x -> (x+3*x*x-1/x)/(x*x)) 2 > test4 = odd (\x -> (x+3*x*x-1/x)/(x*x)) 2

Suppose you have a real valued function on the reals, say f. We can split it into the sum of an even and odd part:whereIf fhas a power series around zero, then all of its terms must have odd powers in x. So f(x)/x must have all even powers and it becomes natural to 'compress' down the terms to form f'(x) = f(sqrt(x))/sqrt(x). (Take that as a definition of f' for this article.) We can implement this operation as a higher order function:Here's a simple example:But there's something not quite right about this. Ifis rational, then so is. But the implementation ofinvolves square roots. Among other things, square roots introduce inaccuracy. As square roots don't appear in the final result, can we eliminate them from the intermediate steps of the computation too?Let's use the results of last week's article to computeanother way. We want a linear function that maps as follows:Here's an automaton:If we start at 0, end at 1, and take exactly n steps, then the product of the factors we collect up along the way is given by the second column of that table. In n is even there is no such path so we collect up 0. As we're working with polynomials over the reals, rather than types, we have x1=1x and so on. We can construct a transition matrix:We now do something like we did last time . Any time we have a function of some variable x, we replace x with the transition matrix. Our functions now take matrix values likeAny polynomial of our transition matrix always gives us equal elements along the diagonal. This is true even if we form the inverse of the transition matrix. So we don't need to store d. So now we implement a simple matrix type needing only to store three elements instead of four:Notice how similar this is to automatic differentiation. We can extend to reciprocals too:And now we can implement a replacement forAnother example:This new version has many advantages: it uses only rational functions, it's more accurate, and it's well defined at zero.Automatic differentiation is just one of a family of methods that can be used to compute a wide variety of functions of real-valued functions. Essentially we're just working over real-valued matrices instead of real numbers. By using automata we can simplify the process of working out which matrices to use. (Though for the simple example above, you may have been able to guess the matrix without any other help).(BTW I think there are hidden automata lurking in a few places in mathematics. For example, in Umbral calculus .)