module Math.Root.Finder.Bisection
( Bisect, bisection
) where
import Math.Root.Finder
data Bisect a b = Bisect { _bisX :: !a, _bisF :: !b , _bisDX :: !a }
deriving (Eq, Ord, Show)
instance (Fractional a, Eq a, Ord b, Num b) => RootFinder Bisect a b where
initRootFinder f x1 x2
| f1 < 0 = Bisect x1 f1 (x2x1)
| otherwise = Bisect x2 f2 (x1x2)
where f1 = f x1; f2 = f x2
stepRootFinder _ orig@(Bisect _ _ 0) = orig
stepRootFinder f orig@(Bisect x fx dx)
| x == xMid = orig
| otherwise = case fMid `compare` 0 of
LT -> Bisect xMid fMid dx2
EQ -> Bisect xMid fMid dx2
GT -> Bisect x fx dx2
where
dx2 = dx * 0.5
xMid = x + dx2
fMid = f xMid
estimateRoot (Bisect x _ _) = x
estimateError (Bisect _ _ dx) = dx
bisection :: (Ord a, Fractional a, Ord b, Num b) => (a -> b) -> a -> a -> a -> Either (Bisect a b) a
bisection f x1 x2 xacc = fmap estimateRoot (findRoot f x1 x2 xacc)