module Data.Number.IReal.UnsafeMemo where
import Data.Number.IReal.Scalable
import Control.Concurrent.MVar (newMVar, readMVar, modifyMVar_)
import System.IO.Unsafe (unsafePerformIO)
unsafeMemo :: Scalable a => (Int -> a) -> Int -> a
unsafeMemo f = unsafePerformIO . unsafePerformIO (memoIO f)
memoIO :: Scalable a => (Int -> a) -> IO (Int -> IO a)
memoIO f = do
v <- newMVar Nothing
return (\p ->
if p<0
then error ("Excessive precision required: " ++ show (fromIntegral p + 2^32))
else do
m <- readMVar v
case m of
Just (q,y)
|p <= q -> return (scale y (p q))
_ -> do let z = f p
modifyMVar_ v (const (return (Just (p,z))))
return z)