2 % (c) The AQUA Project, Glasgow University, 1997
4 \section[MutableArray]{The @MutableArray@ interface}
6 Mutable (byte)arrays interface, re-exports type types and operations
7 over them from @ArrBase@. Have to be used in conjunction with
13 MutableArray(..), -- not abstract
20 newArray, -- :: Ix ix => (ix,ix) -> elt -> ST s (MutableArray s ix elt)
26 newStablePtrArray, -- :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix)
28 boundsOfArray, -- :: Ix ix => MutableArray s ix elt -> (ix, ix)
29 boundsOfMutableByteArray, -- :: Ix ix => MutableByteArray s ix -> (ix, ix)
31 readArray, -- :: Ix ix => MutableArray s ix elt -> ix -> ST s elt
33 readCharArray, -- :: Ix ix => MutableByteArray s ix -> ix -> ST s Char
34 readIntArray, -- :: Ix ix => MutableByteArray s ix -> ix -> ST s Int
35 readAddrArray, -- :: Ix ix => MutableByteArray s ix -> ix -> ST s Addr
36 readFloatArray, -- :: Ix ix => MutableByteArray s ix -> ix -> ST s Float
37 readDoubleArray, -- :: Ix ix => MutableByteArray s ix -> ix -> ST s Double
38 readStablePtrArray, -- :: Ix ix => MutableByteArray s ix -> ix -> ST s (StablePtr a)
40 writeArray, -- :: Ix ix => MutableArray s ix elt -> ix -> elt -> ST s ()
41 writeCharArray, -- :: Ix ix => MutableByteArray s ix -> ix -> Char -> ST s ()
42 writeIntArray, -- :: Ix ix => MutableByteArray s ix -> ix -> Int -> ST s ()
43 writeAddrArray, -- :: Ix ix => MutableByteArray s ix -> ix -> Addr -> ST s ()
44 writeFloatArray, -- :: Ix ix => MutableByteArray s ix -> ix -> Float -> ST s ()
45 writeDoubleArray, -- :: Ix ix => MutableByteArray s ix -> ix -> Double -> ST s ()
46 writeStablePtrArray, -- :: Ix ix => MutableByteArray s ix -> ix -> StablePtr a -> ST s ()
48 freezeArray, -- :: Ix ix => MutableArray s ix elt -> ST s (Array ix elt)
49 freezeCharArray, -- :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
50 freezeIntArray, -- :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
51 freezeAddrArray, -- :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
52 freezeFloatArray, -- :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
53 freezeDoubleArray, -- :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
54 freezeStablePtrArray, -- :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
56 unsafeFreezeArray, -- :: Ix ix => MutableArray s ix elt -> ST s (Array ix elt)
57 unsafeFreezeByteArray, -- :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
59 thawArray, -- :: Ix ix => Array ix elt -> ST s (MutableArray s ix)
60 thawByteArray, -- :: Ix ix => ByteArray ix -> ST s (MutableByteArray s ix)
61 unsafeThawArray, -- :: Ix ix => Array ix elt -> ST s (MutableArray s ix)
62 unsafeThawByteArray, -- :: Ix ix => ByteArray ix -> ST s (MutableByteArray s ix)
64 -- the sizes are reported back are *in bytes*.
65 sizeofMutableByteArray, -- :: Ix ix => MutableByteArray s ix -> Int
67 readWord8Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Word8
68 readWord16Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Word16
69 readWord32Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Word32
70 readWord64Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Word64
72 writeWord8Array, -- :: Ix ix => MutableByteArray s ix -> Int -> Word8 -> IO ()
73 writeWord16Array, -- :: Ix ix => MutableByteArray s ix -> Int -> Word16 -> IO ()
74 writeWord32Array, -- :: Ix ix => MutableByteArray s ix -> Int -> Word32 -> IO ()
75 writeWord64Array, -- :: Ix ix => MutableByteArray s ix -> Int -> Word64 -> IO ()
77 readInt8Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Int8
78 readInt16Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Int16
79 readInt32Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Int32
80 readInt64Array, -- :: Ix ix => MutableByteArray s ix -> Int -> IO Int64
82 writeInt8Array, -- :: Ix ix => MutableByteArray s ix -> Int -> Int8 -> IO ()
83 writeInt16Array, -- :: Ix ix => MutableByteArray s ix -> Int -> Int16 -> IO ()
84 writeInt32Array, -- :: Ix ix => MutableByteArray s ix -> Int -> Int32 -> IO ()
85 writeInt64Array -- :: Ix ix => MutableByteArray s ix -> Int -> Int64 -> IO ()
104 Note: the absence of operations to read/write ForeignObjs to a mutable
105 array is not accidental; storing foreign objs in a mutable array is
109 sizeofMutableByteArray :: Ix ix => MutableByteArray s ix -> Int
110 sizeofMutableByteArray (MutableByteArray _ arr#) =
111 case (sizeofMutableByteArray# arr#) of
117 newStablePtrArray :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix)
118 newStablePtrArray ixs = ST $ \ s# ->
119 case rangeSize ixs of { I# n# ->
120 case (newStablePtrArray# n# s#) of { (# s2#, barr# #) ->
121 (# s2#, (MutableByteArray ixs barr#) #) }}
123 readStablePtrArray :: Ix ix => MutableByteArray s ix -> ix -> ST s (StablePtr a)
124 readStablePtrArray (MutableByteArray ixs barr#) n = ST $ \ s# ->
125 case (index ixs n) of { I# n# ->
126 case readStablePtrArray# barr# n# s# of { (# s2#, r# #) ->
127 (# s2# , (StablePtr r#) #) }}
129 writeStablePtrArray :: Ix ix => MutableByteArray s ix -> ix -> StablePtr a -> ST s ()
130 writeStablePtrArray (MutableByteArray ixs barr#) n (StablePtr sp#) = ST $ \ s# ->
131 case (index ixs n) of { I# n# ->
132 case writeStablePtrArray# barr# n# sp# s# of { s2# ->
135 freezeStablePtrArray :: Ix ix => MutableByteArray s ix -> ST s (ByteArray ix)
136 freezeStablePtrArray (MutableByteArray ixs arr#) = ST $ \ s# ->
137 case rangeSize ixs of { I# n# ->
138 case freeze arr# n# s# of { (# s2# , frozen# #) ->
139 (# s2# , ByteArray ixs frozen# #) }}
141 freeze :: MutableByteArray# s -- the thing
142 -> Int# -- size of thing to be frozen
143 -> State# s -- the Universe and everything
144 -> (# State# s, ByteArray# #)
147 = case (newStablePtrArray# n# s#) of { (# s2# , newarr1# #) ->
148 case copy 0# n# arr1# newarr1# s2# of { (# s3# , newarr2# #) ->
149 unsafeFreezeByteArray# newarr2# s3#
153 -> MutableByteArray# s -> MutableByteArray# s
155 -> (# State# s , MutableByteArray# s #)
157 copy cur# end# from# to# st#
161 = case (readStablePtrArray# from# cur# st#) of { (# s1# , ele #) ->
162 case (writeStablePtrArray# to# cur# ele s1#) of { s2# ->
163 copy (cur# +# 1#) end# from# to# s2#
169 Reminder: indexing an array at some base type is done in units
170 of the size of the type being; *not* in bytes.
173 readWord8Array :: MutableByteArray RealWorld Int -> Int -> IO Word8
174 readWord16Array :: MutableByteArray RealWorld Int -> Int -> IO Word16
175 readWord32Array :: MutableByteArray RealWorld Int -> Int -> IO Word32
176 readWord64Array :: MutableByteArray RealWorld Int -> Int -> IO Word64
178 readWord8Array (MutableByteArray ixs arr#) n@(I# n#) =
179 case sizeofMutableByteArray# arr# of
181 | n# ># (bytes# -# 1#) -> ioError (userError ("readWord8Array: index out of bounds "++show n))
182 | otherwise -> IO $ \ s# ->
183 case readCharArray# arr# n# s# of
184 (# s2# , r# #) -> (# s2# , intToWord8 (I# (ord# r#)) #)
186 readWord16Array (MutableByteArray ixs arr#) n@(I# n#) =
187 case sizeofMutableByteArray# arr# of
189 | n# ># (bytes# `quotInt#` 2# -# 1#) -> ioError (userError ("readWord16Array: index out of bounds "++show n))
190 | otherwise -> IO $ \ s# ->
191 case readWordArray# arr# (n# `quotInt#` 2#) s# of
193 case n# `remInt#` 2# of
194 0# -> (# s2# , wordToWord16 (W# w#) #) -- the double byte hides in the lower half of the wrd.
195 1# -> (# s2# , wordToWord16 (W# (shiftRL# w# 16#)) #) -- take the upper 16 bits.
197 readWord32Array (MutableByteArray ixs arr#) n@(I# n#) =
198 case sizeofMutableByteArray# arr# of
200 | n# ># (bytes# `quotInt#` 4# -# 1#) -> ioError (userError ("readWord32Array: index out of bounds "++show n))
201 | otherwise -> IO $ \ s# ->
202 case readWordArray# arr# n# s# of
203 (# s2# , w# #) -> (# s2# , wordToWord32 (W# w#) #)
205 readWord64Array mb n = do
206 l <- readWord32Array mb (2*n)
207 h <- readWord32Array mb (2*n + 1)
208 #ifdef WORDS_BIGENDIAN
209 return ( word32ToWord64 h + word32ToWord64 l * word32ToWord64 (maxBound::Word32))
211 return ( word32ToWord64 l + word32ToWord64 h * word32ToWord64 (maxBound::Word32))
214 writeWord8Array :: MutableByteArray RealWorld Int -> Int -> Word8 -> IO ()
215 writeWord16Array :: MutableByteArray RealWorld Int -> Int -> Word16 -> IO ()
216 writeWord32Array :: MutableByteArray RealWorld Int -> Int -> Word32 -> IO ()
217 writeWord64Array :: MutableByteArray RealWorld Int -> Int -> Word64 -> IO ()
219 writeWord8Array (MutableByteArray ixs arr#) n@(I# n#) w =
220 case sizeofMutableByteArray# arr# of
222 | n# ># (bytes# -# 1#) -> ioError (userError ("writeWord8Array: index out of bounds "++show n))
223 | otherwise -> IO $ \ s# ->
224 case writeCharArray# arr# n# (chr# (word2Int# (word8ToWord# w))) s# of
225 s2# -> (# s2# , () #)
227 writeWord16Array (MutableByteArray ixs arr#) n@(I# n#) w =
228 case sizeofMutableByteArray# arr# of
230 | n# ># (bytes# `quotInt#` 2# -# 1#) -> ioError (userError ("writeWord16Array: index out of bounds "++show n))
231 | otherwise -> IO $ \ s# ->
232 case readWordArray# arr# (n# `quotInt#` 2#) s# of
234 case writeWordArray# arr# (n# `quotInt#` 2#) (w# `or#` (v# `and#` mask )) s2# of
235 s3# -> (# s3# , () #)
238 let w' = word16ToWord# w in
239 case n# `remInt#` 2# of
244 case n# `remInt#` 2# of
245 0# -> case ``0xffff0000'' of W# x -> x -- writing to the lower half of the word.
246 1# -> int2Word# 0x0000ffff#
248 writeWord32Array (MutableByteArray ixs arr#) n@(I# n#) w =
249 case sizeofMutableByteArray# arr# of
251 | n# ># (bytes# `quotInt#` 4# -# 1#) -> ioError (userError ("writeWord32Array: index out of bounds "++show n))
252 | otherwise -> IO $ \ s# ->
253 case writeWordArray# arr# n# w# s# of
254 s2# -> (# s2# , () #)
258 writeWord64Array mb n w = do
259 #ifdef WORDS_BIGENDIAN
260 writeWord32Array mb (n*2) h
261 writeWord32Array mb (n*2+1) l
263 writeWord32Array mb (n*2) l
264 writeWord32Array mb (n*2+1) h
267 h = word64ToWord32 h'
268 l = word64ToWord32 l'
269 (h',l') = w `divMod` (word32ToWord64 (maxBound::Word32) + 1)
275 readInt8Array :: MutableByteArray RealWorld Int -> Int -> IO Int8
276 readInt16Array :: MutableByteArray RealWorld Int -> Int -> IO Int16
277 readInt32Array :: MutableByteArray RealWorld Int -> Int -> IO Int32
278 readInt64Array :: MutableByteArray RealWorld Int -> Int -> IO Int64
280 readInt8Array (MutableByteArray ixs arr#) n@(I# n#) =
281 case sizeofMutableByteArray# arr# of
283 | n# ># (bytes# -# 1#) -> ioError (userError ("readInt8Array: index out of bounds "++show n))
284 | otherwise -> IO $ \ s# ->
285 case readCharArray# arr# n# s# of
286 (# s2# , r# #) -> (# s2# , intToInt8 (I# (ord# r#)) #)
288 readInt16Array (MutableByteArray ixs arr#) n@(I# n#) =
289 case sizeofMutableByteArray# arr# of
291 | n# ># (bytes# `quotInt#` 2# -# 1#) -> ioError (userError ("readInt16Array: index out of bounds "++show n))
292 | otherwise -> IO $ \ s# ->
293 case readIntArray# arr# (n# `quotInt#` 2#) s# of
295 case n# `remInt#` 2# of
296 0# -> (# s2# , intToInt16 (I# i#) #)
297 1# -> (# s2# , intToInt16 (I# i#) #) -- FIXME.
299 readInt32Array (MutableByteArray ixs arr#) n@(I# n#) =
300 case sizeofMutableByteArray# arr# of
302 | n# ># (bytes# `quotInt#` 4# -# 1#) -> ioError (userError ("readInt32Array: index out of bounds "++show n))
303 | otherwise -> IO $ \ s# ->
304 case readIntArray# arr# n# s# of
305 (# s2# , i# #) -> (# s2# , intToInt32 (I# i#) #)
307 readInt64Array mb n = do
308 l <- readInt32Array mb (2*n)
309 h <- readInt32Array mb (2*n + 1)
310 #ifdef WORDS_BIGENDIAN
311 return ( int32ToInt64 h + int32ToInt64 l * int32ToInt64 (maxBound::Int32))
313 return ( int32ToInt64 l + int32ToInt64 h * int32ToInt64 (maxBound::Int32))
316 writeInt8Array :: MutableByteArray RealWorld Int -> Int -> Int8 -> IO ()
317 writeInt16Array :: MutableByteArray RealWorld Int -> Int -> Int16 -> IO ()
318 writeInt32Array :: MutableByteArray RealWorld Int -> Int -> Int32 -> IO ()
319 writeInt64Array :: MutableByteArray RealWorld Int -> Int -> Int64 -> IO ()
321 writeInt8Array (MutableByteArray ixs arr#) n@(I# n#) i =
322 case sizeofMutableByteArray# arr# of
324 | n# ># (bytes# -# 1#) -> ioError (userError ("writeInt8Array: index out of bounds "++show n))
325 | otherwise -> IO $ \ s# ->
326 case writeCharArray# arr# n# ch s# of
327 s2# -> (# s2# , () #)
329 ch = chr# (int8ToInt# i)
331 writeInt16Array (MutableByteArray ixs arr#) n@(I# n#) i =
332 case sizeofMutableByteArray# arr# of
334 | n# ># (bytes# `quotInt#` 2# -# 1#) -> ioError (userError ("writeInt16Array: index out of bounds "++show n))
335 | otherwise -> IO $ \ s# ->
336 case readIntArray# arr# (n# `quotInt#` 2#) s# of
338 let w' = word2Int# (int2Word# i# `or#` (int2Word# v# `and#` mask))
340 case writeIntArray# arr# (n# `quotInt#` 2#) w' s# of
341 s2# -> (# s2# , () #)
344 let i' = int16ToInt# i in
345 case n# `remInt#` 2# of
347 1# -> iShiftL# i' 16#
350 case n# `remInt#` 2# of
351 0# -> case ``0xffff0000'' of W# x -> x -- writing to the lower half of the word.
352 1# -> int2Word# 0x0000ffff#
354 writeInt32Array (MutableByteArray ixs arr#) n@(I# n#) i =
355 case sizeofMutableByteArray# arr# of
357 | n# ># (bytes# `quotInt#` 4# -# 1#) -> ioError (userError ("writeInt32Array: index out of bounds "++show n))
358 | otherwise -> IO $ \ s# ->
359 case writeIntArray# arr# n# i# s# of
360 s2# -> (# s2# , () #)
364 writeInt64Array mb n w = do
365 #ifdef WORDS_BIGENDIAN
366 writeInt32Array mb (n*2) h
367 writeInt32Array mb (n*2+1) l
369 writeInt32Array mb (n*2) l
370 writeInt32Array mb (n*2+1) h
375 (h',l') = w `divMod` (int32ToInt64 (maxBound::Int32) * 2 - 1)
380 {-# SPECIALIZE boundsOfMutableByteArray :: MutableByteArray s Int -> IPr #-}
381 boundsOfMutableByteArray :: Ix ix => MutableByteArray s ix -> (ix, ix)
382 boundsOfMutableByteArray (MutableByteArray ixs _) = ixs
387 thawByteArray :: Ix ix => ByteArray ix -> ST s (MutableByteArray s ix)
388 thawByteArray (ByteArray ixs barr#) =
390 The implementation is made more complex by the
391 fact that the indexes are in units of whatever
392 base types that's stored in the byte array.
394 case (sizeofByteArray# barr#) of
396 marr <- newCharArray (0,I# i#)
397 mapM_ (\ idx@(I# idx#) ->
398 writeCharArray marr idx (C# (indexCharArray# barr# idx#)))
400 let (MutableByteArray _ arr#) = marr
401 return (MutableByteArray ixs arr#)
404 in-place conversion of immutable arrays to mutable ones places
405 a proof obligation on the user: no other parts of your code can
406 have a reference to the array at the point where you unsafely
407 thaw it (and, subsequently mutate it, I suspect.)
409 unsafeThawByteArray :: Ix ix => ByteArray ix -> ST s (MutableByteArray s ix)
410 unsafeThawByteArray (ByteArray ixs barr#) = ST $ \ s# ->
411 case unsafeThawByteArray# barr# s# of
412 (# s2#, arr# #) -> (# s2#, MutableByteArray ixs arr# #)