{-# LANGUAGE FlexibleContexts #-}
module Simulation.Aivika.Trans.Vector
(Vector,
newVector,
copyVector,
vectorCount,
appendVector,
readVector,
writeVector,
vectorBinarySearch,
vectorInsert,
vectorDeleteAt,
vectorDeleteRange,
vectorDelete,
vectorDeleteBy,
vectorIndex,
vectorIndexBy,
vectorContains,
vectorContainsBy,
freezeVector) where
import Data.Array
import Control.Monad
import Simulation.Aivika.Trans.Simulation
import Simulation.Aivika.Trans.Event
import Simulation.Aivika.Trans.Ref.Base.Lazy
data Vector m a = Vector { vectorArrayRef :: Ref m (Array Int (Ref m a)),
vectorCountRef :: Ref m Int,
vectorCapacityRef :: Ref m Int }
newVector :: MonadRef m => Simulation m (Vector m a)
{-# INLINABLE newVector #-}
newVector =
do xs <- forM [0 .. 4 - 1] $ \i -> newRef undefined
let arr = array (0, 4 - 1) $ zip [0..] xs
arrRef <- newRef $! arr
countRef <- newRef $! 0
capacityRef <- newRef $! 4
return Vector { vectorArrayRef = arrRef,
vectorCountRef = countRef,
vectorCapacityRef = capacityRef }
copyVector :: MonadRef m => Vector m a -> Event m (Vector m a)
{-# INLINABLE copyVector #-}
copyVector vector =
do arr <- readRef (vectorArrayRef vector)
count <- readRef (vectorCountRef vector)
xs' <-
forM [0 .. count - 1] $ \i ->
do x <- readRef (arr ! i)
liftSimulation $ newRef x
let arr' = array (0, count - 1) $ zip [0..] xs'
arrRef' <- liftSimulation $ newRef $! arr'
countRef' <- liftSimulation $ newRef $! count
capacityRef' <- liftSimulation $ newRef $! count
return Vector { vectorArrayRef = arrRef',
vectorCountRef = countRef',
vectorCapacityRef = capacityRef' }
vectorEnsureCapacity :: MonadRef m => Vector m a -> Int -> Event m ()
{-# INLINABLE vectorEnsureCapacity #-}
vectorEnsureCapacity vector capacity =
do capacity' <- readRef (vectorCapacityRef vector)
when (capacity' < capacity) $
do arr' <- readRef (vectorArrayRef vector)
count' <- readRef (vectorCountRef vector)
let capacity'' = max (2 * capacity') capacity
xs'' <-
forM [0 .. capacity'' - 1] $ \i ->
liftSimulation $ newRef undefined
let arr'' = array (0, capacity'' - 1) $ zip [0..] xs''
forM_ [0 .. count' - 1] $ \i ->
do x <- readRef (arr' ! i)
writeRef (arr'' ! i) x
writeRef (vectorArrayRef vector) $! arr''
writeRef (vectorCapacityRef vector) $! capacity''
vectorCount :: MonadRef m => Vector m a -> Event m Int
{-# INLINABLE vectorCount #-}
vectorCount vector = readRef (vectorCountRef vector)
appendVector :: MonadRef m => Vector m a -> a -> Event m ()
{-# INLINABLE appendVector #-}
appendVector vector item =
do count <- readRef (vectorCountRef vector)
vectorEnsureCapacity vector (count + 1)
arr <- readRef (vectorArrayRef vector)
writeRef (arr ! count) $! item
writeRef (vectorCountRef vector) $! (count + 1)
readVector :: MonadRef m => Vector m a -> Int -> Event m a
{-# INLINABLE readVector #-}
readVector vector index =
do arr <- readRef (vectorArrayRef vector)
readRef (arr ! index)
writeVector :: MonadRef m => Vector m a -> Int -> a -> Event m ()
{-# INLINABLE writeVector #-}
writeVector vector index item =
do arr <- readRef (vectorArrayRef vector)
writeRef (arr ! index) $! item
vectorBinarySearch' :: (MonadRef m, Ord a) => Array Int (Ref m a) -> a -> Int -> Int -> Event m Int
{-# INLINABLE vectorBinarySearch' #-}
vectorBinarySearch' arr item left right =
if left > right
then return $ - (right + 1) - 1
else
do let index = (left + right) `div` 2
curr <- readRef (arr ! index)
if item < curr
then vectorBinarySearch' arr item left (index - 1)
else if item == curr
then return index
else vectorBinarySearch' arr item (index + 1) right
vectorBinarySearch :: (MonadRef m, Ord a) => Vector m a -> a -> Event m Int
{-# INLINABLE vectorBinarySearch #-}
vectorBinarySearch vector item =
do arr <- readRef (vectorArrayRef vector)
count <- readRef (vectorCountRef vector)
vectorBinarySearch' arr item 0 (count - 1)
freezeVector :: MonadRef m => Vector m a -> Event m (Array Int a)
{-# INLINABLE freezeVector #-}
freezeVector vector =
do arr <- readRef (vectorArrayRef vector)
count <- readRef (vectorCountRef vector)
xs' <-
forM [0 .. count - 1] $ \i ->
readRef (arr ! i)
let arr' = array (0, count - 1) $ zip [0..] xs'
return arr'
vectorInsert :: MonadRef m => Vector m a -> Int -> a -> Event m ()
{-# INLINABLE vectorInsert #-}
vectorInsert vector index item =
do count <- readRef (vectorCountRef vector)
when (index < 0) $
error $
"Index cannot be " ++
"negative: vectorInsert."
when (index > count) $
error $
"Index cannot be greater " ++
"than the count: vectorInsert."
vectorEnsureCapacity vector (count + 1)
arr <- readRef (vectorArrayRef vector)
forM_ [count, count - 1 .. index + 1] $ \i ->
do x <- readRef (arr ! (i - 1))
writeRef (arr ! i) x
writeRef (arr ! index) $! item
writeRef (vectorCountRef vector) $! (count + 1)
vectorDeleteAt :: MonadRef m => Vector m a -> Int -> Event m ()
{-# INLINABLE vectorDeleteAt #-}
vectorDeleteAt vector index =
do count <- readRef (vectorCountRef vector)
when (index < 0) $
error $
"Index cannot be " ++
"negative: vectorDeleteAt."
when (index >= count) $
error $
"Index must be less " ++
"than the count: vectorDeleteAt."
arr <- readRef (vectorArrayRef vector)
forM_ [index, index + 1 .. count - 2] $ \i ->
do x <- readRef (arr ! (i + 1))
writeRef (arr ! i) x
writeRef (arr ! (count - 1)) undefined
writeRef (vectorCountRef vector) $! (count - 1)
vectorDeleteRange :: MonadRef m
=> Vector m a
-> Int
-> Int
-> Event m ()
{-# INLINABLE vectorDeleteRange #-}
vectorDeleteRange vector index len =
do count <- readRef (vectorCountRef vector)
when (index < 0) $
error $
"The first index cannot be " ++
"negative: vectorDeleteRange."
when (index + len - 1 >= count) $
error $
"The last index must be less " ++
"than the count: vectorDeleteRange."
when (len < 0) $
error "Negative range length: vectorDeleteRange."
arr <- readRef (vectorArrayRef vector)
forM_ [index, index + 1 .. (count - len) - 1] $ \i ->
do x <- readRef (arr ! (i + len))
writeRef (arr ! i) x
forM_ [(count - len) .. count - 1] $ \i ->
writeRef (arr ! i) undefined
writeRef (vectorCountRef vector) $! (count - len)
vectorIndex :: (MonadRef m, Eq a) => Vector m a -> a -> Event m Int
{-# INLINABLE vectorIndex #-}
vectorIndex vector item =
do count <- readRef (vectorCountRef vector)
arr <- readRef (vectorArrayRef vector)
let loop index =
if index >= count
then return $ -1
else do x <- readRef (arr ! index)
if item == x
then return index
else loop $ index + 1
loop 0
vectorIndexBy :: MonadRef m => Vector m a -> (a -> Bool) -> Event m Int
{-# INLINABLE vectorIndexBy #-}
vectorIndexBy vector pred =
do count <- readRef (vectorCountRef vector)
arr <- readRef (vectorArrayRef vector)
let loop index =
if index >= count
then return $ -1
else do x <- readRef (arr ! index)
if pred x
then return index
else loop $ index + 1
loop 0
vectorDelete :: (MonadRef m, Eq a) => Vector m a -> a -> Event m Bool
{-# INLINABLE vectorDelete #-}
vectorDelete vector item =
do index <- vectorIndex vector item
if index >= 0
then do vectorDeleteAt vector index
return True
else return False
vectorDeleteBy :: MonadRef m => Vector m a -> (a -> Bool) -> Event m (Maybe a)
{-# INLINABLE vectorDeleteBy #-}
vectorDeleteBy vector pred =
do index <- vectorIndexBy vector pred
if index >= 0
then do a <- readVector vector index
vectorDeleteAt vector index
return (Just a)
else return Nothing
vectorContains :: (MonadRef m, Eq a) => Vector m a -> a -> Event m Bool
{-# INLINABLE vectorContains #-}
vectorContains vector item =
do index <- vectorIndex vector item
return (index >= 0)
vectorContainsBy :: MonadRef m => Vector m a -> (a -> Bool) -> Event m (Maybe a)
{-# INLINABLE vectorContainsBy #-}
vectorContainsBy vector pred =
do index <- vectorIndexBy vector pred
if index >= 0
then do a <- readVector vector index
return (Just a)
else return Nothing