1 % -----------------------------------------------------------------------------
2 % $Id: PrelArr.lhs,v 1.23 2000/06/30 13:39:35 simonmar Exp $
4 % (c) The University of Glasgow, 1994-2000
7 \section[PrelArr]{Module @PrelArr@}
9 Array implementation, @PrelArr@ exports the basic array
12 For byte-arrays see @PrelByteArr@.
15 {-# OPTIONS -fno-implicit-prelude #-}
19 import {-# SOURCE #-} PrelErr ( error )
20 import PrelList (foldl)
35 %*********************************************************
37 \subsection{The @Ix@ class}
39 %*********************************************************
42 class (Ord a) => Ix a where
44 index, unsafeIndex :: (a,a) -> a -> Int
45 inRange :: (a,a) -> a -> Bool
47 -- Must specify one of index, unsafeIndex
48 index b i | inRange b i = unsafeIndex b i
49 | otherwise = error "Error in array index"
50 unsafeIndex b i = index b i
54 %*********************************************************
56 \subsection{Instances of @Ix@}
58 %*********************************************************
61 -- abstract these errors from the relevant index functions so that
62 -- the guts of the function will be small enough to inline.
64 {-# NOINLINE indexError #-}
65 indexError :: Show a => (a,a) -> a -> String -> b
67 = error (showString "Ix{" . showString tp . showString "}.index: Index " .
68 showParen True (showsPrec 0 i) .
69 showString " out of range " $
70 showParen True (showsPrec 0 rng) "")
72 ----------------------------------------------------------------------
73 instance Ix Char where
77 {-# INLINE unsafeIndex #-}
78 unsafeIndex (m,_n) i = fromEnum i - fromEnum m
80 index b i | inRange b i = unsafeIndex b i
81 | otherwise = indexError b i "Char"
83 inRange (m,n) i = m <= i && i <= n
85 ----------------------------------------------------------------------
88 -- The INLINE stops the build in the RHS from getting inlined,
89 -- so that callers can fuse with the result of range
92 {-# INLINE unsafeIndex #-}
93 unsafeIndex (m,_n) i = i - m
95 index b i | inRange b i = unsafeIndex b i
96 | otherwise = indexError b i "Int"
98 {-# INLINE inRange #-}
99 inRange (I# m,I# n) (I# i) = m <=# i && i <=# n
101 ----------------------------------------------------------------------
102 instance Ix Integer where
106 {-# INLINE unsafeIndex #-}
107 unsafeIndex (m,_n) i = fromInteger (i - m)
109 index b i | inRange b i = unsafeIndex b i
110 | otherwise = indexError b i "Integer"
112 inRange (m,n) i = m <= i && i <= n
115 ----------------------------------------------------------------------
116 instance Ix Bool where -- as derived
120 {-# INLINE unsafeIndex #-}
121 unsafeIndex (l,_) i = fromEnum i - fromEnum l
123 index b i | inRange b i = unsafeIndex b i
124 | otherwise = indexError b i "Bool"
126 inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
128 ----------------------------------------------------------------------
129 instance Ix Ordering where -- as derived
133 {-# INLINE unsafeIndex #-}
134 unsafeIndex (l,_) i = fromEnum i - fromEnum l
136 index b i | inRange b i = unsafeIndex b i
137 | otherwise = indexError b i "Ordering"
139 inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
141 ----------------------------------------------------------------------
144 range ((), ()) = [()]
145 {-# INLINE unsafeIndex #-}
146 unsafeIndex ((), ()) () = 0
147 {-# INLINE inRange #-}
148 inRange ((), ()) () = True
150 index b i = unsafeIndex b i
153 ----------------------------------------------------------------------
154 instance (Ix a, Ix b) => Ix (a, b) where -- as derived
155 {-# SPECIALISE instance Ix (Int,Int) #-}
158 range ((l1,l2),(u1,u2)) =
159 [ (i1,i2) | i1 <- range (l1,u1), i2 <- range (l2,u2) ]
161 {- INLINE unsafeIndex #-}
162 unsafeIndex ((l1,l2),(u1,u2)) (i1,i2) =
163 unsafeIndex (l1,u1) i1 * unsafeRangeSize (l2,u2) + unsafeIndex (l2,u2) i2
165 {- INLINE inRange #-}
166 inRange ((l1,l2),(u1,u2)) (i1,i2) =
167 inRange (l1,u1) i1 && inRange (l2,u2) i2
169 -- Default method for index
171 ----------------------------------------------------------------------
172 instance (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3) where
173 {-# SPECIALISE instance Ix (Int,Int,Int) #-}
175 range ((l1,l2,l3),(u1,u2,u3)) =
176 [(i1,i2,i3) | i1 <- range (l1,u1),
180 unsafeIndex ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
181 unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
182 unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
183 unsafeIndex (l1,u1) i1))
185 inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
186 inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
189 -- Default method for index
191 ----------------------------------------------------------------------
192 instance (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4) where
193 range ((l1,l2,l3,l4),(u1,u2,u3,u4)) =
194 [(i1,i2,i3,i4) | i1 <- range (l1,u1),
199 unsafeIndex ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
200 unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
201 unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
202 unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
203 unsafeIndex (l1,u1) i1)))
205 inRange ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
206 inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
207 inRange (l3,u3) i3 && inRange (l4,u4) i4
209 -- Default method for index
211 instance (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5) where
212 range ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) =
213 [(i1,i2,i3,i4,i5) | i1 <- range (l1,u1),
219 unsafeIndex ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
220 unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (
221 unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
222 unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
223 unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
224 unsafeIndex (l1,u1) i1))))
226 inRange ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
227 inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
228 inRange (l3,u3) i3 && inRange (l4,u4) i4 &&
231 -- Default method for index
235 %********************************************************
237 \subsection{Size of @Ix@ interval}
239 %********************************************************
241 The @rangeSize@ operator returns the number of elements
242 in the range for an @Ix@ pair.
245 {-# SPECIALISE unsafeRangeSize :: (Int,Int) -> Int #-}
246 {-# SPECIALISE unsafeRangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
247 unsafeRangeSize :: (Ix a) => (a,a) -> Int
248 unsafeRangeSize b@(_l,h) = unsafeIndex b h + 1
250 {-# SPECIALISE rangeSize :: (Int,Int) -> Int #-}
251 {-# SPECIALISE rangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
252 rangeSize :: (Ix a) => (a,a) -> Int
253 rangeSize b@(_l,h) | inRange b h = unsafeIndex b h + 1
256 -- Note that the following is NOT right
257 -- rangeSize (l,h) | l <= h = index b h + 1
260 -- Because it might be the case that l<h, but the range
261 -- is nevertheless empty. Consider
263 -- Here l<h, but the second index ranges from 2..1 and
269 %*********************************************************
271 \subsection{The @Array@ types}
273 %*********************************************************
276 type IPr = (Int, Int)
278 data Ix ix => Array ix elt = Array ix ix (Array# elt)
279 data Ix ix => STArray s ix elt = STArray ix ix (MutableArray# s elt)
282 data STRef s a = STRef (MutVar# s a)
284 instance Eq (STRef s a) where
285 STRef v1# == STRef v2#
286 = sameMutVar# v1# v2#
288 -- just pointer equality on arrays:
289 instance Eq (STArray s ix elt) where
290 STArray _ _ arr1# == STArray _ _ arr2#
291 = sameMutableArray# arr1# arr2#
294 %*********************************************************
296 \subsection{Operations on mutable variables}
298 %*********************************************************
301 newSTRef :: a -> ST s (STRef s a)
302 readSTRef :: STRef s a -> ST s a
303 writeSTRef :: STRef s a -> a -> ST s ()
305 newSTRef init = ST $ \ s# ->
306 case (newMutVar# init s#) of { (# s2#, var# #) ->
307 (# s2#, STRef var# #) }
309 readSTRef (STRef var#) = ST $ \ s# -> readMutVar# var# s#
311 writeSTRef (STRef var#) val = ST $ \ s# ->
312 case writeMutVar# var# val s# of { s2# ->
316 %*********************************************************
318 \subsection{Operations on immutable arrays}
320 %*********************************************************
322 "array", "!" and "bounds" are basic; the rest can be defined in terms of them
325 bounds :: (Ix a) => Array a b -> (a,a)
326 {-# INLINE bounds #-}
327 bounds (Array l u _) = (l,u)
329 assocs :: (Ix a) => Array a b -> [(a,b)]
330 {-# INLINE assocs #-} -- Want to fuse the list comprehension
331 assocs a = [(i, a!i) | i <- indices a]
333 indices :: (Ix a) => Array a b -> [a]
334 {-# INLINE indices #-}
335 indices = range . bounds
337 {-# SPECIALISE amap :: (b -> c) -> Array Int b -> Array Int c #-}
338 amap :: (Ix a) => (b -> c) -> Array a b -> Array a c
339 amap f a = array b [(i, f (a!i)) | i <- range b]
342 {-# SPECIALISE (!) :: Array Int b -> Int -> b #-}
343 (!) :: (Ix a) => Array a b -> a -> b
345 = let n# = case (index (l,u) i) of { I# x -> x } -- index fails if out of range
347 case (indexArray# arr# n#) of
351 array :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
354 = case rangeSize ixs of { I# n ->
356 case newArray# n arrEleBottom s1 of { (# s2, marr #) ->
357 foldr (fill ixs marr) (done ixs marr) ivs s2
360 fill :: Ix ix => (ix,ix) -> MutableArray# s elt
361 -> (ix,elt) -> STRep s a -> STRep s a
363 fill ixs marr (i,v) next = \s1 -> case index ixs i of { I# n ->
364 case writeArray# marr n v s1 of { s2 ->
367 done :: Ix ix => (ix,ix) -> MutableArray# s elt
368 -> STRep s (Array ix elt)
370 done (l,u) marr = \s1 ->
371 case unsafeFreezeArray# marr s1 of { (# s2, arr #) ->
372 (# s2, Array l u arr #) }
375 arrEleBottom = error "(Array.!): undefined array element"
378 -----------------------------------------------------------------------
379 -- These also go better with magic: (//), accum, accumArray
380 -- *** NB *** We INLINE them all so that their foldr's get to the call site
382 (//) :: (Ix a) => Array a b -> [(a,b)] -> Array a b
386 -- copy the old array:
387 arr <- thawSTArray old_array
388 -- now write the new elements into the new array:
393 fill_it_in :: Ix ix => STArray s ix elt -> [(ix, elt)] -> ST s ()
394 {-# INLINE fill_it_in #-}
395 fill_it_in arr lst = foldr (fill_one_in arr) (return ()) lst
396 -- **** STRICT **** (but that's OK...)
398 fill_one_in arr (i, v) rst = writeSTArray arr i v >> rst
400 zap_with_f :: Ix ix => (elt -> elt2 -> elt) -> STArray s ix elt -> [(ix,elt2)] -> ST s ()
401 -- zap_with_f: reads an elem out first, then uses "f" on that and the new value
402 {-# INLINE zap_with_f #-}
405 = foldr (zap_one f arr) (return ()) lst
407 zap_one f arr (i, new_v) rst = do
408 old_v <- readSTArray arr i
409 writeSTArray arr i (f old_v new_v)
412 accum :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)] -> Array a b
414 accum f old_array ivs
416 -- copy the old array:
417 arr <- thawSTArray old_array
418 -- now zap the elements in question with "f":
424 accumArray :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)] -> Array a b
425 {-# INLINE accumArray #-}
426 accumArray f zero ixs ivs
428 arr <- newSTArray ixs zero
435 %*********************************************************
437 \subsection{Array instances}
439 %*********************************************************
443 instance Ix a => Functor (Array a) where
446 instance (Ix a, Eq b) => Eq (Array a b) where
447 a == a' = assocs a == assocs a'
448 a /= a' = assocs a /= assocs a'
450 instance (Ix a, Ord b) => Ord (Array a b) where
451 compare a b = compare (assocs a) (assocs b)
453 instance (Ix a, Show a, Show b) => Show (Array a b) where
454 showsPrec p a = showParen (p > 9) (
455 showString "array " .
456 shows (bounds a) . showChar ' ' .
458 showList = showList__ (showsPrec 0)
461 instance (Ix a, Read a, Read b) => Read (Array a b) where
462 readsPrec p = readParen (p > 9)
463 (\r -> [(array b as, u) | ("array",s) <- lex r,
466 readList = readList__ (readsPrec 0)
471 %*********************************************************
473 \subsection{Operations on mutable arrays}
475 %*********************************************************
477 Idle ADR question: What's the tradeoff here between flattening these
478 datatypes into @STArray ix ix (MutableArray# s elt)@ and using
479 it as is? As I see it, the former uses slightly less heap and
480 provides faster access to the individual parts of the bounds while the
481 code used has the benefit of providing a ready-made @(lo, hi)@ pair as
482 required by many array-related functions. Which wins? Is the
483 difference significant (probably not).
485 Idle AJG answer: When I looked at the outputted code (though it was 2
486 years ago) it seems like you often needed the tuple, and we build
487 it frequently. Now we've got the overloading specialiser things
488 might be different, though.
491 newSTArray :: Ix ix => (ix,ix) -> elt -> ST s (STArray s ix elt)
493 {-# SPECIALIZE newSTArray :: IPr -> elt -> ST s (STArray s Int elt),
494 (IPr,IPr) -> elt -> ST s (STArray s IPr elt)
496 newSTArray (l,u) init = ST $ \ s# ->
497 case rangeSize (l,u) of { I# n# ->
498 case (newArray# n# init s#) of { (# s2#, arr# #) ->
499 (# s2#, STArray l u arr# #) }}
503 boundsSTArray :: Ix ix => STArray s ix elt -> (ix, ix)
504 {-# SPECIALIZE boundsSTArray :: STArray s Int elt -> IPr #-}
505 boundsSTArray (STArray l u _) = (l,u)
507 readSTArray :: Ix ix => STArray s ix elt -> ix -> ST s elt
508 {-# SPECIALIZE readSTArray :: STArray s Int elt -> Int -> ST s elt,
509 STArray s IPr elt -> IPr -> ST s elt
512 readSTArray (STArray l u arr#) n = ST $ \ s# ->
513 case (index (l,u) n) of { I# n# ->
514 case readArray# arr# n# s# of { (# s2#, r #) ->
517 writeSTArray :: Ix ix => STArray s ix elt -> ix -> elt -> ST s ()
518 {-# SPECIALIZE writeSTArray :: STArray s Int elt -> Int -> elt -> ST s (),
519 STArray s IPr elt -> IPr -> elt -> ST s ()
522 writeSTArray (STArray l u arr#) n ele = ST $ \ s# ->
523 case index (l,u) n of { I# n# ->
524 case writeArray# arr# n# ele s# of { s2# ->
529 %*********************************************************
531 \subsection{Moving between mutable and immutable}
533 %*********************************************************
536 freezeSTArray :: Ix ix => STArray s ix elt -> ST s (Array ix elt)
537 {-# SPECIALISE freezeSTArray :: STArray s Int elt -> ST s (Array Int elt),
538 STArray s IPr elt -> ST s (Array IPr elt)
541 freezeSTArray (STArray l u arr#) = ST $ \ s# ->
542 case rangeSize (l,u) of { I# n# ->
543 case freeze arr# n# s# of { (# s2#, frozen# #) ->
544 (# s2#, Array l u frozen# #) }}
546 freeze :: MutableArray# s ele -- the thing
547 -> Int# -- size of thing to be frozen
548 -> State# s -- the Universe and everything
549 -> (# State# s, Array# ele #)
551 = case newArray# n# init s# of { (# s2#, newarr1# #) ->
552 case copy 0# n# m_arr# newarr1# s2# of { (# s3#, newarr2# #) ->
553 unsafeFreezeArray# newarr2# s3#
556 init = error "freezeArray: element not copied"
559 -> MutableArray# s ele
560 -> MutableArray# s ele
562 -> (# State# s, MutableArray# s ele #)
564 copy cur# end# from# to# st#
568 = case readArray# from# cur# st# of { (# s1#, ele #) ->
569 case writeArray# to# cur# ele s1# of { s2# ->
570 copy (cur# +# 1#) end# from# to# s2#
573 unsafeFreezeSTArray :: Ix ix => STArray s ix elt -> ST s (Array ix elt)
574 unsafeFreezeSTArray (STArray l u arr#) = ST $ \ s# ->
575 case unsafeFreezeArray# arr# s# of { (# s2#, frozen# #) ->
576 (# s2#, Array l u frozen# #) }
578 --This takes a immutable array, and copies it into a mutable array, in a
581 thawSTArray :: Ix ix => Array ix elt -> ST s (STArray s ix elt)
582 {-# SPECIALISE thawSTArray :: Array Int elt -> ST s (STArray s Int elt),
583 Array IPr elt -> ST s (STArray s IPr elt)
586 thawSTArray (Array l u arr#) = ST $ \ s# ->
587 case rangeSize (l,u) of { I# n# ->
588 case thaw arr# n# s# of { (# s2#, thawed# #) ->
589 (# s2#, STArray l u thawed# #)}}
591 thaw :: Array# ele -- the thing
592 -> Int# -- size of thing to be thawed
593 -> State# s -- the Universe and everything
594 -> (# State# s, MutableArray# s ele #)
597 = case newArray# n# init s# of { (# s2#, newarr1# #) ->
598 copy 0# n# arr1# newarr1# s2# }
600 init = error "thawSTArray: element not copied"
604 -> MutableArray# s ele
606 -> (# State# s, MutableArray# s ele #)
608 copy cur# end# from# to# st#
612 = case indexArray# from# cur# of { (# ele #) ->
613 case writeArray# to# cur# ele st# of { s1# ->
614 copy (cur# +# 1#) end# from# to# s1#
617 -- this is a quicker version of the above, just flipping the type
618 -- (& representation) of an immutable array. And placing a
619 -- proof obligation on the programmer.
620 unsafeThawSTArray :: Ix ix => Array ix elt -> ST s (STArray s ix elt)
621 unsafeThawSTArray (Array l u arr#) = ST $ \ s# ->
622 case unsafeThawArray# arr# s# of
623 (# s2#, marr# #) -> (# s2#, STArray l u marr# #)