module Numeric.AD
(
grad, grad2
, gradWith, gradWith2
, jacobian, jacobian2
, jacobianWith, jacobianWith2
, diff
, diff2
, diffs
, diffs0
, diffUU
, diffUF
, diff2UU
, diff2UF
, diffFU
, diff2FU
, diffsUU
, diffsUF
, diffs0UU
, diffs0UF
, taylor
, taylor0
, AD(..)
, Mode(..)
) where
import Data.Traversable (Traversable)
import Data.Foldable (Foldable, foldr')
import Control.Applicative
import Numeric.AD.Classes (Mode(..))
import Numeric.AD.Internal (AD(..), probed, unprobe)
import Numeric.AD.Forward (diff, diffUU, diff2, diff2UU, diffUF, diff2UF)
import Numeric.AD.Tower (diffsUU, diffs0UU , diffsUF, diffs0UF , diffs, diffs0, taylor, taylor0)
import Numeric.AD.Reverse (diffFU, diff2FU, grad, grad2, gradWith, gradWith2)
import qualified Numeric.AD.Forward as Forward
import qualified Numeric.AD.Reverse as Reverse
jacobian :: (Traversable f, Traversable g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f a)
jacobian f bs = snd <$> jacobian2 f bs
jacobian2 :: (Traversable f, Traversable g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)
jacobian2 f bs | n == 0 = fmap (\x -> (unprobe x, bs)) as
| n > m = Reverse.jacobian2 f bs
| otherwise = Forward.jacobian2 f bs
where
as = f (probed bs)
n = size bs
m = size as
size :: Foldable f => f a -> Int
size = foldr' (\_ b -> 1 + b) 0
jacobianWith :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f b)
jacobianWith g f bs = snd <$> jacobianWith2 g f bs
jacobianWith2 :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)
jacobianWith2 g f bs
| n == 0 = fmap (\x -> (unprobe x, undefined <$> bs)) as
| n > m = Reverse.jacobianWith2 g f bs
| otherwise = Forward.jacobianWith2 g f bs
where
as = f (probed bs)
n = size bs
m = size as
size :: Foldable f => f a -> Int
size = foldr' (\_ b -> 1 + b) 0