module Data.Array.Util
(
updateElems
, updateElemsIx
, updateElemsM
, updateElemsIxM
, updateOn
, updateOnIx
, updateOnM
, updateOnIxM
, updateWithin
, updateWithinIx
, updateWithinM
, updateWithinIxM
, updateSlice
, updateSliceM
) where
import GHC.Arr
import Data.Array.Base
import Control.Monad
import Control.Exception
#ifdef __GLASGOW_HASKELL__
#if __GLASGOW_HASKELL__ >= 700
#define INLINE(x) {-# INLINABLE x #-}
#else -- 700
#define INLINE(x) {-# INLINE x #-}
#endif -- 700
#else
#define INLINE(x) {- not inlined -}
#endif -- __GLASGOW_HASKELL__
INLINE(updateElems)
updateElems :: (MArray a e m, Ix i)
=> (e -> e)
-> a i e
-> m ()
updateElems f arr = do
bnds@(_ , end') <- getBounds arr
let !end = unsafeIndex bnds end'
forM_ [0..end] (update arr f)
INLINE(updateElemsM)
updateElemsM :: (MArray a e m, Ix i) => (e -> m e) -> a i e -> m ()
updateElemsM f arr = do
bnds@(_ , end') <- getBounds arr
let !end = unsafeIndex bnds end'
forM_ [0..end] (updateM arr f)
INLINE(updateElemsIx)
updateElemsIx :: (MArray a e m, Ix i) => (i -> e -> e) -> a i e -> m ()
updateElemsIx f arr = do
bnds@(_ , end') <- getBounds arr
let !end = unsafeIndex bnds end'
go !i (x:xs) | i <= end = updateIx arr f i x >> go (i+1) xs
go _ _ = return ()
go 0 (range bnds)
INLINE(updateElemsIxM)
updateElemsIxM :: (MArray a e m, Ix i) => (i -> e -> m e) -> a i e -> m ()
updateElemsIxM f arr = do
bnds@(_ , end') <- getBounds arr
let !end = unsafeIndex bnds end'
go !i (x:xs) | i <= end = updateIxM arr f i x >> go (i+1) xs
go _ _ = return ()
go 0 (range bnds)
INLINE(updateWithin)
updateWithin :: (MArray a e m, Ix i)
=> (e -> e)
-> (i,i)
-> a i e
-> m ()
updateWithin f (start, finish) arr = do
bnds <- getBounds arr
let !ok = inRange bnds start && inRange bnds finish
indicies = map (unsafeIndex bnds) $ range (start, finish)
when (not ok) $ throw $ IndexOutOfBounds $ "Data.Array.Util updateWithin"
forM_ indicies (update arr f)
INLINE(updateWithinM)
updateWithinM :: (MArray a e m, Ix i) => (e -> m e) -> (i,i) -> a i e -> m ()
updateWithinM f (start, finish) arr = do
bnds <- getBounds arr
let !ok = inRange bnds start && inRange bnds finish
indicies = map (unsafeIndex bnds) $ range (start, finish)
when (not ok) $ throw $ IndexOutOfBounds $ "Data.Array.Util updateWithin"
forM_ indicies (updateM arr f)
INLINE(updateWithinIx)
updateWithinIx :: (MArray a e m, Ix i, Show i) => (i -> e -> e) -> (i,i) -> a i e -> m ()
updateWithinIx f (start, finish) arr = do
bnds <- getBounds arr
let !ok = inRange bnds start && inRange bnds finish
rnge = range (start, finish)
indicies = map (unsafeIndex bnds) rnge
go (!i:is) (x:xs) = updateIx arr f i x >> go is xs
go _ _ = return ()
when (not ok) $ throw $ IndexOutOfBounds $ "Data.Array.Util updateWithinIx"
go indicies rnge
INLINE(updateWithinIxM)
updateWithinIxM :: (MArray a e m, Ix i, Show i) => (i -> e -> m e) -> (i,i) -> a i e -> m ()
updateWithinIxM f (start, finish) arr = do
bnds <- getBounds arr
let !ok = inRange bnds start && inRange bnds finish
rnge = range (start, finish)
indicies = map (unsafeIndex bnds) rnge
go (!i:is) (x:xs) = updateIxM arr f i x >> go is xs
go _ _ = return ()
when (not ok) $ throw $ IndexOutOfBounds $ "Data.Array.Util updateWithinIx"
go indicies rnge
INLINE(updateOn)
updateOn :: (MArray a e m, Ix i)
=> (e -> e)
-> [i]
-> a i e
-> m ()
updateOn f xs arr = do
bnds <- getBounds arr
let !ok = all (inRange bnds) xs
toOffset = unsafeIndex bnds
when (not ok) $ throw (IndexOutOfBounds $ "Data.Array.Util updateElems'")
forM_ (map toOffset xs) (update arr f)
INLINE(updateOnM)
updateOnM :: (MArray a e m, Ix i) => (e -> m e) -> [i] -> a i e -> m ()
updateOnM f xs arr = do
bnds <- getBounds arr
let !ok = all (inRange bnds) xs
toOffset = unsafeIndex bnds
when (not ok) $ throw (IndexOutOfBounds $ "Data.Array.Util updateElems'")
forM_ (map toOffset xs) (updateM arr f)
INLINE(updateOnIx)
updateOnIx :: (MArray a e m, Ix i) => (i -> e -> e) -> [i] -> a i e -> m ()
updateOnIx f indexes arr = do
bnds@(_, hi) <- getBounds arr
let toOffset = unsafeIndex bnds
ixs = map toOffset indexes
end = toOffset hi
!ok = all (\x -> x >= 0 && x <= end) ixs
go (!i:is) (x:xs) = updateIx arr f i x >> go is xs
go _ _ = return ()
when (not ok) $ throw (IndexOutOfBounds $ "Data.Array.Util updateElemsIx'")
go ixs indexes
INLINE(updateOnIxM)
updateOnIxM :: (MArray a e m, Ix i) => (i -> e -> m e) -> [i] -> a i e -> m ()
updateOnIxM f indexes arr = do
bnds@(_ , hi) <- getBounds arr
let toOffset = unsafeIndex bnds
!end = toOffset hi
ixs = map toOffset indexes
!ok = all (\x -> x >= 0 && x <= end) ixs
go (!i:is) (x:xs) = updateIxM arr f i x >> go is xs
go _ _ = return ()
when (not ok) $ throw (IndexOutOfBounds $ "Data.Array.Util updateElemsIx'")
go ixs indexes
INLINE(updateSlice)
updateSlice :: (MArray a e m, Ix i)
=> (e -> e)
-> (i,i)
-> a i e
-> m ()
updateSlice f (start', finish') arr = do
bnds@(_ , end') <- getBounds arr
let !end = unsafeIndex bnds end'
!start = unsafeIndex bnds start'
!finish = unsafeIndex bnds finish'
!ok = start >= 0 && start <= end && finish >= 0 && finish <= end
when (not ok) $ throw (IndexOutOfBounds $ "Data.Array.Util updateSlice")
forM_ [start..finish] (update arr f)
INLINE(updateSliceM)
updateSliceM :: (MArray a e m, Ix i) => (e -> m e) -> (i,i) -> a i e -> m ()
updateSliceM f (start', finish') arr = do
bnds@(_ , end') <- getBounds arr
let !end = unsafeIndex bnds end'
!start = unsafeIndex bnds start'
!finish = unsafeIndex bnds finish'
!ok = start >= 0 && start <= end && finish >= 0 && finish <= end
when (not ok) $ throw (IndexOutOfBounds $ "Data.Array.Util updateSlice")
forM_ [start..finish] (updateM arr f)
update :: (MArray a e m, Ix i) => a i e -> (e -> e) -> Int -> m ()
update arr f i = unsafeRead arr i >>= unsafeWrite arr i . f
updateIx :: (MArray a e m, Ix i) => a i e -> (i -> e -> e) -> Int -> i -> m ()
updateIx arr f i x = unsafeRead arr i >>= unsafeWrite arr i . f x
updateM :: (MArray a e m, Ix i) => a i e -> (e -> m e) -> Int -> m ()
updateM arr f i = unsafeRead arr i >>= f >>= unsafeWrite arr i
updateIxM :: (MArray a e m, Ix i) => a i e -> (i -> e -> m e) -> Int -> i -> m ()
updateIxM arr f i x = unsafeRead arr i >>= f x >>= unsafeWrite arr i