1{-# LANGUAGE CPP, ExistentialQuantification, MagicHash, Rank2Types,
2 ScopedTypeVariables, UnboxedTuples #-}
4-- Module : Data.Text.Array
5-- Copyright : (c) Bryan O'Sullivan 2009
8-- Maintainer : bos@serpentine.com,
9-- Stability : experimental
10-- Portability : portable
12-- Packed, unboxed, heap-resident arrays. Suitable for performance
13-- critical use, both in terms of large data quantities and high
16-- This module is intended to be imported @qualified@, to avoid name
17-- clashes with "Prelude" functions, e.g.
19-- > import qualified Data.Text.Array as A
21-- The names in this module resemble those in the 'Data.Array' family
22-- of modules, but are shorter due to the assumption of qualifid
41#define BOUNDS_CHECKING
42-- This fugly hack is brought by GHC's apparent reluctance to deal
43-- with MagicHash and UnboxedTuples when inferring types. Eek!
44#define CHECK_BOUNDS(_func_,_len_,_k_) \
45if (_k_) < 0 || (_k_) >= (_len_) then error ("Data.Text.Array." ++ (_func_) ++ ": bounds error, offset " ++ show (_k_) ++ ", length " ++ show (_len_)) else
47#define CHECK_BOUNDS(_func_,_len_,_k_)
50#if defined(__GLASGOW_HASKELL__)
53import GHC.Base (ByteArray#, MutableByteArray#, Int(..), indexWord16Array#,
54 newByteArray#, readWord16Array#, unsafeCoerce#,
55 writeWord16Array#, (+#), (*#))
57import GHC.ST (ST(..), runST)
58import GHC.Word (Word16(..))
60#elif defined(__HUGS__)
62import Control.Exception (assert)
63import Hugs.ByteArray (ByteArray, MutableByteArray, readByteArray,
64 newMutableByteArray, readMutableByteArray,
65 unsafeFreezeMutableByteArray, writeMutableByteArray)
66import Foreign.Storable (Storable, sizeOf)
67import Hugs.ST (ST(..), runST)
70# error not implemented for this compiler
73import Data.Typeable (Typeable1(..), Typeable2(..), TyCon, mkTyCon, mkTyConApp)
74import Data.Word (Word16)
75import Prelude hiding (length, read)
79-- | Immutable array type.
81 {-# UNPACK #-} !Int -- length (in units of e, not bytes)
82#if defined(__GLASGOW_HASKELL__)
84#elif defined(__HUGS__)
88INSTANCE_TYPEABLE1(Array,arrayTc,"Array")
90-- | Mutable array type, for use in the ST monad.
91data MArray s e = MArray
92 {-# UNPACK #-} !Int -- length (in units of e, not bytes)
93#if defined(__GLASGOW_HASKELL__)
95#elif defined(__HUGS__)
99INSTANCE_TYPEABLE2(MArray,mArrayTc,"MArray")
101-- | Operations supported by all arrays.
103 -- | Return the length of an array.
106instance IArray (Array e) where
107 length (Array len _ba) = len
108 {-# INLINE length #-}
110instance IArray (MArray s e) where
111 length (MArray len _ba) = len
112 {-# INLINE length #-}
114check :: IArray a => String -> a -> Int -> (a -> Int -> b) -> b
116 | i >= 0 && i < length ary = f ary i
117 | otherwise = error ("Data.Array.Flat." ++ func ++ ": index out of bounds")
120-- | Operations supported by all elements that can be stored in
123 -- | Indicate how many bytes would be used for an array of the
125 bytesInArray :: Int -> e -> Int
126 -- | Unchecked read of an immutable array. May return garbage or
127 -- crash on an out-of-bounds access.
128 unsafeIndex :: Array e -> Int -> e
129 -- | Unchecked read of a mutable array. May return garbage or
130 -- crash on an out-of-bounds access.
131 unsafeRead :: MArray s e -> Int -> ST s e
132 -- | Unchecked write of a mutable array. May return garbage or
133 -- crash on an out-of-bounds access.
134 unsafeWrite :: MArray s e -> Int -> e -> ST s ()
136 -- | Read an immutable array. An invalid index results in a
138 index :: Array e -> Int -> e
139 index ary i = check "index" ary i unsafeIndex
142 -- | Read a mutable array. An invalid index results in a runtime
144 read :: Array e -> Int -> ST s e
145 read ary i = check "read" ary i read
148 -- | Write a mutable array. An invalid index results in a runtime
150 write :: Array e -> Int -> ST s e
151 write ary i = check "write" ary i write
154-- | Freeze a mutable array. Do not mutate the 'MArray' afterwards!
155unsafeFreeze :: MArray s e -> ST s (Array e)
157#if defined(__GLASGOW_HASKELL__)
159wORD16_SCALE :: Int# -> Int#
160wORD16_SCALE n# = scale# *# n# where I# scale# = SIZEOF_WORD16
162-- | Create an uninitialized mutable array.
163unsafeNew :: forall s e. Elt e => Int -> ST s (MArray s e)
164unsafeNew n = ST $ \s1# ->
165 case bytesInArray n (undefined :: e) of
167#if defined(BOUNDS_CHECKING)
168 if len < 0 then error (show ("unsafeNew",len)) else
170 case newByteArray# len# s1# of
171 (# s2#, marr# #) -> (# s2#, MArray n marr# #)
172{-# INLINE unsafeNew #-}
174unsafeFreeze (MArray len mba#) = ST $ \s# ->
175 (# s#, Array len (unsafeCoerce# mba#) #)
176{-# INLINE unsafeFreeze #-}
178-- | Create a mutable array, with its elements initialized with the
180new :: forall s e. Elt e => Int -> e -> ST s (MArray s e)
182#elif defined(__HUGS__)
184unsafeIndexArray :: Storable e => Array e -> Int -> e
185unsafeIndexArray (Array off len arr) i =
186 assert (i >= 0 && i < len) $ readByteArray arr (off + i)
188unsafeReadMArray :: Storable e => MArray s e -> Int -> ST s e
189unsafeReadMArray (MArray _len marr) i =
190 assert (i >= 0 && i < len) $ readMutableByteArray marr
192unsafeWriteMArray :: Storable e => MArray s e -> Int -> e -> ST s ()
193unsafeWriteMArray (MArray len marr) i =
194 assert (i >= 0 && i < len) $ writeMutableByteArray marr
196-- | Create an uninitialized mutable array.
197unsafeNew :: (Storable e) => Int -> ST s (MArray s e)
198unsafeNew n = new undefined
199 where new :: (Storable e) => e -> ST s (MArray s e)
201 marr <- newMutableByteArray (n * sizeOf unused)
202 return (MArray n marr)
204unsafeFreeze (MArray len mba) = do
205 ba <- unsafeFreezeMutableByteArray mba
206 return (Array 0 len ba)
208-- | Create a mutable array, with its elements initialized with the
210new :: (Storable e) => Int -> e -> ST s (MArray s e)
214 marr <- unsafeNew len
215 sequence_ [unsafeWrite marr i initVal | i <- [0..len-1]]
218instance Elt Word16 where
219#if defined(__GLASGOW_HASKELL__)
221 bytesInArray (I# i#) _ = I# (wORD16_SCALE i#)
222 {-# INLINE bytesInArray #-}
224 unsafeIndex (Array len ba#) i@(I# i#) =
225 CHECK_BOUNDS("unsafeIndex",len,i)
226 case indexWord16Array# ba# i# of r# -> (W16# r#)
227 {-# INLINE unsafeIndex #-}
229 unsafeRead (MArray len mba#) i@(I# i#) = ST $ \s# ->
230 CHECK_BOUNDS("unsafeRead",len,i)
231 case readWord16Array# mba# i# s# of
232 (# s2#, r# #) -> (# s2#, W16# r# #)
233 {-# INLINE unsafeRead #-}
235 unsafeWrite (MArray len marr#) i@(I# i#) (W16# e#) = ST $ \s1# ->
236 CHECK_BOUNDS("unsafeWrite",len,i)
237 case writeWord16Array# marr# i# e# s1# of
239 {-# INLINE unsafeWrite #-}
241#elif defined(__HUGS__)
243 bytesInArray n w = sizeOf w * n
244 unsafeIndex = unsafeIndexArray
245 unsafeRead = unsafeReadMArray
246 unsafeWrite = unsafeWriteMArray
250-- | An empty immutable array.
251empty :: Elt e => Array e
252empty = runST (unsafeNew 0 >>= unsafeFreeze)
254-- | Run an action in the ST monad and return an immutable array of
256run :: Elt e => (forall s. ST s (MArray s e)) -> Array e
257run k = runST (k >>= unsafeFreeze)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list