aern2-real-0.2.15.1: src/AERN2/Continuity/Principles.hs
module AERN2.Continuity.Principles
( maxSeqIndexUsed,
maxIntParamUsed,
)
where
import AERN2.Kleenean (Kleenean (..), kleenean)
import AERN2.Real (pi)
import AERN2.Real.CKleenean (CKleenean)
import AERN2.Real.Comparisons ()
import AERN2.Real.Type (CSequence (..), creal)
import GHC.Conc (TVar, atomically, newTVarIO, readTVar, readTVarIO, writeTVar)
import GHC.IO (unsafePerformIO)
import MixedTypesNumPrelude
-- |
-- Apply a predicate to a `CSequence`, assuming it returns True
-- and return the largest index in the sequence that was accessed during the computation.
-- Index 0 means that the sequence was not accessed at all,
-- 1 means the first element was accessed, etc.
maxSeqIndexUsed :: (CSequence t -> CKleenean) -> CSequence t -> Integer
maxSeqIndexUsed = maxEffortUsed addCSequenceAccessMonitor
-- |
-- Apply a predicate to a convergent sequence, assuming it returns True
-- and return the largest index in the sequence that was accessed during the computation.
-- Index 0 means that the sequence was not accessed at all,
-- 1 means the sequence was called only with index 0, etc.
maxIntParamUsed :: ((Integer -> t) -> CKleenean) -> (Integer -> t) -> Integer
maxIntParamUsed = maxEffortUsed addCallMonitor
maxEffortUsed :: (TVar Integer -> seq -> seq) -> (seq -> CKleenean) -> seq -> Integer
maxEffortUsed addMonitor f x =
unsafePerformIO $ do
maxSoFarTvar <- newTVarIO 0
let res = f (addMonitor maxSoFarTvar x)
let true = waitForTrue (unCSequence res)
if isCertainlyTrue true
then readTVarIO maxSoFarTvar
else error "internal error in maxEffortUsed" -- this should never happen
addCallMonitor :: TVar Integer -> (Integer -> a) -> Integer -> a
addCallMonitor maxSoFarTvar x i =
unsafePerformIO $ do
atomically $ do
prevMax <- readTVar maxSoFarTvar
writeTVar maxSoFarTvar (prevMax `max` (i + 1)) -- calling x with 0 sets max to 1, etc.
pure (x i)
addCSequenceAccessMonitor :: TVar Integer -> CSequence t -> CSequence t
addCSequenceAccessMonitor maxSoFarTvar x = CSequence (monitorSeq 1 (unCSequence x))
where
monitorSeq _ [] = []
monitorSeq i (h : t) = monitorH : monitorSeq (i + 1) t
where
monitorH = unsafePerformIO $ do
atomically $ writeTVar maxSoFarTvar i
pure h
waitForTrue :: [CN Kleenean] -> CN Kleenean
waitForTrue [] = cn TrueOrFalse
waitForTrue (h : t)
| isCertainlyTrue h = h
| otherwise = waitForTrue t
_testNever :: Integer
_testNever = maxSeqIndexUsed (> 0) (pi - pi) -- loop forever
_test0 :: Integer
_test0 = maxSeqIndexUsed (> 0) (pi - pi + creal (1 / 1000000000)) -- 8
_test1 :: Integer
_test1 = maxIntParamUsed (\x -> CSequence (map (\n -> cn (kleenean (n > 3 * x n))) [0 ..])) (const 3) -- 11