diff options
Diffstat (limited to 'ghc/lib/prelude/IArray.hs')
-rw-r--r-- | ghc/lib/prelude/IArray.hs | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/ghc/lib/prelude/IArray.hs b/ghc/lib/prelude/IArray.hs new file mode 100644 index 0000000000..eec3b04f2d --- /dev/null +++ b/ghc/lib/prelude/IArray.hs @@ -0,0 +1,285 @@ +-- *** all of PreludeArray except the actual data decls + +module PreludeArray ( + Array, Assoc, + + (!), + (//), + accum, + accumArray, + amap, + array, + assocs, + bounds, + elems, + indices, + ixmap, + listArray + ) where + +import Cls +import Core +import IChar +import IInt -- instances +import IList +import ITup2 +import List ( (++), zipWith, foldr ) +import Prel ( (&&), (.) ) +import PS ( _PackedString, _unpackPS ) +import Text +import TyArray ( Array(..), Assoc(..) ) +import PreludeGlaST + +-- Hey! This isn't wimp Haskell-report code! This is +-- the Business End of Arrays... + +--infixl 9 ! +--infixl 9 // +--infix 1 := + +----------------------------------------------------------- +instance (Eq a, Eq b) => Eq (Assoc a b) where + (a1 := b1) == (a2 := b2) = a1 == a2 && b1 == b2 + a /= b = if a == b then False else True + +instance (Ord a, Ord b) => Ord (Assoc a b) where + a < b = case _tagCmp a b of { _LT -> True; _EQ -> False; _GT -> False } + a <= b = case _tagCmp a b of { _LT -> True; _EQ -> True; _GT -> False } + a >= b = case _tagCmp a b of { _LT -> False; _EQ -> True; _GT -> True } + a > b = case _tagCmp a b of { _LT -> False; _EQ -> False; _GT -> True } + max a b = case _tagCmp a b of { _LT -> b; _EQ -> a; _GT -> a } + min a b = case _tagCmp a b of { _LT -> a; _EQ -> a; _GT -> b } + _tagCmp (a1 := b1) (a2 := b2) + = case (_tagCmp a1 a2) of { _LT -> _LT; _GT -> _GT; _EQ -> _tagCmp b1 b2 } + +instance (Ix a, Ix b) => Ix (Assoc a b) where + range (l1 := l2, u1 := u2) + = [ (i1 := i2) | i1 <- range (l1, u1), i2 <- range (l2, u2) ] + + index (l1 := l2, u1 := u2) (i1 := i2) + = index (l1, u1) i1 * (index (l2, u2) u2 + 1){-rangeSize (l2, u2)-} + index (l2, u2) i2 + + inRange (l1 := l2, u1 := u2) (i1 := i2) + = inRange (l1, u1) i1 && inRange (l2, u2) i2 + +instance (Text a, Text b) => Text (Assoc a b) where + -- magic fixity wired in: infix 1 := + readsPrec p + = readParen ( p > 1 ) + (\ r -> [ (x := y, s2) | (x, s0) <- readsPrec 2 r, + (":=", s1) <- lex s0, + (y, s2) <- readsPrec 2 s1 ]) + showsPrec d (a := b) + = showParen (d > 1) + (showsPrec 2 a . showString " := " . showsPrec 2 b) + +-- ToDo: *** Binary + +----------------------------------------------------------- + +type IPr = (Int, Int) + +{-# GENERATE_SPECS array a{~,Int,IPr} b{} #-} +array :: (Ix a) => (a,a) -> [Assoc a b] -> Array a b + +{-# GENERATE_SPECS (!) a{~,Int,IPr} b{} #-} +(!) :: (Ix a) => Array a b -> a -> b + +bounds :: Array a b -> (a,a) + +{-# GENERATE_SPECS listArray a{~,Int,IPr} b{} #-} +listArray :: (Ix a) => (a,a) -> [b] -> Array a b + +{-# GENERATE_SPECS indices a{~,Int,IPr} b{} #-} +indices :: (Ix a) => Array a b -> [a] + +{-# GENERATE_SPECS elems a{~,Int,IPr} b{} #-} +elems :: (Ix a) => Array a b -> [b] + +{-# GENERATE_SPECS assocs a{~,Int,IPr} b{} #-} +assocs :: (Ix a) => Array a b -> [Assoc a b] + +{-# GENERATE_SPECS accumArray a{~,Int,IPr} b{} c{} #-} +accumArray :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [Assoc a c] -> Array a b + +{-# GENERATE_SPECS (//) a{~,Int,IPr} b{} #-} +(//) :: (Ix a) => Array a b -> [Assoc a b] -> Array a b + +{-# GENERATE_SPECS accum a{~,Int,IPr} b{} c{} #-} +accum :: (Ix a) => (b -> c -> b) -> Array a b -> [Assoc a c] -> Array a b + +{-# GENERATE_SPECS amap a{~,Int,IPr} b{} c{} #-} +amap :: (Ix a) => (b -> c) -> Array a b -> Array a c + +ixmap :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c -> Array a c + + +{- "array", "!" and "bounds" are basic; + the rest can be defined in terms of them +-} + +bounds (_Array b _) = b + +array ixs@(ix_start, ix_end) ivs + = _runST ( + newArray ixs arrEleBottom `thenStrictlyST` \ arr# -> + fill_it_in arr# ivs `seqStrictlyST` + freezeArray arr# + ) + where + arrEleBottom = error "(!){PreludeArray}: undefined array element" + +(_Array bounds arr#) ! i + = let n# = case (index bounds i) of { I# x -> x } -- index fails if out of range + in + case (indexArray# arr# n#) of + _Lift v -> v + +fill_it_in arr lst s + = foldr fill_one_in (returnStrictlyST ()) lst s + where -- **** STRICT **** (but that's OK...) + fill_one_in (i := v) rst s + = (writeArray arr i v `seqStrictlyST` rst) s + +{- the rest ------------------------------------------------- -} + +listArray b vs = array b (zipWith (:=) (range b) vs) + +indices a = range (bounds a) + +elems a = [a!i | i <- indices a] + +assocs a = [i := a!i | i <- indices a] + +#ifdef USE_REPORT_PRELUDE +a // us = array (bounds a) + ([i := a!i | i <- indices a \\ [i | i:=_ <- us]] + ++ us) + +accum f = foldl (\a (i := v) -> a // [i := f (a!i) v]) + +accumArray f z b = accum f (array b [i := z | i <- range b]) + +#else /* ! USE_REPORT_PRELUDE */ + +old_array // ivs + = _runST ( + -- copy the old array: + newArray (bounds old_array) bottom `thenStrictlyST` \ arr# -> + fill_it_in arr# (assocs old_array) `seqStrictlyST` + -- now write the new elements into the new array: + fill_it_in arr# ivs `seqStrictlyST` + freezeArray arr# + ) + where + bottom = error "(//){PreludeArray}: error in copying old array\n" + +-- zap_with_f: reads an elem out first, then uses "f" on that and the new value + +zap_with_f f arr lst s + = foldr zap_one (returnStrictlyST ()) lst s + where + zap_one (i := new_v) rst s + = (readArray arr i `thenStrictlyST` \ old_v -> + writeArray arr i (f old_v new_v) `seqStrictlyST` + rst) s + +accum f arr ivs + = _runST ( + -- copy the old array: + newArray (bounds arr) bottom `thenST` \ arr# -> + fill_it_in arr# (assocs arr) `seqST` + + -- now zap the elements in question with "f": + zap_with_f f arr# ivs `seqST` + freezeArray arr# + ) + where + bottom = error "accum{PreludeArray}: error in copying old array\n" + +accumArray f zero ixs ivs + = _runST ( + newArray ixs zero `thenST` \ arr# -> + zap_with_f f arr# ivs `seqST` + freezeArray arr# + ) +#endif /* ! USE_REPORT_PRELUDE */ + +amap f a = array b [i := f (a!i) | i <- range b] + where b = bounds a + +ixmap b f a = array b [i := a ! f i | i <- range b] + +instance (Ix a, Eq b) => Eq (Array a b) where + a == a' = assocs a == assocs a' + a /= a' = assocs a /= assocs a' + +instance (Ix a, Ord b) => Ord (Array a b) where + a < b = case _tagCmp a b of { _LT -> True; _EQ -> False; _GT -> False } + a <= b = case _tagCmp a b of { _LT -> True; _EQ -> True; _GT -> False } + a >= b = case _tagCmp a b of { _LT -> False; _EQ -> True; _GT -> True } + a > b = case _tagCmp a b of { _LT -> False; _EQ -> False; _GT -> True } + + max a b = case _tagCmp a b of { _LT -> b; _EQ -> a; _GT -> a } + min a b = case _tagCmp a b of { _LT -> a; _EQ -> a; _GT -> b } + + _tagCmp a b = _tagCmp (assocs a) (assocs b) + +instance (Ix a, Text a, Text b) => Text (Array a b) where + showsPrec p a = showParen (p > 9) ( + showString "array " . + shows (bounds a) . showChar ' ' . + shows (assocs a) ) + + readsPrec p = readParen (p > 9) + (\r -> [(array b as, u) | ("array",s) <- lex r, + (b,t) <- reads s, + (as,u) <- reads t ] + ++ + [(listArray b xs, u) | ("listArray",s) <- lex r, + (b,t) <- reads s, + (xs,u) <- reads t ]) + +{- **** OMITTED **** (ToDo) +instance (Ix a, Binary a, Binary b) => Binary (Array a b) where + showBin a = showBin (bounds a) . showBin (elems a) + + readBin bin = (listArray b vs, bin'') + where (b,bin') = readBin bin + (vs,bin'') = readBin bin' +-} +{- ToDo ... + +#if defined(__UNBOXED_INSTANCES__) + +-- {-# GENERATE_SPECS array a{~,Int#,Int,IPr} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS (!) a{~,Int#,Int,IPr} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS bounds a{~,Int#} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS listArray a{~,Int#,Int,IPr} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS indices a{~,Int#,Int,IPr} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS elems a{~,Int#,Int,IPr} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS assocs a{~,Int#,Int,IPr} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS accumArray a{~,Int#,Int,IPr} b{Int#,Double#} c{Int#,Double#} #-} +-- {-# GENERATE_SPECS (//) a{~,Int#,Int,IPr} b{Int#,Double#} #-} +-- {-# GENERATE_SPECS accum a{~,Int#,Int,IPr} b{Int#,Double#} c{Int#,Double#} #-} +-- {-# GENERATE_SPECS amap a{~,Int#,Int,IPr} b{Int#,Double#} c{Int#,Double#} #-} +-- {-# GENERATE_SPECS ixmap a{~,Int#,Int} b{~,Int#,Int} c{Int#,Double#} #-} + +-- {-# GENERATE_SPECS instance a{Int#} b{Int#,Double#} :: Eq (Array a b) #-} +-- {-# GENERATE_SPECS instance a{Int#} b{Int#,Double#} :: Ord (Array a b) #-} +-- {-# GENERATE_SPECS instance a{Int#} b{Int#,Double#} :: Text (Array a b) #-} + + +-- {-# GENERATE_SPECS instance a{Int} b{} :: Eq (Array a b) #-} +This raises the question of ambiguous specialised instances: +Which instance would be chosen for Array Int Int# ? +Array Int b or Array a Int# ? + +-- {-# GENERATE_SPECS instance a{Int#} b{Int#,Double#} :: Eq (Assoc a b) #-} +-- {-# GENERATE_SPECS instance a{Int#} b{Int#,Double#} :: Ord (Assoc a b) #-} +-- {-# GENERATE_SPECS instance a{Int#} b{Int#,Double#} :: Ix (Assoc a b) #-} +-- {-# GENERATE_SPECS instance a{Int#} b{Int#,Double#} :: Text (Assoc a b) #-} + +#endif + +-} |