{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE Safe #-}
module Physics.Learn.RootFinding
( findRoots
, findRootsN
, findRoot
, bracketRoot
, bracketRootStep
)
where
bracketRoot :: (Ord a, Fractional a) =>
a
-> (a -> a)
-> (a,a)
-> (a,a)
bracketRoot :: forall a.
(Ord a, Fractional a) =>
a -> (a -> a) -> (a, a) -> (a, a)
bracketRoot a
dx a -> a
f (a
a,a
b)
= let fa :: a
fa = a -> a
f a
a
fb :: a
fb = a -> a
f a
b
bRoot :: ((a, a), (a, a)) -> (a, a)
bRoot ((a
c,a
fc),(a
d,a
fd)) = let m :: a
m = (a
c forall a. Num a => a -> a -> a
+ a
d) forall a. Fractional a => a -> a -> a
/ a
2
fm :: a
fm = a -> a
f a
m
in if forall a. Num a => a -> a
abs (a
c forall a. Num a => a -> a -> a
- a
d) forall a. Ord a => a -> a -> Bool
< a
dx
then (a
c,a
d)
else if a
fc forall a. Num a => a -> a -> a
* a
fm forall a. Ord a => a -> a -> Bool
<= a
0
then ((a, a), (a, a)) -> (a, a)
bRoot ((a
c,a
fc),(a
m,a
fm))
else ((a, a), (a, a)) -> (a, a)
bRoot ((a
m,a
fm),(a
d,a
fd))
in if a
fa forall a. Num a => a -> a -> a
* a
fb forall a. Ord a => a -> a -> Bool
> a
0
then forall a. HasCallStack => [Char] -> a
error [Char]
"bracketRoot: initial interval is not a bracket"
else ((a, a), (a, a)) -> (a, a)
bRoot ((a
a,a
fa),(a
b,a
fb))
bracketRootStep :: (Ord a, Fractional a) =>
(a -> a)
-> ((a,a),(a,a))
-> ((a,a),(a,a))
bracketRootStep :: forall a.
(Ord a, Fractional a) =>
(a -> a) -> ((a, a), (a, a)) -> ((a, a), (a, a))
bracketRootStep a -> a
f ((a
a,a
fa),(a
b,a
fb))
= let m :: a
m = (a
a forall a. Num a => a -> a -> a
+ a
b) forall a. Fractional a => a -> a -> a
/ a
2
fm :: a
fm = a -> a
f a
m
in if a
fa forall a. Num a => a -> a -> a
* a
fm forall a. Ord a => a -> a -> Bool
<= a
0
then ((a
a,a
fa),(a
m,a
fm))
else ((a
m,a
fm),(a
b,a
fb))
findRootMachinePrecision :: (Double -> Double)
-> ((Double,Double),(Double,Double))
-> Double
findRootMachinePrecision :: (Double -> Double)
-> ((Double, Double), (Double, Double)) -> Double
findRootMachinePrecision Double -> Double
f ((Double
c,Double
fc),(Double
d,Double
fd))
= let m :: Double
m = (Double
c forall a. Num a => a -> a -> a
+ Double
d) forall a. Fractional a => a -> a -> a
/ Double
2
fm :: Double
fm = Double -> Double
f Double
m
in if Double
fc forall a. Eq a => a -> a -> Bool
== Double
0
then Double
c
else if Double
fd forall a. Eq a => a -> a -> Bool
== Double
0
then Double
d
else if Double
c forall a. Eq a => a -> a -> Bool
== Double
m
then Double
c
else if Double
m forall a. Eq a => a -> a -> Bool
== Double
d
then Double
d
else if Double
fc forall a. Num a => a -> a -> a
* Double
fm forall a. Ord a => a -> a -> Bool
<= Double
0
then (Double -> Double)
-> ((Double, Double), (Double, Double)) -> Double
findRootMachinePrecision Double -> Double
f ((Double
c,Double
fc),(Double
m,Double
fm))
else (Double -> Double)
-> ((Double, Double), (Double, Double)) -> Double
findRootMachinePrecision Double -> Double
f ((Double
m,Double
fm),(Double
d,Double
fd))
findRoot :: (Double -> Double)
-> (Double,Double)
-> Double
findRoot :: (Double -> Double) -> (Double, Double) -> Double
findRoot Double -> Double
f (Double
a,Double
b)
= let fa :: Double
fa = Double -> Double
f Double
a
fb :: Double
fb = Double -> Double
f Double
b
in if Double
fa forall a. Num a => a -> a -> a
* Double
fb forall a. Ord a => a -> a -> Bool
> Double
0
then forall a. HasCallStack => [Char] -> a
error [Char]
"bracketRoot: initial interval is not a bracket"
else (Double -> Double)
-> ((Double, Double), (Double, Double)) -> Double
findRootMachinePrecision Double -> Double
f ((Double
a,Double
fa),(Double
b,Double
fb))
findRootsN :: Int
-> (Double -> Double)
-> (Double,Double)
-> [Double]
findRootsN :: Int -> (Double -> Double) -> (Double, Double) -> [Double]
findRootsN Int
n Double -> Double
f (Double
a,Double
b)
= let dx :: Double
dx = (Double
b forall a. Num a => a -> a -> a
- Double
a) forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n
xs :: [Double]
xs = [Double
a,Double
aforall a. Num a => a -> a -> a
+Double
dx..Double
b]
in forall a b. (a -> b) -> [a] -> [b]
map ((Double -> Double)
-> ((Double, Double), (Double, Double)) -> Double
findRootMachinePrecision Double -> Double
f) [((Double
x0,Double
fx0),(Double
x1,Double
fx1)) | (Double
x0,Double
x1) <- forall a b. [a] -> [b] -> [(a, b)]
zip [Double]
xs (forall a. [a] -> [a]
tail [Double]
xs), let fx0 :: Double
fx0 = Double -> Double
f Double
x0, let fx1 :: Double
fx1 = Double -> Double
f Double
x1, Double
fx0 forall a. Num a => a -> a -> a
* Double
fx1 forall a. Ord a => a -> a -> Bool
<= Double
0]
findRoots :: (Double -> Double)
-> (Double,Double)
-> [Double]
findRoots :: (Double -> Double) -> (Double, Double) -> [Double]
findRoots = Int -> (Double -> Double) -> (Double, Double) -> [Double]
findRootsN Int
1000