{-# LANGUAGE RebindableSyntax #-}
module Circuit.Diff.Inverse
(
newton,
inverseN,
implicit1N,
varDiff,
constDiff,
)
where
import Circuit.Diff (Diff (..), runDiff)
import NumHask.Algebra.Additive (Additive (..), Subtractive (..))
import NumHask.Algebra.Multiplicative (Divisive (..), Multiplicative (..))
import NumHask.Prelude
varDiff :: Diff p a a
varDiff :: forall {k} (p :: k) a. Diff p a a
varDiff = (a -> (a, a -> a)) -> Diff p a a
forall k (p :: k) a b. (a -> (b, b -> a)) -> Diff p a b
Diff (\a
s -> (a
s, a -> a
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id))
constDiff :: (Additive a) => b -> Diff p a b
constDiff :: forall {k} a b (p :: k). Additive a => b -> Diff p a b
constDiff b
b = (a -> (b, b -> a)) -> Diff p a b
forall k (p :: k) a b. (a -> (b, b -> a)) -> Diff p a b
Diff ((b, b -> a) -> a -> (b, b -> a)
forall a b. a -> b -> a
const (b
b, a -> b -> a
forall a b. a -> b -> a
const a
forall a. Additive a => a
zero))
newton ::
(Subtractive a, Divisive a) =>
Diff p a a ->
a ->
a ->
Int ->
a
newton :: forall {k} a (p :: k).
(Subtractive a, Divisive a) =>
Diff p a a -> a -> a -> Int -> a
newton Diff p a a
f a
target a
x0 Int
n =
let step :: a -> a
step a
x =
let (a
y, a -> a
pb) = Diff p a a -> a -> (a, a -> a)
forall k (p :: k) a b. Diff p a b -> a -> (b, b -> a)
runDiff Diff p a a
f a
x
dy :: a
dy = a -> a
pb a
forall a. Multiplicative a => a
one
in a
x a -> a -> a
forall a. Subtractive a => a -> a -> a
- (a
y a -> a -> a
forall a. Subtractive a => a -> a -> a
- a
target) a -> a -> a
forall a. Divisive a => a -> a -> a
/ a
dy
in ([a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
n) ((a -> a) -> a -> [a]
forall a. (a -> a) -> a -> [a]
iterate a -> a
step a
x0)
inverseN ::
(Subtractive a, Divisive a) =>
Diff p a a ->
a ->
a ->
Int ->
a
inverseN :: forall {k} a (p :: k).
(Subtractive a, Divisive a) =>
Diff p a a -> a -> a -> Int -> a
inverseN Diff p a a
f a
y = Diff p a a -> a -> a -> Int -> a
forall {k} a (p :: k).
(Subtractive a, Divisive a) =>
Diff p a a -> a -> a -> Int -> a
newton Diff p a a
f a
y
implicit1N ::
(Subtractive b, Divisive b) =>
Diff p b b ->
b ->
Int ->
b
implicit1N :: forall {k} b (p :: k).
(Subtractive b, Divisive b) =>
Diff p b b -> b -> Int -> b
implicit1N Diff p b b
g = Diff p b b -> b -> b -> Int -> b
forall {k} a (p :: k).
(Subtractive a, Divisive a) =>
Diff p a a -> a -> a -> Int -> a
newton Diff p b b
g b
forall a. Additive a => a
zero