module Data.Array.Util
(
updateElems
, updateElemsIx
, updateElemsM
, updateElemsIxM
, updateElemsOn
, updateElemsIxOn
, updateElemsOnM
, updateElemsIxOnM
, updateElemsWithin
, updateElemsWithinIx
, updateElemsWithinM
, updateElemsWithinIxM
, updateElemsSlice
, updateElemsSliceM
) 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(updateElemsWithin)
updateElemsWithin :: (MArray a e m, Ix i)
=> (e -> e)
-> (i,i)
-> a i e
-> m ()
updateElemsWithin 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 updateElemsWithin"
forM_ indicies (update arr f)
INLINE(updateElemsWithinM)
updateElemsWithinM :: (MArray a e m, Ix i) => (e -> m e) -> (i,i) -> a i e -> m ()
updateElemsWithinM 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 updateElemsWithin"
forM_ indicies (updateM arr f)
INLINE(updateElemsWithinIx)
updateElemsWithinIx :: (MArray a e m, Ix i, Show i) => (i -> e -> e) -> (i,i) -> a i e -> m ()
updateElemsWithinIx 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 updateElemsWithinIx"
go indicies rnge
INLINE(updateElemsWithinIxM)
updateElemsWithinIxM :: (MArray a e m, Ix i, Show i) => (i -> e -> m e) -> (i,i) -> a i e -> m ()
updateElemsWithinIxM 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 updateElemsWithinIx"
go indicies rnge
INLINE(updateElemsOn)
updateElemsOn :: (MArray a e m, Ix i)
=> (e -> e)
-> [i]
-> a i e
-> m ()
updateElemsOn 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(updateElemsOnM)
updateElemsOnM :: (MArray a e m, Ix i) => (e -> m e) -> [i] -> a i e -> m ()
updateElemsOnM 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(updateElemsIxOn)
updateElemsIxOn :: (MArray a e m, Ix i) => (i -> e -> e) -> [i] -> a i e -> m ()
updateElemsIxOn 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(updateElemsIxOnM)
updateElemsIxOnM :: (MArray a e m, Ix i) => (i -> e -> m e) -> [i] -> a i e -> m ()
updateElemsIxOnM 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(updateElemsSlice)
updateElemsSlice :: (MArray a e m, Ix i)
=> (e -> e)
-> (i,i)
-> a i e
-> m ()
updateElemsSlice 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 updateElemsSlice")
forM_ [start..finish] (update arr f)
INLINE(updateElemsSliceM)
updateElemsSliceM :: (MArray a e m, Ix i) => (e -> m e) -> (i,i) -> a i e -> m ()
updateElemsSliceM 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 updateElemsSlice")
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