ArrayRef-0.1.2: Data/ArrayBZ/Internals/Boxed.hs
{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances,
MultiParamTypeClasses, FlexibleContexts #-}
{- |
Module : Data.ArrayBZ.Internals.Boxed
Copyright : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin
License : BSD3
Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>
Stability : experimental
Portability: GHC/Hugs
Boxed arrays
-}
module Data.ArrayBZ.Internals.Boxed
#ifdef __HUGS__
( -- * Types
Array,
IOArray,
STArray,
-- * Freeze/thaw operations
freezeIOArray,
thawIOArray,
unsafeFreezeIOArray,
freezeSTArray,
thawSTArray,
unsafeFreezeSTArray,
)
#endif
where
import Control.Monad.ST ( ST, runST )
import Control.Monad.ST.Lazy ( strictToLazyST )
import qualified Control.Monad.ST.Lazy as Lazy (ST)
import Data.Ix
import Data.Typeable
#include "Typeable.h"
import Data.ArrayBZ.Internals.IArray
import Data.ArrayBZ.Internals.MArray
#ifdef __HUGS__
-- ---------------------------------------------------------------------------
-- Hugs primitives are higher-level than GHC/NHC's
-- ---------------------------------------------------------------------------
import Hugs.Array as Arr
import Hugs.IOArray
import Hugs.ST
-----------------------------------------------------------------------------
-- Normal polymorphic arrays
instance HasBounds Array where
bounds = Arr.bounds
instance IArray Array e where
unsafeArray = Arr.unsafeArray
unsafeAt = Arr.unsafeAt
unsafeReplace = Arr.unsafeReplace
unsafeAccum = Arr.unsafeAccum
unsafeAccumArray = Arr.unsafeAccumArray
-----------------------------------------------------------------------------
-- | Instance declarations for 'IOArray's
instance HasBounds IOArray where
bounds = boundsIOArray
instance HasMutableBounds IOArray IO where
getBounds = return . boundsIOArray
instance MArray IOArray e IO where
newArray = newIOArray
unsafeRead = unsafeReadIOArray
unsafeWrite = unsafeWriteIOArray
-----------------------------------------------------------------------------
-- Polymorphic non-strict mutable arrays (ST monad)
instance HasBounds (STArray s) where
bounds = boundsSTArray
instance HasMutableBounds (STArray s) (ST s) where
getBounds = return . boundsSTArray
instance MArray (STArray s) e (ST s) where
newArray = newSTArray
unsafeRead = unsafeReadSTArray
unsafeWrite = unsafeWriteSTArray
#else
-- ---------------------------------------------------------------------------
-- Non-Hugs implementation
-- ---------------------------------------------------------------------------
import Control.Monad.STorIO
import GHC.ArrBZ
-- ---------------------------------------------------------------------------
-- | Boxed mutable arrays
data BoxedMutableArray s i e = BMA !i !i !(MVec s e)
instance HasBounds (BoxedMutableArray s) where
{-# INLINE bounds #-}
bounds (BMA l u _) = (l,u)
instance (STorIO m s) => HasMutableBounds (BoxedMutableArray s) m where
{-# INLINE getBounds #-}
getBounds (BMA l u _) = return (l,u)
instance (STorIO m s) => MArray (BoxedMutableArray s) e m where
newArray (l,u) initial = do arr <- allocBoxed (rangeSize (l,u)) initial
return (BMA l u arr)
{-# INLINE unsafeRead #-}
unsafeRead (BMA _ _ arr) = readBoxed arr
{-# INLINE unsafeWrite #-}
unsafeWrite (BMA _ _ arr) = writeBoxed arr
-- ---------------------------------------------------------------------------
-- | Boxed mutable arrays in ST monad
type STArray = BoxedMutableArray
-- ---------------------------------------------------------------------------
-- STArray also works in Lazy ST monad
instance MArray (STArray s) e (Lazy.ST s) where
{-# INLINE newArray #-}
newArray (l,u) initial = strictToLazyST (newArray (l,u) initial)
{-# INLINE unsafeRead #-}
unsafeRead arr i = strictToLazyST (unsafeRead arr i)
{-# INLINE unsafeWrite #-}
unsafeWrite arr i e = strictToLazyST (unsafeWrite arr i e)
-- ---------------------------------------------------------------------------
-- | Boxed mutable arrays in IO monad
type IOArray = IOSpecific3 BoxedMutableArray
-- ---------------------------------------------------------------------------
-- | Boxed immutable arrays
data Array i e = BA !i !i !(Vec e)
instance HasBounds Array where
{-# INLINE bounds #-}
bounds (BA l u _) = (l,u)
instance IArray Array e where
{-# INLINE unsafeArray #-}
-- Create new array filled with (i,e) values
unsafeArray lu ies = runST (withNewArray lu arrEleBottom (doReplace ies))
{-# INLINE unsafeAt #-}
unsafeAt (BA _ _ arr) = indexBoxed arr
{-# INLINE unsafeReplace #-}
-- Make a copy of array and perform (i,e) replacements
unsafeReplace arr ies = runST (withArrayCopy arr (doReplace ies))
{-# INLINE unsafeAccum #-}
-- Make a copy of array and perform (i,e) accumulation in new array
unsafeAccum f arr ies = runST (withArrayCopy arr (doAccum f ies))
{-# INLINE unsafeAccumArray #-}
-- Create new array accumulating (i,e) values
unsafeAccumArray f initial lu ies = runST (withNewArray lu initial (doAccum f ies))
-- Implementation helper functions -------------
-- Create new array and perform given action on it before freezing
withNewArray :: (STorIO t t2,
Ix i,
MArray (BoxedMutableArray t2) e t) =>
(i, i)
-> e
-> (BoxedMutableArray t2 i e -> t t1)
-> t (Array i e)
withNewArray lu initial action = do
marr <- newArray lu initial
action marr
unsafeFreezeBA marr
-- Make a copy of array and perform given action on it before freezing
withArrayCopy :: (Ix t, STorIO t2 s) =>
Array t t1
-> (BoxedMutableArray s t t1 -> t2 t3)
-> t2 (Array t t1)
withArrayCopy arr action = do
marr <- thawBA arr
action marr
unsafeFreezeBA marr
-- Perform (i,e) replaces in mutable array
doReplace :: (Ix i, MArray a e t) => [(Int, e)] -> a i e -> t ()
doReplace ies marr = do
sequence_ [unsafeWrite marr i e | (i, e) <- ies]
-- Accumulate (i,e) values in mutable array
doAccum :: (Ix i, MArray a t1 t2) => (t1 -> t -> t1) -> [(Int, t)] -> a i t1 -> t2 ()
doAccum f ies marr = do
sequence_ [do old <- unsafeRead marr i
unsafeWrite marr i (f old new)
| (i, new) <- ies]
-- Mutable->immutable array conversion which takes a copy of contents
freezeBA :: (STorIO t3 t, Ix t1) => BoxedMutableArray t t1 t2 -> t3 (Array t1 t2)
freezeBA ua@(BMA l u marr) = do
arr <- freezeBoxed marr (sizeOfBA ua) arrEleBottom
return (BA l u arr)
-- Immutable->mutable array conversion which takes a copy of contents
thawBA :: (STorIO t2 s, Ix t) => Array t t1 -> t2 (BoxedMutableArray s t t1)
thawBA ua@(BA l u arr) = do
marr <- thawBoxed arr (sizeOfBA ua) arrEleBottom
return (BMA l u marr)
-- On-the-place mutable->immutable array conversion
unsafeFreezeBA :: (STorIO t3 t1) => BoxedMutableArray t1 t t2 -> t3 (Array t t2)
unsafeFreezeBA (BMA l u marr) = do
arr <- unsafeFreezeBoxed marr
return (BA l u arr)
-- On-the-place immutable->mutable array conversion
unsafeThawBA :: (STorIO t2 s) => Array t t1 -> t2 (BoxedMutableArray s t t1)
unsafeThawBA (BA l u arr) = do
marr <- unsafeThawBoxed arr
return (BMA l u marr)
-- | Number of array elements
sizeOfBA :: (Ix a1, HasBounds a) => a a1 e -> Int
sizeOfBA arr = rangeSize (bounds arr)
-- ---------------------------------------------------------------------------
-- | Freeze/thaw rules for IOArray
freezeIOArray :: (Ix i) => IOArray i e -> IO (Array i e)
thawIOArray :: (Ix i) => Array i e -> IO (IOArray i e)
unsafeFreezeIOArray :: (Ix i) => IOArray i e -> IO (Array i e)
unsafeThawIOArray :: (Ix i) => Array i e -> IO (IOArray i e)
freezeIOArray = freezeBA
thawIOArray = thawBA
unsafeFreezeIOArray = unsafeFreezeBA
unsafeThawIOArray = unsafeThawBA
{-# RULES
"freeze/IOArray" freeze = freezeIOArray
"thaw/IOArray" thaw = thawIOArray
"unsafeFreeze/IOArray" unsafeFreeze = unsafeFreezeIOArray
"unsafeThaw/IOArray" unsafeThaw = unsafeThawIOArray
#-}
-- ---------------------------------------------------------------------------
-- | Freeze/thaw rules for STArray
freezeSTArray :: (Ix i) => STArray s i e -> ST s (Array i e)
thawSTArray :: (Ix i) => Array i e -> ST s (STArray s i e)
unsafeFreezeSTArray :: (Ix i) => STArray s i e -> ST s (Array i e)
unsafeThawSTArray :: (Ix i) => Array i e -> ST s (STArray s i e)
freezeSTArray = freezeBA
thawSTArray = thawBA
unsafeFreezeSTArray = unsafeFreezeBA
unsafeThawSTArray = unsafeThawBA
{-# RULES
"freeze/STArray" freeze = freezeSTArray
"thaw/STArray" thaw = thawSTArray
"unsafeFreeze/STArray" unsafeFreeze = unsafeFreezeSTArray
"unsafeThaw/STArray" unsafeThaw = unsafeThawSTArray
#-}
-- ---------------------------------------------------------------------------
-- | Instances
instance (Ix i, Show i, Show e) => Show (Array i e) where
showsPrec = showsIArray
instance (Ix i, Eq i, Eq e) => Eq (Array i e) where
(==) = eqIArray
instance (Ix i, Ord i, Ord e) => Ord (Array i e) where
compare = cmpIArray
#endif
iOArrayTc :: TyCon
INSTANCE_TYPEABLE2(IOArray,iOArrayTc,"IOArray")
stArrayTc :: TyCon
INSTANCE_TYPEABLE3(STArray,stArrayTc,"STArray")