{-# LANGUAGE BangPatterns, Rank2Types, ScopedTypeVariables #-}
{-
emndl -- exponentially transformed Mandelbrot Set renderer
Copyright (C) 2011 Claude Heiland-Allen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-}
module Roots (root2, root4, FF, lift) where
import Prelude hiding (zipWith)
import Data.Functor ((<$>))
import Data.Vec (toList, solve, fromList, matFromLists, zipWith, Vec2, Mat22, Vec4, Mat44, NearZero(nearZero))
import Numeric.AD (jacobian', FF, lift)
root2' :: forall r . (Fractional r, NearZero r, Ord r) => FF [] [] r -> Vec2 r -> Vec2 r
root2' f !x = go x
where
jf = jacobian' f
go x0 =
let (ys, js) = unzip $ jf (toList x0)
y = fromList (negate <$> ys) :: Vec2 r
j = matFromLists js :: Mat22 r
mdx = solve j y
in if all nearZero ys
then x0
else case mdx of
Nothing -> x0
Just dx ->
let x1 = zipWith (+) x0 dx
in if all nearZero (toList dx)
then x1
else go x1
root2 :: (Fractional r, NearZero r, Ord r) => FF [] [] r -> [r] -> [r]
root2 f = toList . root2' f . fromList
root4' :: forall r . (Fractional r, NearZero r, Ord r) => FF [] [] r -> Vec4 r -> Vec4 r
root4' f !x = go x
where
jf = jacobian' f
go x0 =
let (ys, js) = unzip $ jf (toList x0)
y = fromList (negate <$> ys) :: Vec4 r
j = matFromLists js :: Mat44 r
mdx = solve j y
in if all nearZero ys
then x0
else case mdx of
Nothing -> x0
Just dx ->
let x1 = zipWith (+) x0 dx
in if all nearZero (toList dx)
then x1
else go x1
root4 :: (Fractional r, NearZero r, Ord r) => FF [] [] r -> [r] -> [r]
root4 f = toList . root4' f . fromList