{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstrainedClassMethods #-}
module Data.CReal.Converge
( Converge(..)
) where
import Control.Arrow ((&&&))
import Data.Coerce (coerce)
import Data.CReal.Internal (CReal(..), atPrecision, crMemoize)
import Data.Function (on)
import Data.Proxy (Proxy)
import GHC.TypeLits (someNatVal, SomeNat(..))
class Converge a where
type Element a
converge :: a -> Maybe (Element a)
convergeErr :: Ord (Element a) => (Element a -> Element a) -> a -> Maybe (Element a)
instance {-# OVERLAPPABLE #-} Eq a => Converge [a] where
type Element [a] = a
converge :: [a] -> Maybe (Element [a])
converge = [a] -> Maybe a
forall a. [a] -> Maybe a
lastMay ([a] -> Maybe a) -> ([a] -> [a]) -> [a] -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> Bool) -> [a] -> [a]
forall a. (a -> a -> Bool) -> [a] -> [a]
takeWhilePairwise a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(/=)
{-# INLINE converge #-}
convergeErr :: (Element [a] -> Element [a]) -> [a] -> Maybe (Element [a])
convergeErr err :: Element [a] -> Element [a]
err xs :: [a]
xs = ((a, a) -> a) -> Maybe (a, a) -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, a) -> a
forall a b. (a, b) -> b
snd (Maybe (a, a) -> Maybe a)
-> ([(a, a)] -> Maybe (a, a)) -> [(a, a)] -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(a, a)] -> Maybe (a, a)
forall a. [a] -> Maybe a
lastMay ([(a, a)] -> Maybe (a, a))
-> ([(a, a)] -> [(a, a)]) -> [(a, a)] -> Maybe (a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, a) -> (a, a) -> Bool) -> [(a, a)] -> [(a, a)]
forall a. (a -> a -> Bool) -> [a] -> [a]
takeWhilePairwise (a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(>) (a -> a -> Bool) -> ((a, a) -> a) -> (a, a) -> (a, a) -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (a, a) -> a
forall a b. (a, b) -> a
fst) ([(a, a)] -> Maybe (Element [a]))
-> [(a, a)] -> Maybe (Element [a])
forall a b. (a -> b) -> a -> b
$ [(a, a)]
es
where es :: [(a, a)]
es = (a -> a
Element [a] -> Element [a]
err (a -> a) -> (a -> a) -> a -> (a, a)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& a -> a
forall a. a -> a
id) (a -> (a, a)) -> [a] -> [(a, a)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a]
xs
{-# INLINE convergeErr #-}
instance {-# OVERLAPPING #-} Converge [CReal n] where
type Element [CReal n] = CReal n
converge :: [CReal n] -> Maybe (Element [CReal n])
converge [] = Maybe (Element [CReal n])
forall a. Maybe a
Nothing
converge xs :: [CReal n]
xs =
CReal n -> Maybe (Element [CReal n])
forall a. a -> Maybe a
Just (CReal n -> Maybe (Element [CReal n]))
-> CReal n -> Maybe (Element [CReal n])
forall a b. (a -> b) -> a -> b
$ (Int -> Integer) -> CReal n
forall (n :: Nat). (Int -> Integer) -> CReal n
crMemoize (\p :: Int
p ->
case Integer -> Maybe SomeNat
someNatVal (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
p) of
Nothing -> [Char] -> Integer
forall a. HasCallStack => [Char] -> a
error "Data.CReal.Converge p should be non negative"
Just (SomeNat (Proxy n
_ :: Proxy p')) ->
let modifyPrecision :: [CReal n] -> [CReal n]
modifyPrecision = [CReal n] -> [CReal n]
forall a b. Coercible a b => a -> b
coerce :: [CReal n] -> [CReal p']
in ([CReal n] -> CReal n
forall a. [a] -> a
last ([CReal n] -> CReal n)
-> ([CReal n] -> [CReal n]) -> [CReal n] -> CReal n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CReal n -> CReal n -> Bool) -> [CReal n] -> [CReal n]
forall a. (a -> a -> Bool) -> [a] -> [a]
takeWhilePairwise CReal n -> CReal n -> Bool
forall a. Eq a => a -> a -> Bool
(/=) ([CReal n] -> [CReal n])
-> ([CReal n] -> [CReal n]) -> [CReal n] -> [CReal n]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CReal n] -> [CReal n]
modifyPrecision ([CReal n] -> CReal n) -> [CReal n] -> CReal n
forall a b. (a -> b) -> a -> b
$ [CReal n]
xs) CReal n -> Int -> Integer
forall (n :: Nat). CReal n -> Int -> Integer
`atPrecision` Int
p)
{-# INLINE converge #-}
convergeErr :: (Element [CReal n] -> Element [CReal n])
-> [CReal n] -> Maybe (Element [CReal n])
convergeErr _ [] = Maybe (Element [CReal n])
forall a. Maybe a
Nothing
convergeErr err :: Element [CReal n] -> Element [CReal n]
err xs :: [CReal n]
xs =
CReal n -> Maybe (Element [CReal n])
forall a. a -> Maybe a
Just (CReal n -> Maybe (Element [CReal n]))
-> CReal n -> Maybe (Element [CReal n])
forall a b. (a -> b) -> a -> b
$ (Int -> Integer) -> CReal n
forall (n :: Nat). (Int -> Integer) -> CReal n
crMemoize (\p :: Int
p ->
case Integer -> Maybe SomeNat
someNatVal (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
p) of
Nothing -> [Char] -> Integer
forall a. HasCallStack => [Char] -> a
error "Data.CReal.Converge p should be non negative"
Just (SomeNat (Proxy n
_ :: Proxy p')) ->
let modifyPrecision :: [CReal n] -> [CReal n]
modifyPrecision = [CReal n] -> [CReal n]
forall a b. Coercible a b => a -> b
coerce :: [CReal n] -> [CReal p']
modifyFunPrecision :: (CReal n -> CReal n) -> CReal n -> CReal n
modifyFunPrecision = (CReal n -> CReal n) -> CReal n -> CReal n
forall a b. Coercible a b => a -> b
coerce :: (CReal n -> CReal n) -> CReal p' -> CReal p'
es :: [(CReal n, CReal n)]
es = ((CReal n -> CReal n) -> CReal n -> CReal n
modifyFunPrecision CReal n -> CReal n
Element [CReal n] -> Element [CReal n]
err (CReal n -> CReal n)
-> (CReal n -> CReal n) -> CReal n -> (CReal n, CReal n)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& CReal n -> CReal n
forall a. a -> a
id) (CReal n -> (CReal n, CReal n))
-> [CReal n] -> [(CReal n, CReal n)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [CReal n] -> [CReal n]
modifyPrecision [CReal n]
xs
continue :: (a, a) -> (a, a) -> Bool
continue (e1 :: a
e1, x1 :: a
x1) (e2 :: a
e2, x2 :: a
x2) = if a
e1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== 0 then a
x1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
x2 else a
e1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
e2
in ((CReal n, CReal n) -> CReal n
forall a b. (a, b) -> b
snd ((CReal n, CReal n) -> CReal n)
-> ([(CReal n, CReal n)] -> (CReal n, CReal n))
-> [(CReal n, CReal n)]
-> CReal n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(CReal n, CReal n)] -> (CReal n, CReal n)
forall a. [a] -> a
last ([(CReal n, CReal n)] -> (CReal n, CReal n))
-> ([(CReal n, CReal n)] -> [(CReal n, CReal n)])
-> [(CReal n, CReal n)]
-> (CReal n, CReal n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((CReal n, CReal n) -> (CReal n, CReal n) -> Bool)
-> [(CReal n, CReal n)] -> [(CReal n, CReal n)]
forall a. (a -> a -> Bool) -> [a] -> [a]
takeWhilePairwise (CReal n, CReal n) -> (CReal n, CReal n) -> Bool
forall a a. (Num a, Eq a, Ord a) => (a, a) -> (a, a) -> Bool
continue ([(CReal n, CReal n)] -> CReal n)
-> [(CReal n, CReal n)] -> CReal n
forall a b. (a -> b) -> a -> b
$ [(CReal n, CReal n)]
es) CReal n -> Int -> Integer
forall (n :: Nat). CReal n -> Int -> Integer
`atPrecision` Int
p)
{-# INLINE convergeErr #-}
takeWhilePairwise :: (a -> a -> Bool) -> [a] -> [a]
takeWhilePairwise :: (a -> a -> Bool) -> [a] -> [a]
takeWhilePairwise p :: a -> a -> Bool
p (x1 :: a
x1:x2 :: a
x2:xs :: [a]
xs) = if a
x1 a -> a -> Bool
`p` a
x2
then a
x1 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: (a -> a -> Bool) -> [a] -> [a]
forall a. (a -> a -> Bool) -> [a] -> [a]
takeWhilePairwise a -> a -> Bool
p (a
x2a -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs)
else [a
x1]
takeWhilePairwise _ xs :: [a]
xs = [a]
xs
lastMay :: [a] -> Maybe a
lastMay :: [a] -> Maybe a
lastMay [] = Maybe a
forall a. Maybe a
Nothing
lastMay xs :: [a]
xs = a -> Maybe a
forall a. a -> Maybe a
Just ([a] -> a
forall a. [a] -> a
last [a]
xs)