{-# LANGUAGE CPP #-}
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Safe #-}
#endif
module Math.Sequence.Converge where
import Data.List
import Data.Maybe
import Data.Monoid
converge :: Eq a => [a] -> a
converge :: [a] -> a
converge [] = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"converge: empty list"
converge [a]
xs = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
forall a. a
empty (([a] -> Maybe a) -> (a -> Maybe a) -> [a] -> Maybe a
forall a b. ([a] -> Maybe b) -> (a -> Maybe b) -> [a] -> Maybe b
convergeBy [a] -> Maybe a
forall a. Eq a => [a] -> Maybe a
eq a -> Maybe a
forall a. a -> Maybe a
Just [a]
xs)
where
empty :: a
empty = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"converge: programming error in converge implementation"
eq :: [a] -> Maybe a
eq (a
a:a
b:[a]
_)
| a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b = a -> Maybe a
forall a. a -> Maybe a
Just a
b
| a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
b = a -> Maybe a
forall a. a -> Maybe a
Just a
a
eq [a]
_ = Maybe a
forall a. Maybe a
Nothing
convergeTo :: (Fractional a, Ord a) => a -> a -> [a] -> a
convergeTo :: a -> a -> [a] -> a
convergeTo a
absEps a
relEps [] = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"convergeTo: empty list"
convergeTo a
absEps a
relEps [a]
xs = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
forall a. a
empty (([a] -> Maybe a) -> (a -> Maybe a) -> [a] -> Maybe a
forall a b. ([a] -> Maybe b) -> (a -> Maybe b) -> [a] -> Maybe b
convergeBy [a] -> Maybe a
eq a -> Maybe a
forall a. a -> Maybe a
Just [a]
xs)
where
empty :: a
empty = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"convergeTo: programming error in convergeTo implementation"
eq :: [a] -> Maybe a
eq (a
a:a
b:[a]
_)
| a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
b = a -> Maybe a
forall a. a -> Maybe a
Just a
a
| a
absDiff a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a -> a
forall a. Num a => a -> a
abs a
absEps = a -> Maybe a
forall a. a -> Maybe a
Just a
b
| a
absDiff a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a -> a
forall a. Num a => a -> a
abs a
relEps a -> a -> a
forall a. Num a => a -> a -> a
* a
relScale = a -> Maybe a
forall a. a -> Maybe a
Just a
b
where
absDiff :: a
absDiff = a -> a
forall a. Num a => a -> a
abs (a
aa -> a -> a
forall a. Num a => a -> a -> a
-a
b)
relScale :: a
relScale = a -> a -> a
forall a. Ord a => a -> a -> a
max (a -> a
forall a. Num a => a -> a
abs a
a) (a -> a
forall a. Num a => a -> a
abs a
b)
eq [a]
_ = Maybe a
forall a. Maybe a
Nothing
convergeBy :: ([a] -> Maybe b) -> (a -> Maybe b) -> [a] -> Maybe b
convergeBy :: ([a] -> Maybe b) -> (a -> Maybe b) -> [a] -> Maybe b
convergeBy [a] -> Maybe b
f a -> Maybe b
end = [b] -> Maybe b
forall a. [a] -> Maybe a
listToMaybe ([b] -> Maybe b) -> ([a] -> [b]) -> [a] -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe b] -> [b]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe b] -> [b]) -> ([a] -> [Maybe b]) -> [a] -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([a] -> Maybe b) -> [[a]] -> [Maybe b]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> Maybe b
f' ([[a]] -> [Maybe b]) -> ([a] -> [[a]]) -> [a] -> [Maybe b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [[a]]
forall a. [a] -> [[a]]
tails
where
f' :: [a] -> Maybe b
f' [a]
xs = case [a] -> Maybe b
f [a]
xs of
Maybe b
Nothing -> [a] -> Maybe b
end' [a]
xs
Maybe b
other -> Maybe b
other
end' :: [a] -> Maybe b
end' [a
x] = a -> Maybe b
end a
x
end' [a]
_ = Maybe b
forall a. Maybe a
Nothing