Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ghc/packages/array
  • RyanGlScott/array
  • int-index/array
  • osa1/array
  • Haskell-mouse/array
  • trac-runeks/array
  • Jdoc82/array
  • meooow/array
  • supersven/array
  • konsumlamm/array
  • tbidne/array
  • wavewave/array
12 results
Show changes
Commits on Source (45)
Showing with 424 additions and 74 deletions
name: Building
on:
pull_request:
branches:
- '**'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
ghc: ['9.10', '9.8', '9.6', '9.4', '9.2', '9.0', '8.10', '8.8', '8.6', '8.4', '8.2', '8.0']
os: ['ubuntu-22.04', 'windows-latest']
name: Build on ${{ matrix.os }} with GHC ${{ matrix.ghc }}
steps:
- uses: actions/checkout@v4
- uses: haskell-actions/setup@v2
with:
ghc-version: ${{ matrix.ghc }}
- run: cabal build
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
, UnliftedFFITypes , UnliftedFFITypes
, RoleAnnotations , RoleAnnotations
#-} #-}
{-# OPTIONS_HADDOCK hide #-} {-# OPTIONS_HADDOCK not-home #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
...@@ -25,18 +25,29 @@ ...@@ -25,18 +25,29 @@
-- Basis for IArray and MArray. Not intended for external consumption; -- Basis for IArray and MArray. Not intended for external consumption;
-- use IArray or MArray instead. -- use IArray or MArray instead.
-- --
-- = WARNING
--
-- This module is considered __internal__.
--
-- The Package Versioning Policy __does not apply__.
--
-- The contents of this module may change __in any way whatsoever__
-- and __without any warning__ between minor versions of this package.
--
-- Authors importing this module are expected to track development
-- closely.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module Data.Array.Base where module Data.Array.Base where
import Control.Monad.ST.Lazy ( strictToLazyST ) import Control.Monad.ST.Lazy ( strictToLazyST )
import qualified Control.Monad.ST.Lazy as Lazy (ST) import qualified Control.Monad.ST.Lazy as Lazy (ST)
import Data.Ix ( Ix, range, index, rangeSize ) import Data.Ix ( Ix, range, index, inRange, rangeSize )
import Foreign.C.Types import Foreign.C.Types
import Foreign.StablePtr import Foreign.StablePtr
import Data.Char import Data.Char
import GHC.Arr ( STArray ) import GHC.Arr ( STArray, unsafeIndex )
import qualified GHC.Arr as Arr import qualified GHC.Arr as Arr
import qualified GHC.Arr as ArrST import qualified GHC.Arr as ArrST
import GHC.ST ( ST(..), runST ) import GHC.ST ( ST(..), runST )
...@@ -183,35 +194,26 @@ listArray (l,u) es = ...@@ -183,35 +194,26 @@ listArray (l,u) es =
let n = safeRangeSize (l,u) let n = safeRangeSize (l,u)
in unsafeArray (l,u) (zip [0 .. n - 1] es) in unsafeArray (l,u) (zip [0 .. n - 1] es)
{-# INLINE listArrayST #-} {-# INLINE genArray #-}
-- | Constructs an immutable array using a generator function.
--
-- @since 0.5.6.0
genArray :: (IArray a e, Ix i) => (i,i) -> (i -> e) -> a i e
genArray (l,u) f = listArray (l,u) $ map f $ range (l,u)
{-# INLINE listArrayST #-} -- See Note [Inlining and fusion]
listArrayST :: Ix i => (i,i) -> [e] -> ST s (STArray s i e) listArrayST :: Ix i => (i,i) -> [e] -> ST s (STArray s i e)
listArrayST (l,u) es = do listArrayST = newListArray
marr <- newArray_ (l,u)
let n = safeRangeSize (l,u)
let fillFromList i xs | i == n = return ()
| otherwise = case xs of
[] -> return ()
y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
fillFromList 0 es
return marr
{-# RULES {-# RULES
"listArray/Array" listArray = "listArray/Array" listArray =
\lu es -> runST (listArrayST lu es >>= ArrST.unsafeFreezeSTArray) \lu es -> runST (listArrayST lu es >>= ArrST.unsafeFreezeSTArray)
#-} #-}
{-# INLINE listUArrayST #-} {-# INLINE listUArrayST #-} -- See Note [Inlining and fusion]
listUArrayST :: (MArray (STUArray s) e (ST s), Ix i) listUArrayST :: (MArray (STUArray s) e (ST s), Ix i)
=> (i,i) -> [e] -> ST s (STUArray s i e) => (i,i) -> [e] -> ST s (STUArray s i e)
listUArrayST (l,u) es = do listUArrayST = newListArray
marr <- newArray_ (l,u)
let n = safeRangeSize (l,u)
let fillFromList i xs | i == n = return ()
| otherwise = case xs of
[] -> return ()
y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
fillFromList 0 es
return marr
-- I don't know how to write a single rule for listUArrayST, because -- I don't know how to write a single rule for listUArrayST, because
-- the type looks like constrained over 's', which runST doesn't -- the type looks like constrained over 's', which runST doesn't
...@@ -272,11 +274,23 @@ type ListUArray e = forall i . Ix i => (i,i) -> [e] -> UArray i e ...@@ -272,11 +274,23 @@ type ListUArray e = forall i . Ix i => (i,i) -> [e] -> UArray i e
#-} #-}
{-# INLINE (!) #-} {-# INLINE (!) #-}
-- | Returns the element of an immutable array at the specified index. -- | Returns the element of an immutable array at the specified index,
-- or throws an exception if the index is out of bounds.
(!) :: (IArray a e, Ix i) => a i e -> i -> e (!) :: (IArray a e, Ix i) => a i e -> i -> e
(!) arr i = case bounds arr of (!) arr i = case bounds arr of
(l,u) -> unsafeAt arr $ safeIndex (l,u) (numElements arr) i (l,u) -> unsafeAt arr $ safeIndex (l,u) (numElements arr) i
{-# INLINE (!?) #-}
-- | Returns 'Just' the element of an immutable array at the specified index,
-- or 'Nothing' if the index is out of bounds.
--
-- @since 0.5.6.0
(!?) :: (IArray a e, Ix i) => a i e -> i -> Maybe e
(!?) arr i = let b = bounds arr in
if inRange b i
then Just $ unsafeAt arr $ unsafeIndex b i
else Nothing
{-# INLINE indices #-} {-# INLINE indices #-}
-- | Returns a list of all the valid indices in an array. -- | Returns a list of all the valid indices in an array.
indices :: (IArray a e, Ix i) => a i e -> [i] indices :: (IArray a e, Ix i) => a i e -> [i]
...@@ -372,6 +386,94 @@ ixmap :: (IArray a e, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> a i e ...@@ -372,6 +386,94 @@ ixmap :: (IArray a e, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> a i e
ixmap (l,u) f arr = ixmap (l,u) f arr =
array (l,u) [(i, arr ! f i) | i <- range (l,u)] array (l,u) [(i, arr ! f i) | i <- range (l,u)]
-- | Lazy right-associative fold.
--
-- @since 0.5.8.0
foldrArray :: (IArray a e, Ix i) => (e -> b -> b) -> b -> a i e -> b
foldrArray f z = \a ->
let !n = numElements a
go i | i >= n = z
| otherwise = f (unsafeAt a i) (go (i+1))
in go 0
{-# INLINE foldrArray #-}
-- | Strict accumulating left-associative fold.
--
-- @since 0.5.8.0
foldlArray' :: (IArray a e, Ix i) => (b -> e -> b) -> b -> a i e -> b
foldlArray' f z0 = \a ->
let !n = numElements a
go !z i | i >= n = z
| otherwise = go (f z (unsafeAt a i)) (i+1)
in go z0 0
{-# INLINE foldlArray' #-}
-- | Lazy left-associative fold.
--
-- @since 0.5.8.0
foldlArray :: (IArray a e, Ix i) => (b -> e -> b) -> b -> a i e -> b
foldlArray f z = \a ->
let !n = numElements a
go i | i < 0 = z
| otherwise = f (go (i-1)) (unsafeAt a i)
in go (n-1)
{-# INLINE foldlArray #-}
-- | Strict accumulating right-associative fold.
--
-- @since 0.5.8.0
foldrArray' :: (IArray a e, Ix i) => (e -> b -> b) -> b -> a i e -> b
foldrArray' f z0 = \a ->
let !n = numElements a
go i !z | i < 0 = z
| otherwise = go (i-1) (f (unsafeAt a i) z)
in go (n-1) z0
{-# INLINE foldrArray' #-}
-- | Map elements to applicative actions, sequence them left-to-right, and
-- discard the results.
--
-- @since 0.5.8.0
traverseArray_
:: (IArray a e, Ix i, Applicative f) => (e -> f b) -> a i e -> f ()
traverseArray_ f = foldrArray (\x z -> f x *> z) (pure ())
{-# INLINE traverseArray_ #-}
-- | @forArray_@ is 'traverseArray_' with its arguments flipped.
--
-- @since 0.5.8.0
forArray_ :: (IArray a e, Ix i, Applicative f) => a i e -> (e -> f b) -> f ()
forArray_ = flip traverseArray_
{-# INLINE forArray_ #-}
-- | Strict accumulating left-associative monadic fold.
--
-- @since 0.5.8.0
foldlArrayM'
:: (IArray a e, Ix i, Monad m) => (b -> e -> m b) -> b -> a i e -> m b
foldlArrayM' f z0 = \a ->
let !n = numElements a
go !z i | i >= n = pure z
| otherwise = do
z' <- f z (unsafeAt a i)
go z' (i+1)
in go z0 0
{-# INLINE foldlArrayM' #-}
-- | Strict accumulating right-associative monadic fold.
--
-- @since 0.5.8.0
foldrArrayM'
:: (IArray a e, Ix i, Monad m) => (e -> b -> m b) -> b -> a i e -> m b
foldrArrayM' f z0 = \a ->
let !n = numElements a
go i !z | i < 0 = pure z
| otherwise = do
z' <- f (unsafeAt a i) z
go (i-1) z'
in go (n-1) z0
{-# INLINE foldrArrayM' #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Normal polymorphic arrays -- Normal polymorphic arrays
...@@ -485,11 +587,6 @@ cmpIntUArray arr1@(UArray l1 u1 n1 _) arr2@(UArray l2 u2 n2 _) = ...@@ -485,11 +587,6 @@ cmpIntUArray arr1@(UArray l1 u1 n1 _) arr2@(UArray l2 u2 n2 _) =
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Showing and Reading IArrays -- Showing and Reading IArrays
{-# SPECIALISE
showsIArray :: (IArray UArray e, Ix i, Show i, Show e) =>
Int -> UArray i e -> ShowS
#-}
showsIArray :: (IArray a e, Ix i, Show i, Show e) => Int -> a i e -> ShowS showsIArray :: (IArray a e, Ix i, Show i, Show e) => Int -> a i e -> ShowS
showsIArray p a = showsIArray p a =
showParen (p > appPrec) $ showParen (p > appPrec) $
...@@ -497,11 +594,7 @@ showsIArray p a = ...@@ -497,11 +594,7 @@ showsIArray p a =
shows (bounds a) . shows (bounds a) .
showChar ' ' . showChar ' ' .
shows (assocs a) shows (assocs a)
{-# SPECIALISE
readIArray :: (IArray UArray e, Ix i, Read i, Read e) =>
ReadPrec (UArray i e)
#-}
readIArray :: (IArray a e, Ix i, Read i, Read e) => ReadPrec (a i e) readIArray :: (IArray a e, Ix i, Read i, Read e) => ReadPrec (a i e)
readIArray = parens $ prec appPrec $ readIArray = parens $ prec appPrec $
...@@ -662,7 +755,7 @@ instance IArray UArray (StablePtr a) where ...@@ -662,7 +755,7 @@ instance IArray UArray (StablePtr a) where
-- bogus StablePtr value for initialising a UArray of StablePtr. -- bogus StablePtr value for initialising a UArray of StablePtr.
nullStablePtr :: StablePtr a nullStablePtr :: StablePtr a
nullStablePtr = StablePtr (unsafeCoerce# 0#) nullStablePtr = StablePtr (unsafeCoerce# nullAddr#)
instance IArray UArray Int8 where instance IArray UArray Int8 where
{-# INLINE bounds #-} {-# INLINE bounds #-}
...@@ -823,24 +916,27 @@ same way as for 'IArray'), and also over the type of the monad, @m@, ...@@ -823,24 +916,27 @@ same way as for 'IArray'), and also over the type of the monad, @m@,
in which the mutable array will be manipulated. in which the mutable array will be manipulated.
-} -}
class (Monad m) => MArray a e m where class (Monad m) => MArray a e m where
-- | Returns the bounds of the array (lowest,highest).
-- | Returns the bounds of the array
getBounds :: Ix i => a i e -> m (i,i) getBounds :: Ix i => a i e -> m (i,i)
-- | Returns the number of elements in the array -- | Returns the number of elements in the array.
getNumElements :: Ix i => a i e -> m Int getNumElements :: Ix i => a i e -> m Int
-- | Builds a new array, with every element initialised to the supplied -- | Builds a new array, with every element initialised to the supplied
-- value. -- value. The first and second element of the tuple specifies the lowest
-- and highest index, respectively.
newArray :: Ix i => (i,i) -> e -> m (a i e) newArray :: Ix i => (i,i) -> e -> m (a i e)
-- | Builds a new array, with every element initialised to an -- | Builds a new array, with every element initialised to an
-- undefined value. In a monadic context in which operations must -- undefined value. In a monadic context in which operations must
-- be deterministic (e.g. the ST monad), the array elements are -- be deterministic (e.g. the ST monad), the array elements are
-- initialised to a fixed but undefined value, such as zero. -- initialised to a fixed but undefined value, such as zero.
-- The first and second element of the tuple specifies the lowest
-- and highest index, respectively.
newArray_ :: Ix i => (i,i) -> m (a i e) newArray_ :: Ix i => (i,i) -> m (a i e)
-- | Builds a new array, with every element initialised to an undefined -- | Builds a new array, with every element initialised to an undefined
-- value. -- value. The first and second element of the tuple specifies the lowest
-- and highest index, respectively.
unsafeNewArray_ :: Ix i => (i,i) -> m (a i e) unsafeNewArray_ :: Ix i => (i,i) -> m (a i e)
unsafeRead :: Ix i => a i e -> Int -> m e unsafeRead :: Ix i => a i e -> Int -> m e
...@@ -877,6 +973,8 @@ class (Monad m) => MArray a e m where ...@@ -877,6 +973,8 @@ class (Monad m) => MArray a e m where
-- default initialisation with undefined values if we *do* know the -- default initialisation with undefined values if we *do* know the
-- initial value and it is constant for all elements. -- initial value and it is constant for all elements.
{-# MINIMAL getBounds, getNumElements, (newArray | unsafeNewArray_), unsafeRead, unsafeWrite #-}
instance MArray IOArray e IO where instance MArray IOArray e IO where
{-# INLINE getBounds #-} {-# INLINE getBounds #-}
getBounds (IOArray marr) = stToIO $ getBounds marr getBounds (IOArray marr) = stToIO $ getBounds marr
...@@ -886,19 +984,39 @@ instance MArray IOArray e IO where ...@@ -886,19 +984,39 @@ instance MArray IOArray e IO where
unsafeRead = unsafeReadIOArray unsafeRead = unsafeReadIOArray
unsafeWrite = unsafeWriteIOArray unsafeWrite = unsafeWriteIOArray
{-# INLINE newListArray #-} {-# INLINE newListArray #-} -- See Note [Inlining and fusion]
-- | Constructs a mutable array from a list of initial elements. -- | Constructs a mutable array from a list of initial elements.
-- The list gives the elements of the array in ascending order -- The list gives the elements of the array in ascending order
-- beginning with the lowest index. -- beginning with the lowest index. The first and second element
-- of the tuple specifies the lowest and highest index, respectively.
newListArray :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e) newListArray :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
newListArray (l,u) es = do newListArray (l,u) es = do
marr <- newArray_ (l,u) marr <- newArray_ (l,u)
let n = safeRangeSize (l,u) let n = safeRangeSize (l,u)
let fillFromList i xs | i == n = return () f x k i
| otherwise = case xs of | i == n = return ()
[] -> return () | otherwise = unsafeWrite marr i x >> k (i+1)
y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys foldr f (\ !_i -> return ()) es 0
fillFromList 0 es -- The bang above is important for GHC for unbox the Int.
return marr
{-# INLINE newGenArray #-}
-- | Constructs a mutable array using a generator function.
-- It invokes the generator function in ascending order of the indices.
--
-- @since 0.5.6.0
newGenArray :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
newGenArray bnds f = do
let n = safeRangeSize bnds
marr <- unsafeNewArray_ bnds
let g ix k i
| i == n = return ()
| otherwise = do
x <- f ix
unsafeWrite marr i x
k (i+1)
foldr g (\ !_i -> return ()) (range bnds) 0
-- The bang above is important for GHC for unbox the Int.
return marr return marr
{-# INLINE readArray #-} {-# INLINE readArray #-}
...@@ -917,6 +1035,31 @@ writeArray marr i e = do ...@@ -917,6 +1035,31 @@ writeArray marr i e = do
n <- getNumElements marr n <- getNumElements marr
unsafeWrite marr (safeIndex (l,u) n i) e unsafeWrite marr (safeIndex (l,u) n i) e
{-# INLINE modifyArray #-}
-- | Modify an element in a mutable array
--
-- @since 0.5.6.0
modifyArray :: (MArray a e m, Ix i) => a i e -> i -> (e -> e) -> m ()
modifyArray marr i f = do
(l,u) <- getBounds marr
n <- getNumElements marr
let idx = safeIndex (l,u) n i
x <- unsafeRead marr idx
unsafeWrite marr idx (f x)
{-# INLINE modifyArray' #-}
-- | Modify an element in a mutable array. Strict in the written element.
--
-- @since 0.5.6.0
modifyArray' :: (MArray a e m, Ix i) => a i e -> i -> (e -> e) -> m ()
modifyArray' marr i f = do
(l,u) <- getBounds marr
n <- getNumElements marr
let idx = safeIndex (l,u) n i
x <- unsafeRead marr idx
let !x' = f x
unsafeWrite marr idx x'
{-# INLINE getElems #-} {-# INLINE getElems #-}
-- | Return a list of all the elements of a mutable array -- | Return a list of all the elements of a mutable array
getElems :: (MArray a e m, Ix i) => a i e -> m [e] getElems :: (MArray a e m, Ix i) => a i e -> m [e]
...@@ -960,6 +1103,70 @@ mapIndices (l',u') f marr = do ...@@ -960,6 +1103,70 @@ mapIndices (l',u') f marr = do
| i' <- range (l',u')] | i' <- range (l',u')]
return marr' return marr'
-- | Strict accumulating left-associative fold.
--
-- @since 0.5.8.0
foldlMArray' :: (MArray a e m, Ix i) => (b -> e -> b) -> b -> a i e -> m b
foldlMArray' f = foldlMArrayM' (\z x -> pure (f z x))
{-# INLINE foldlMArray' #-}
-- | Strict accumulating right-associative fold.
--
-- @since 0.5.8.0
foldrMArray' :: (MArray a e m, Ix i) => (e -> b -> b) -> b -> a i e -> m b
foldrMArray' f = foldrMArrayM' (\x z -> pure (f x z))
{-# INLINE foldrMArray' #-}
-- | Strict accumulating left-associative monadic fold.
--
-- @since 0.5.8.0
foldlMArrayM' :: (MArray a e m, Ix i) => (b -> e -> m b) -> b -> a i e -> m b
foldlMArrayM' f z0 = \a -> do
!n <- getNumElements a
let go !z i | i >= n = pure z
| otherwise = do
x <- unsafeRead a i
z' <- f z x
go z' (i+1)
go z0 0
{-# INLINE foldlMArrayM' #-}
-- | Strict accumulating right-associative monadic fold.
--
-- @since 0.5.8.0
foldrMArrayM' :: (MArray a e m, Ix i) => (e -> b -> m b) -> b -> a i e -> m b
foldrMArrayM' f z0 = \a -> do
!n <- getNumElements a
let go i !z | i < 0 = pure z
| otherwise = do
x <- unsafeRead a i
z' <- f x z
go (i-1) z'
go (n-1) z0
{-# INLINE foldrMArrayM' #-}
-- | Map elements to monadic actions, sequence them left-to-right, and discard
-- the results.
--
-- @since 0.5.8.0
mapMArrayM_ :: (MArray a e m, Ix i) => (e -> m b) -> a i e -> m ()
mapMArrayM_ f = \a -> do
!n <- getNumElements a
let go i | i >= n = pure ()
| otherwise = do
x <- unsafeRead a i
_ <- f x
go (i+1)
go 0
{-# INLINE mapMArrayM_ #-}
-- | @forMArrayM_@ is 'mapMArrayM_' with its arguments flipped.
--
-- @since 0.5.8.0
forMArrayM_ :: (MArray a e m, Ix i) => a i e -> (e -> m b) -> m ()
forMArrayM_ = flip mapMArrayM_
{-# INLINE forMArrayM_ #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Polymorphic non-strict mutable arrays (ST monad) -- Polymorphic non-strict mutable arrays (ST monad)
...@@ -1349,8 +1556,15 @@ instance MArray (STUArray s) Word64 (ST s) where ...@@ -1349,8 +1556,15 @@ instance MArray (STUArray s) Word64 (ST s) where
bOOL_SCALE, wORD_SCALE, dOUBLE_SCALE, fLOAT_SCALE :: Int# -> Int# bOOL_SCALE, wORD_SCALE, dOUBLE_SCALE, fLOAT_SCALE :: Int# -> Int#
bOOL_SCALE n# = bOOL_SCALE n# =
-- + 7 to handle case where n is not divisible by 8 -- Round the number of bits up to the next whole-word-aligned number
(n# +# 7#) `uncheckedIShiftRA#` 3# -- of bytes to avoid ghc#23132; the addition can signed-overflow but
-- that's OK because it will not unsigned-overflow and the logical
-- right-shift brings us back in-bounds
#if SIZEOF_HSWORD == 4
((n# +# 31#) `uncheckedIShiftRL#` 5#) `uncheckedIShiftL#` 2#
#elif SIZEOF_HSWORD == 8
((n# +# 63#) `uncheckedIShiftRL#` 6#) `uncheckedIShiftL#` 3#
#endif
wORD_SCALE n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSWORD wORD_SCALE n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSWORD
dOUBLE_SCALE n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSDOUBLE dOUBLE_SCALE n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSDOUBLE
fLOAT_SCALE n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSFLOAT fLOAT_SCALE n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSFLOAT
...@@ -1398,12 +1612,12 @@ freeze marr = do ...@@ -1398,12 +1612,12 @@ freeze marr = do
freezeSTUArray :: STUArray s i e -> ST s (UArray i e) freezeSTUArray :: STUArray s i e -> ST s (UArray i e)
freezeSTUArray (STUArray l u n marr#) = ST $ \s1# -> freezeSTUArray (STUArray l u n marr#) = ST $ \s1# ->
case sizeofMutableByteArray# marr# of { n# -> case getSizeofMutableByteArray# marr# s1# of { (# s2#, n# #) ->
case newByteArray# n# s1# of { (# s2#, marr'# #) -> case newByteArray# n# s2# of { (# s3#, marr'# #) ->
case memcpy_freeze marr'# marr# (fromIntegral (I# n#)) of { IO m -> case memcpy_freeze marr'# marr# (fromIntegral (I# n#)) of { IO m ->
case unsafeCoerce# m s2# of { (# s3#, _ #) -> case unsafeCoerce# m s3# of { (# s4#, _ #) ->
case unsafeFreezeByteArray# marr'# s3# of { (# s4#, arr# #) -> case unsafeFreezeByteArray# marr'# s4# of { (# s5#, arr# #) ->
(# s4#, UArray l u n arr# #) }}}}} (# s5#, UArray l u n arr# #) }}}}}
foreign import ccall unsafe "memcpy" foreign import ccall unsafe "memcpy"
memcpy_freeze :: MutableByteArray# s -> MutableByteArray# s -> CSize memcpy_freeze :: MutableByteArray# s -> MutableByteArray# s -> CSize
...@@ -1580,3 +1794,13 @@ unsafeFreezeIOArray (IOArray marr) = stToIO (ArrST.unsafeFreezeSTArray marr) ...@@ -1580,3 +1794,13 @@ unsafeFreezeIOArray (IOArray marr) = stToIO (ArrST.unsafeFreezeSTArray marr)
castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b) castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
castSTUArray (STUArray l u n marr#) = return (STUArray l u n marr#) castSTUArray (STUArray l u n marr#) = return (STUArray l u n marr#)
--------------------------------------------------------------------------------
-- Note [Inlining and fusion]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Many functions in this module are marked INLINE because they consume their
-- input with `foldr`. By inlining them, it is possible that the `foldr` will
-- meet a `build` from the call site, and beneficial fusion will take place.
-- That is, they become "good consumers". See array issue #8 for data showing
-- the perf improvement that comes with fusion.
...@@ -29,14 +29,26 @@ module Data.Array.IArray ( ...@@ -29,14 +29,26 @@ module Data.Array.IArray (
array, -- :: (IArray a e, Ix i) => (i,i) -> [(i, e)] -> a i e 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 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 accumArray, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> e -> (i,i) -> [(i, e')] -> a i e
genArray, -- :: (IArray a e, Ix i) => (i,i) -> (i -> e) -> a i e
-- * Accessing arrays -- * Accessing arrays
(!), -- :: (IArray a e, Ix i) => a i e -> i -> e (!), -- :: (IArray a e, Ix i) => a i e -> i -> e
(!?), -- :: (IArray a e, Ix i) => a i e -> i -> Maybe e
bounds, -- :: (HasBounds a, Ix i) => a i e -> (i,i) bounds, -- :: (HasBounds a, Ix i) => a i e -> (i,i)
indices, -- :: (HasBounds a, Ix i) => a i e -> [i] indices, -- :: (HasBounds a, Ix i) => a i e -> [i]
elems, -- :: (IArray a e, Ix i) => a i e -> [e] elems, -- :: (IArray a e, Ix i) => a i e -> [e]
assocs, -- :: (IArray a e, Ix i) => a i e -> [(i, e)] assocs, -- :: (IArray a e, Ix i) => a i e -> [(i, e)]
-- * Array folds
foldrArray,
foldlArray',
foldlArray,
foldrArray',
traverseArray_,
forArray_,
foldlArrayM',
foldrArrayM',
-- * Incremental array updates -- * Incremental array updates
(//), -- :: (IArray a e, Ix i) => a i e -> [(i, e)] -> a i e (//), -- :: (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 accum, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(i, e')] -> a i e
......
{-# LANGUAGE MagicHash, UnliftedFFITypes #-} {-# LANGUAGE MagicHash, Trustworthy, UnliftedFFITypes #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
, RoleAnnotations , RoleAnnotations
#-} #-}
{-# OPTIONS_HADDOCK hide #-} {-# OPTIONS_HADDOCK not-home #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : Data.Array.IO.Internal -- Module : Data.Array.IO.Internal
...@@ -17,6 +17,18 @@ ...@@ -17,6 +17,18 @@
-- --
-- Mutable boxed and unboxed arrays in the IO monad. -- Mutable boxed and unboxed arrays in the IO monad.
-- --
-- = WARNING
--
-- This module is considered __internal__.
--
-- The Package Versioning Policy __does not apply__.
--
-- The contents of this module may change __in any way whatsoever__
-- and __without any warning__ between minor versions of this package.
--
-- Authors importing this module are expected to track development
-- closely.
--
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module Data.Array.IO.Internals ( module Data.Array.IO.Internals (
......
{-# LANGUAGE Trustworthy #-} {-# LANGUAGE Safe #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
......
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP, Trustworthy #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
...@@ -27,10 +27,21 @@ module Data.Array.MArray ( ...@@ -27,10 +27,21 @@ module Data.Array.MArray (
newArray, -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e) newArray, -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)
newArray_, -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e) newArray_, -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)
newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e) newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
newGenArray, -- :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
-- * Reading and writing mutable arrays -- * Reading and writing mutable arrays
readArray, -- :: (MArray a e m, Ix i) => a i e -> i -> m e readArray, -- :: (MArray a e m, Ix i) => a i e -> i -> m e
writeArray, -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m () writeArray, -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
modifyArray,
modifyArray',
-- * Array folds
foldlMArray',
foldrMArray',
mapMArrayM_,
forMArrayM_,
foldlMArrayM',
foldrMArrayM',
-- * Derived arrays -- * Derived arrays
mapArray, -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e) mapArray, -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)
......
...@@ -29,11 +29,20 @@ module Data.Array.MArray.Safe ( ...@@ -29,11 +29,20 @@ module Data.Array.MArray.Safe (
newArray, -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e) newArray, -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)
newArray_, -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e) newArray_, -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)
newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e) newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
newGenArray, -- :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
-- * Reading and writing mutable arrays -- * Reading and writing mutable arrays
readArray, -- :: (MArray a e m, Ix i) => a i e -> i -> m e readArray, -- :: (MArray a e m, Ix i) => a i e -> i -> m e
writeArray, -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m () writeArray, -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
-- * Array folds
foldlMArray',
foldrMArray',
mapMArrayM_,
forMArrayM_,
foldlMArrayM',
foldrMArrayM',
-- * Derived arrays -- * Derived arrays
mapArray, -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e) mapArray, -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)
mapIndices, -- :: (MArray a e m, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> m (a i e) mapIndices, -- :: (MArray a e m, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> m (a i e)
......
{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RankNTypes, Trustworthy #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : Data.Array.ST -- Module : Data.Array.ST
......
{-# LANGUAGE Trustworthy #-} {-# LANGUAGE Safe #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : Data.Array.ST.Safe -- Module : Data.Array.ST.Safe
......
{-# LANGUAGE Trustworthy #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : Data.Array.Storable -- Module : Data.Array.Storable
......
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, RoleAnnotations #-} {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, RoleAnnotations #-}
{-# OPTIONS_HADDOCK hide #-} {-# OPTIONS_HADDOCK not-home #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : Data.Array.Storable.Internals -- Module : Data.Array.Storable.Internals
...@@ -13,6 +13,18 @@ ...@@ -13,6 +13,18 @@
-- Actual implementation of "Data.Array.Storable". -- Actual implementation of "Data.Array.Storable".
-- --
-- @since 0.4.0.0 -- @since 0.4.0.0
--
-- = WARNING
--
-- This module is considered __internal__.
--
-- The Package Versioning Policy __does not apply__.
--
-- The contents of this module may change __in any way whatsoever__
-- and __without any warning__ between minor versions of this package.
--
-- Authors importing this module are expected to track development
-- closely.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module Data.Array.Storable.Internals ( module Data.Array.Storable.Internals (
......
cabal-version: >= 1.10 cabal-version: >= 1.10
name: array name: array
version: 0.5.4.0 version: 0.5.8.0
-- NOTE: Don't forget to update ./changelog.md -- NOTE: Don't forget to update ./changelog.md
license: BSD3 license: BSD3
license-file: LICENSE license-file: LICENSE
maintainer: libraries@haskell.org maintainer: libraries@haskell.org
bug-reports: https://gitlab.haskell.org/ghc/packages/array/issues bug-reports: https://github.com/haskell/array/issues
synopsis: Mutable and immutable arrays synopsis: Mutable and immutable arrays
category: Data Structures category: Data Structures
build-type: Simple build-type: Simple
...@@ -21,7 +21,7 @@ extra-source-files: changelog.md ...@@ -21,7 +21,7 @@ extra-source-files: changelog.md
source-repository head source-repository head
type: git type: git
location: http://gitlab.haskell.org/ghc/packages/array.git location: https://github.com/haskell/array.git
library library
default-language: Haskell2010 default-language: Haskell2010
...@@ -36,7 +36,7 @@ library ...@@ -36,7 +36,7 @@ library
Trustworthy, Trustworthy,
UnboxedTuples, UnboxedTuples,
UnliftedFFITypes UnliftedFFITypes
build-depends: base >= 4.9 && < 4.17 build-depends: base >= 4.9 && < 4.23
ghc-options: -Wall ghc-options: -Wall
exposed-modules: exposed-modules:
Data.Array Data.Array
......
# Changelog for [`array` package](http://hackage.haskell.org/package/array) # Changelog for [`array` package](http://hackage.haskell.org/package/array)
## 0.5.8.0 *Aug 2024*
### Added
* Folds for arrays: `foldrArray`, `foldlArray'`, `foldlArray`, `foldrArray'`,
`traverseArray_`, `forArray_`, `foldlArrayM'`, `foldrArrayM'`.
* Folds for mutable arrays: `foldlMArray'`, `foldrMArray'`, `mapMArrayM_`,
`forMArrayM_`, `foldlMArrayM'`, `foldrMArrayM'`.
### Fixed
* Fix a build error that the package can't be buildable before `base-4.14`.
## 0.5.7.0 *April 2024*
### Changed
* `MArray` now has a `MINIMAL` pragma
* Optimisation of `newListArray` and `newGenArray`
## 0.5.6.0 *July 2023*
### Changed
* `listArray` and `newListArray` are now good consumers of the input list
* Bump base bound to `<4.20`
### Added
* Add the `genArray` and `newGenArray` function
* Add `Data.Array.MArray.modifyArray` and `Data.Array.MArray.modifyArray'`
These are also exposed from `Data.Array.IO`, `Data.Array.ST`, and
`Data.Array.Storable`.
* Add `Data.Array.IArray.(!?)`
### Fixed
* Array docs regarding constructing arrays
* Update note [Inlining and fusion]
* Unboxed Bool arrays no longer cause spurious alarms
when used with `-fcheck-prim-bounds`
* Replace Haddock hide pragma with not-home to make the Haddocks more readable
## 0.5.5.0 *February 2022*
* Compatibility with GHC's new JavaScript backend.
## 0.5.4.0 *July 2019* ## 0.5.4.0 *July 2019*
* Add a `Read` instance for `UArray` * Add a `Read` instance for `UArray`
## 0.5.3.0 *Oct 2018* ## 0.5.3.0 *Oct 2018*
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
#include "MachDeps.h" #include "MachDeps.h"
import Control.Exception
import Data.Array.MArray import Data.Array.MArray
import Data.Array.IO import Data.Array.IO
import Data.Word import Data.Word
main :: IO () main :: IO ()
main = do main = handle (\(exc :: SomeException) -> print exc) $ do
-- This should fail due to integer overflow -- This should fail due to integer overflow
#if WORD_SIZE_IN_BITS == 64 #if WORD_SIZE_IN_BITS == 64
m <- newArray_ (0,2^62-1) :: IO (IOUArray Int Word32) -- allocates 0 bytes m <- newArray_ (0,2^62-1) :: IO (IOUArray Int Word32) -- allocates 0 bytes
......
T229: Data.Array.Base.safe_scale: Overflow; scale: 4, n: 1073741824
CallStack (from HasCallStack):
error, called at libraries/array/Data/Array/Base.hs:1356:20 in array-0.5.1.2:Data.Array.Base
T229: Data.Array.Base.safe_scale: Overflow; scale: 4, n: 4611686018427387904
CallStack (from HasCallStack):
error, called at libraries/array/Data/Array/Base.hs:1356:20 in array-0.5.1.2:Data.Array.Base
Data.Array.Base.safe_scale: Overflow; scale: 4, n: 1073741824
Data.Array.Base.safe_scale: Overflow; scale: 4, n: 4611686018427387904
...@@ -6,4 +6,4 @@ test('array001', [ ...@@ -6,4 +6,4 @@ test('array001', [
compile_and_run, ['']) compile_and_run, [''])
test('T9220', filter_stdout_lines('.*type role .*'), ghci_script, ['T9220.script']) test('T9220', filter_stdout_lines('.*type role .*'), ghci_script, ['T9220.script'])
test('T229', [exit_code(1)], compile_and_run, ['']) test('T229', normal, compile_and_run, [''])