Commit 95a61790 authored by Ian Lynagh's avatar Ian Lynagh
Browse files

Data.Array* and Data.PackedString have now moved to their own packages

parent c769383a
{-# OPTIONS_GHC -fno-implicit-prelude #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.Array
-- Copyright : (c) The University of Glasgow 2001
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : provisional
-- Portability : portable
--
-- Basic non-strict arrays.
--
-- /Note:/ The "Data.Array.IArray" module provides more general interface
-- to immutable arrays: it defines operations with the same names as
-- those defined below, but with more general types, and also defines
-- 'Array' instances of the relevant classes. To use that more general
-- interface, import "Data.Array.IArray" but not "Data.Array".
-----------------------------------------------------------------------------
module Data.Array
(
-- * Immutable non-strict arrays
-- $intro
module Data.Ix -- export all of Ix
, Array -- Array type is abstract
-- * Array construction
, array -- :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
, listArray -- :: (Ix a) => (a,a) -> [b] -> Array a b
, accumArray -- :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)] -> Array a b
-- * Accessing arrays
, (!) -- :: (Ix a) => Array a b -> a -> b
, bounds -- :: (Ix a) => Array a b -> (a,a)
, indices -- :: (Ix a) => Array a b -> [a]
, elems -- :: (Ix a) => Array a b -> [b]
, assocs -- :: (Ix a) => Array a b -> [(a,b)]
-- * Incremental array updates
, (//) -- :: (Ix a) => Array a b -> [(a,b)] -> Array a b
, accum -- :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)] -> Array a b
-- * Derived arrays
, ixmap -- :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c -> Array a b
-- Array instances:
--
-- Ix a => Functor (Array a)
-- (Ix a, Eq b) => Eq (Array a b)
-- (Ix a, Ord b) => Ord (Array a b)
-- (Ix a, Show a, Show b) => Show (Array a b)
-- (Ix a, Read a, Read b) => Read (Array a b)
--
-- Implementation checked wrt. Haskell 98 lib report, 1/99.
) where
import Data.Ix
#ifdef __GLASGOW_HASKELL__
import GHC.Arr -- Most of the hard work is done here
import Data.Generics.Basics -- To provide a Data instance
import Data.Generics.Instances -- To provide a Data instance
import GHC.Err ( error ) -- Needed for Data instance
#endif
#ifdef __HUGS__
import Hugs.Array
#endif
#ifdef __NHC__
import Array -- Haskell'98 arrays
#endif
import Data.Typeable
{- $intro
Haskell provides indexable /arrays/, which may be thought of as functions
whose domains are isomorphic to contiguous subsets of the integers.
Functions restricted in this way can be implemented efficiently;
in particular, a programmer may reasonably expect rapid access to
the components. To ensure the possibility of such an implementation,
arrays are treated as data, not as general functions.
Since most array functions involve the class 'Ix', this module is exported
from "Data.Array" so that modules need not import both "Data.Array" and
"Data.Ix".
-}
This diff is collapsed.
-----------------------------------------------------------------------------
-- |
-- Module : Data.Array.Diff
-- Copyright : (c) The University of Glasgow 2001
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
-- Portability : non-portable (uses Data.Array.IArray)
--
-- Functional arrays with constant-time update.
--
-----------------------------------------------------------------------------
module Data.Array.Diff (
-- * Diff array types
-- | Diff arrays have an immutable interface, but rely on internal
-- updates in place to provide fast functional update operator
-- '//'.
--
-- When the '//' operator is applied to a diff array, its contents
-- are physically updated in place. The old array silently changes
-- its representation without changing the visible behavior:
-- it stores a link to the new current array along with the
-- difference to be applied to get the old contents.
--
-- So if a diff array is used in a single-threaded style,
-- i.e. after '//' application the old version is no longer used,
-- @a'!'i@ takes O(1) time and @a '//' d@ takes O(@length d@).
-- Accessing elements of older versions gradually becomes slower.
--
-- Updating an array which is not current makes a physical copy.
-- The resulting array is unlinked from the old family. So you
-- can obtain a version which is guaranteed to be current and
-- thus have fast element access by @a '//' []@.
-- Possible improvement for the future (not implemented now):
-- make it possible to say "I will make an update now, but when
-- I later return to the old version, I want it to mutate back
-- instead of being copied".
IOToDiffArray, -- data IOToDiffArray
-- (a :: * -> * -> *) -- internal mutable array
-- (i :: *) -- indices
-- (e :: *) -- elements
-- | Type synonyms for the two most important IO array types.
-- Two most important diff array types are fully polymorphic
-- lazy boxed DiffArray:
DiffArray, -- = IOToDiffArray IOArray
-- ...and strict unboxed DiffUArray, working only for elements
-- of primitive types but more compact and usually faster:
DiffUArray, -- = IOToDiffArray IOUArray
-- * Overloaded immutable array interface
-- | Module "Data.Array.IArray" provides the interface of diff arrays.
-- They are instances of class 'IArray'.
module Data.Array.IArray,
-- * Low-level interface
-- | These are really internal functions, but you will need them
-- to make further 'IArray' instances of various diff array types
-- (for either more 'MArray' types or more unboxed element types).
newDiffArray, readDiffArray, replaceDiffArray
)
where
------------------------------------------------------------------------
-- Imports.
import Prelude
import Data.Ix
import Data.Array.Base
import Data.Array.IArray
import Data.Array.IO
import Foreign.Ptr ( Ptr, FunPtr )
import Foreign.StablePtr ( StablePtr )
import Data.Int ( Int8, Int16, Int32, Int64 )
import Data.Word ( Word, Word8, Word16, Word32, Word64 )
import System.IO.Unsafe ( unsafePerformIO )
import Control.Exception ( evaluate )
import Control.Concurrent.MVar ( MVar, newMVar, takeMVar, putMVar, readMVar )
------------------------------------------------------------------------
-- Diff array types.
-- | An arbitrary 'MArray' type living in the 'IO' monad can be converted
-- to a diff array.
newtype IOToDiffArray a i e =
DiffArray {varDiffArray :: MVar (DiffArrayData a i e)}
-- Internal representation: either a mutable array, or a link to
-- another diff array patched with a list of index+element pairs.
data DiffArrayData a i e = Current (a i e)
| Diff (IOToDiffArray a i e) [(Int, e)]
-- | Fully polymorphic lazy boxed diff array.
type DiffArray = IOToDiffArray IOArray
-- | Strict unboxed diff array, working only for elements
-- of primitive types but more compact and usually faster than 'DiffArray'.
type DiffUArray = IOToDiffArray IOUArray
-- Having 'MArray a e IO' in instance context would require
-- -fallow-undecidable-instances, so each instance is separate here.
------------------------------------------------------------------------
-- Showing DiffArrays
instance (Ix ix, Show ix, Show e) => Show (DiffArray ix e) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Char) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Float) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Double) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int8) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int16) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int32) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int64) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word8) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word16) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word32) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word64) where
showsPrec = showsIArray
------------------------------------------------------------------------
-- Boring instances.
instance IArray (IOToDiffArray IOArray) e where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray1` ies
instance IArray (IOToDiffArray IOUArray) Char where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) (Ptr a) where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) (FunPtr a) where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Float where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Double where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) (StablePtr a) where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int8 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int16 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int32 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int64 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word8 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word16 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word32 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word64 where
bounds a = unsafePerformIO $ boundsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
------------------------------------------------------------------------
-- The important stuff.
newDiffArray :: (MArray a e IO, Ix i)
=> (i,i)
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
newDiffArray (l,u) ies = do
a <- newArray_ (l,u)
sequence_ [unsafeWrite a i e | (i, e) <- ies]
var <- newMVar (Current a)
return (DiffArray var)
readDiffArray :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> Int
-> IO e
a `readDiffArray` i = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> unsafeRead a' i
Diff a' ies -> maybe (readDiffArray a' i) return (lookup i ies)
replaceDiffArray :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
a `replaceDiffArray` ies = do
d <- takeMVar (varDiffArray a)
case d of
Current a' -> case ies of
[] -> do
-- We don't do the copy when there is nothing to change
-- and this is the current version. But see below.
putMVar (varDiffArray a) d
return a
_:_ -> do
diff <- sequence [do e <- unsafeRead a' i; return (i, e)
| (i, _) <- ies]
sequence_ [unsafeWrite a' i e | (i, e) <- ies]
var' <- newMVar (Current a')
putMVar (varDiffArray a) (Diff (DiffArray var') diff)
return (DiffArray var')
Diff _ _ -> do
-- We still do the copy when there is nothing to change
-- but this is not the current version. So you can use
-- 'a // []' to make sure that the resulting array has
-- fast element access.
putMVar (varDiffArray a) d
a' <- thawDiffArray a
-- thawDiffArray gives a fresh array which we can
-- safely mutate.
sequence_ [unsafeWrite a' i e | (i, e) <- ies]
var' <- newMVar (Current a')
return (DiffArray var')
-- The elements of the diff list might recursively reference the
-- array, so we must seq them before taking the MVar to avoid
-- deadlock.
replaceDiffArray1 :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
a `replaceDiffArray1` ies = do
mapM_ (evaluate . fst) ies
a `replaceDiffArray` ies
-- If the array contains unboxed elements, then the elements of the
-- diff list may also recursively reference the array from inside
-- replaceDiffArray, so we must seq them too.
replaceDiffArray2 :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
a `replaceDiffArray2` ies = do
mapM_ (\(a,b) -> do evaluate a; evaluate b) ies
a `replaceDiffArray` ies
boundsDiffArray :: (MArray a e IO, Ix ix)
=> IOToDiffArray a ix e
-> IO (ix,ix)
boundsDiffArray a = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> getBounds a'
Diff a' _ -> boundsDiffArray a'
freezeDiffArray :: (MArray a e IO, Ix ix)
=> a ix e
-> IO (IOToDiffArray a ix e)
freezeDiffArray a = do
(l,u) <- getBounds a
a' <- newArray_ (l,u)
sequence_ [unsafeRead a i >>= unsafeWrite a' i | i <- [0 .. rangeSize (l,u) - 1]]
var <- newMVar (Current a')
return (DiffArray var)
{-# RULES
"freeze/DiffArray" freeze = freezeDiffArray
#-}
-- unsafeFreezeDiffArray is really unsafe. Better don't use the old
-- array at all after freezing. The contents of the source array will
-- be changed when '//' is applied to the resulting array.
unsafeFreezeDiffArray :: (MArray a e IO, Ix ix)
=> a ix e
-> IO (IOToDiffArray a ix e)
unsafeFreezeDiffArray a = do
var <- newMVar (Current a)
return (DiffArray var)
{-# RULES
"unsafeFreeze/DiffArray" unsafeFreeze = unsafeFreezeDiffArray
#-}
thawDiffArray :: (MArray a e IO, Ix ix)
=> IOToDiffArray a ix e
-> IO (a ix e)
thawDiffArray a = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> do
(l,u) <- getBounds a'
a'' <- newArray_ (l,u)
sequence_ [unsafeRead a' i >>= unsafeWrite a'' i | i <- [0 .. rangeSize (l,u) - 1]]
return a''
Diff a' ies -> do
a'' <- thawDiffArray a'
sequence_ [unsafeWrite a'' i e | (i, e) <- ies]
return a''
{-# RULES
"thaw/DiffArray" thaw = thawDiffArray
#-}
-- unsafeThawDiffArray is really unsafe. Better don't use the old
-- array at all after thawing. The contents of the resulting array
-- will be changed when '//' is applied to the source array.
unsafeThawDiffArray :: (MArray a e IO, Ix ix)
=> IOToDiffArray a ix e
-> IO (a ix e)
unsafeThawDiffArray a = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> return a'
Diff a' ies -> do
a'' <- unsafeThawDiffArray a'
sequence_ [unsafeWrite a'' i e | (i, e) <- ies]
return a''
{-# RULES
"unsafeThaw/DiffArray" unsafeThaw = unsafeThawDiffArray
#-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.Array.IArray
-- Copyright : (c) The University of Glasgow 2001
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
-- Portability : non-portable (uses Data.Array.Base)
--
-- Immutable arrays, with an overloaded interface. For array types which
-- can be used with this interface, see the 'Array' type exported by this
-- module, and the "Data.Array.Unboxed" and "Data.Array.Diff" modules.
--
-----------------------------------------------------------------------------
module Data.Array.IArray (
-- * Array classes
IArray, -- :: (* -> * -> *) -> * -> class
module Data.Ix,
-- * Immutable non-strict (boxed) arrays
Array,
-- * Array construction
array, -- :: (IArray a e, Ix i) => (i,i) -> [(i, e)] -> a i e
listArray, -- :: (IArray a e, Ix i) => (i,i) -> [e] -> a i e
accumArray, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> e -> (i,i) -> [(i, e')] -> a i e
-- * Accessing arrays
(!), -- :: (IArray a e, Ix i) => a i e -> i -> e
bounds, -- :: (HasBounds a, Ix i) => a i e -> (i,i)
indices, -- :: (HasBounds a, Ix i) => a i e -> [i]
elems, -- :: (IArray a e, Ix i) => a i e -> [e]
assocs, -- :: (IArray a e, Ix i) => a i e -> [(i, e)]
-- * Incremental array updates
(//), -- :: (IArray a e, Ix i) => a i e -> [(i, e)] -> a i e
accum, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(i, e')] -> a i e
-- * Derived arrays
amap, -- :: (IArray a e', IArray a e, Ix i) => (e' -> e) -> a i e' -> a i e
ixmap, -- :: (IArray a e, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> a i e
) where
import Prelude
import Data.Ix
import Data.Array (Array)
import Data.Array.Base
{-# OPTIONS_GHC -#include "HsBase.h" #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.Array.IO
-- Copyright : (c) The University of Glasgow 2001
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
-- Portability : non-portable (uses Data.Array.MArray)
--
-- Mutable boxed and unboxed arrays in the IO monad.
--
-----------------------------------------------------------------------------
module Data.Array.IO (
-- * @IO@ arrays with boxed elements
IOArray, -- instance of: Eq, Typeable
-- * @IO@ arrays with unboxed elements
IOUArray, -- instance of: Eq, Typeable
castIOUArray, -- :: IOUArray i a -> IO (IOUArray i b)
-- * Overloaded mutable array interface
module Data.Array.MArray,
-- * Doing I\/O with @IOUArray@s
hGetArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO Int
hPutArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO ()
) where
import Prelude
import Data.Array.Base
import Data.Array.IO.Internals
import Data.Array ( Array )
import Data.Array.MArray
import Data.Int
import Data.Word
#ifdef __GLASGOW_HASKELL__