module Data.RangeMin.Internal.HandyArray (Producer, unsafeLookup, asPureArray, mListArray, mListUArray, mFuncArray, mFuncUArray, listMArray, listMUArray, listMArray', listMUArray', funcMArray, funcMUArray, MutArr(newArr, writeArr, readArr, lookup), MArr, MUArr, asMArr, asMUArr, mLook, muLook) where
import Data.RangeMin.Internal.HandyList
import Control.Monad
import Data.Array.Base
import Data.Array.IArray(Array)
import GHC.Arr(Ix(..))
import GHC.Prim
import GHC.Exts(Int(..))
import GHC.ST
import Control.Monad.State.Strict
import Control.Monad.Reader
import Data.Monoid
import Foreign.Storable(Storable(sizeOf))
import Prelude hiding (lookup)
type Producer m e = forall acc . (e -> acc -> m acc) -> acc -> m acc
type IA a s = StateT Int (Reader (a s)) (STBlank s)
data MArr e s = MArr Int# !(MutableArray# s e)
data MUArr s = MUArr Int# !(MutableByteArray# s)
type STBlank s = State# s -> State# s
boxIn :: (Int# -> e) -> Int -> e
boxIn f (I# i) = f i
blankIA :: IA a s
blankIA = return mempty
fromBlank :: STBlank s -> ST s ()
fromBlank m = ST $ \ s -> (# m s, () #)
instance Monoid (STBlank s) where
mempty s = s
mappend f g s = f (g s)
class MutArr a e | a -> e where
newArr :: Int -> ST s (a s)
readArr :: a s -> Int -> ST s e
write :: a s -> Int -> e -> STBlank s
writeArr :: a s -> Int -> e -> ST s ()
lookup :: a s -> ST s (Int# -> e)
writeArr arr !i x = fromBlank $ write arr i x
instance MutArr (MArr e) e where
newArr (I# n#) = ST $ \ s -> case newArray# n# (error "Undefined element") s of
(# s', arr# #) -> (# s', MArr n# arr# #)
readArr (MArr n# arr#) (I# i#) = ST $ readArray# arr# i#
write (MArr n# arr#) (I# i#) = writeArray# arr# i#
lookup (MArr n# arr#) = ST $ \ s -> case unsafeFreezeArray# arr# s of
(# s', iArr# #) -> (# s', \ i# -> case indexArray# iArr# i# of (# x #) -> x #)
instance MutArr MUArr Int where
newArr (I# n#) = ST $ \ s -> case newByteArray# (n# *# intSize#) s of
(# s', arr# #) -> (# s', MUArr n# arr# #)
where intSize# = case sizeOf (1 :: Int) of I# i -> i
readArr (MUArr n# arr#) (I# i#) = ST $ \ s -> case readIntArray# arr# i# s of
(# s', x# #) -> (# s', I# x# #)
write (MUArr n# arr#) (I# i#) (I# x#) = writeIntArray# arr# i# x#
lookup (MUArr n# arr#) = ST $ \ s -> case unsafeFreezeByteArray# arr# s of
(# s', iArr# #) -> (# s', \ i# -> I# (indexIntArray# iArr# i#) #)
asPureArray :: Ix i => Array i e -> Array i e
asPureArray = id
asMArr :: MArr e s -> MArr e s
asMArr = id
asMUArr :: MUArr s -> MUArr s
asMUArr = id
decr :: (Monad m, MonadState Int m) => m Int
decr = modify (subtract 1) >> get
extractor :: ST s e -> (e -> STBlank s) -> STBlank s
extractor (ST k) f s = case k s of (# s', x #) -> f x s'
acc :: MutArr a e => e -> IA a s -> IA a s
acc x ia = do m <- ia
!arr <- ask
!j <- decr
return (m `mappend` write arr j x)
mAcc :: MutArr a e => ST s e -> IA a s -> IA a s
mAcc x ia = do m <- ia
!j <- decr
!arr <- ask
return (m `mappend` extractor x (write arr j))
accF :: MutArr a e => a s -> (Int -> e) -> Int -> STBlank s
accF arr f !n = foldr (mappend . acc') mempty (zeroEft (n1)) where
acc' !i = write arr i (f i)
mAccF :: MutArr a e => a s -> (Int -> ST s e) -> Int -> STBlank s
mAccF arr f !n = foldr (mappend . mAcc') mempty (zeroEft (n1)) where
mAcc' !i = extractor (f i) (write arr i)
unboxedLookup :: IArray UArray e => UArray Int e -> (Int -> e)
unboxedLookup arr = unsafeAt $! arr
mLook :: MArr e s -> ST s (Int -> e)
mLook = liftM boxIn . lookup
muLook :: MUArr s -> ST s (Int -> Int)
muLook = liftM boxIn . lookup
runArr :: MutArr a e => Int -> (a s -> STBlank s) -> ST s (a s)
runArr !n f = do !arr <- newArr n
fromBlank $ f arr
return arr
runIA :: MutArr a e => Int -> IA a s -> ST s (a s)
runIA !n m = runArr n $ runReader $ evalStateT m n
mListArray :: Int -> [e] -> ST s (Int -> e)
mListArray n l = (runIA n $ foldr acc blankIA l) >>= mLook
mListUArray :: Int -> [Int] -> ST s (Int -> Int)
mListUArray n l = (runIA n $ foldr acc blankIA l) >>= muLook
mFuncArray :: Int -> (Int -> e) -> ST s (Int -> e)
mFuncArray n f = mFuncArr n f >>= mLook
mFuncUArray :: Int -> (Int -> Int) -> ST s (Int -> Int)
mFuncUArray n f = mFuncArr n f >>= muLook
mFuncArr :: MutArr a e => Int -> (Int -> e) -> ST s (a s)
mFuncArr !n f = runArr n (\ arr -> accF arr f n)
listMArray :: Int -> [ST s e] -> ST s (Int -> e)
listMArray n l = (runIA n $ foldr mAcc blankIA l) >>= mLook
listMUArray :: Int -> [ST s Int] -> ST s (Int -> Int)
listMUArray n l = (runIA n $ foldr mAcc blankIA l) >>= muLook
listMArray' :: Int -> Producer (ST s) e -> ST s (Int -> e)
listMArray' n prod = listMArr' n prod >>= mLook
listMUArray' :: Int -> Producer (ST s) Int -> ST s (Int -> Int)
listMUArray' n prod = listMArr' n prod >>= muLook
listMArr' :: MutArr a e => Int -> Producer (ST s) e -> ST s (a s)
listMArr' !n prod = do arr <- newArr n
prod (\ x i -> let !j = i 1 in ST $ \ s -> (# write arr j x s, j #)) n
return arr
funcMArray :: Int -> (Int -> ST s e) -> ST s (Int -> e)
funcMArray n f = funcMArr n f >>= mLook
funcMUArray :: Int -> (Int -> ST s Int) -> ST s (Int -> Int)
funcMUArray n f = funcMArr n f >>= muLook
funcMArr :: MutArr a e => Int -> (Int -> ST s e) -> ST s (a s)
funcMArr !n f = runArr n (\ arr -> mAccF arr f n)
unsafeLookup :: (IArray a e, Ix i) => a i e -> i -> e
unsafeLookup arr@(bounds -> b) = unsafeAt arr . unsafeIndex b