module Data.RangeMin.Internal.HandyArray (unsafeMemoize', asPureArray, pureLookup, listLookup') where
import Data.RangeMin.Internal.HandyList()
import Control.Monad(Monad(..))
import Control.Monad.ST(ST, runST)
import Data.Array.ST(STArray)
import Data.Array.IArray(Ix(..), Array)
import Data.Array.Base
import GHC.Exts(Int#, Int(..), (+#), (-#), (==#))
asPureArray :: Ix i => Array i e -> Array i e
asPureArray = id
listToArray :: IArray a e => [e]
-> a Int e
listToArray list = listArray (0, length list 1) list
arraySize :: (Ix i, IArray a e) => a i e -> Int
arraySize = rangeSize . bounds
pureLookup :: Ix i => Array i e -> i -> e
pureLookup = (!)
pureUnsafeLookup :: Ix i => Array i e -> Int -> e
pureUnsafeLookup = unsafeAt
unsafeMemoize :: (Int -> e)
-> Int
-> (Int -> e)
unsafeMemoize f (n+1) = unsafeMemoize' f n
unsafeMemoize' :: (Int -> e)
-> Int
-> (Int -> e)
unsafeMemoize' f n = listLookerUpper (memoizer f n) (n+1)
memoizer :: (Int -> e) -> Int -> STArray s Int e -> ST s ()
memoizer f (I# n#) arr = memoizer' 0# where
memoizer' i# = let i = I# i#; write = unsafeWrite arr i (f i) in if i# ==# n# then write else memoizer' (i# +# 1#) >> write
listLookerUpper :: (forall s . STArray s Int e -> ST s ()) -> Int -> (Int -> e)
listLookerUpper f n = pureUnsafeLookup $ runST $ newArray_ (0, n1) >>= \arr -> f arr >> unsafeFreeze arr
stInit :: ST s ()
stInit = return ()
data Acc e = A Int# e
listLookup' :: Int -> [e] -> (Int -> e)
listLookup' n@(I# n#) l = listLookerUpper
(\ arr -> case foldr (acc arr) (A n# stInit) l of A _ ans -> ans) n where
acc arr x (A i# m) = let j# = i# -# 1# in A j# (unsafeWrite arr (I# j#) x >> m)