mios-1.4.0: SAT/Mios/Vec.hs
{-# LANGUAGE
BangPatterns
, FlexibleContexts
, FlexibleInstances
, FunctionalDependencies
, MultiParamTypeClasses
, TypeFamilies
#-}
{-# LANGUAGE Trustworthy #-}
-- | Abstraction Layer for Mutable Vectors
module SAT.Mios.Vec
(
-- * Vector class
VecFamily (..)
-- * Vectors
, UVector
, Vec (..)
-- * SingleStorage
, SingleStorage (..)
, Bool'
, Double'
, Int'
-- * Stack
, StackFamily (..)
, Stack
, newStackFromList
)
where
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UV
-- | Interface on vectors.
class VecFamily v a | v -> a where
-- | returns the /n/-th value.
getNth ::v -> Int -> IO a
-- | sets the /n/-th value.
setNth :: v -> Int -> a -> IO ()
-- | erases all elements in it.
reset:: v -> IO ()
-- | converts to an Int vector.
asUVector :: (a ~ Int) => v -> UVector Int
-- | returns the /n/-th value (index starts from zero in any case).
-- | swaps two elements.
swapBetween :: v -> Int -> Int -> IO ()
-- | calls the update function.
modifyNth :: v -> (a -> a) -> Int -> IO ()
-- | returns a new vector.
newVec :: Int -> a -> IO v
-- | sets all elements.
setAll :: v -> a -> IO ()
-- | extends the size of stack by /n/; note: values in new elements aren't initialized maybe.
growBy :: v -> Int -> IO v
-- | converts to a list.
asList :: v -> IO [a]
{-# MINIMAL getNth, setNth #-}
reset = error "no default method: reset"
asUVector = error "no default method: asUVector"
swapBetween = error "no default method: swapBetween"
modifyNth = error "no default method: modifyNth"
newVec = error "no default method: newVec"
setAll = error "no default method: setAll"
asList = error "no default method: asList"
growBy = error "no default method: growBy"
{-
-- | (FOR DEBUG) dump the contents.
dump :: Show a => String -> v -> IO String
dump msg v = (msg ++) . show <$> asList v
-}
-------------------------------------------------------------------------------- UVector
-- | A thin abstract layer for Mutable unboxed Vector
type UVector a = UV.IOVector a
instance VecFamily (UVector Int) Int where
{-# SPECIALIZE INLINE getNth :: UVector Int -> Int -> IO Int #-}
getNth = UV.unsafeRead
{-# SPECIALIZE INLINE setNth :: UVector Int -> Int -> Int -> IO () #-}
setNth = UV.unsafeWrite
{-# SPECIALIZE INLINE modifyNth :: UVector Int -> (Int -> Int) -> Int -> IO () #-}
modifyNth = UV.unsafeModify
{-# SPECIALIZE INLINE swapBetween:: UVector Int -> Int -> Int -> IO () #-}
swapBetween = UV.unsafeSwap
{-# SPECIALIZE INLINE newVec :: Int -> Int -> IO (UVector Int) #-}
newVec n 0 = UV.new n
newVec n x = do
v <- UV.new n
UV.set v x
return v
{-# SPECIALIZE INLINE setAll :: UVector Int -> Int -> IO () #-}
setAll = UV.set
{-# SPECIALIZE INLINE growBy :: UVector Int -> Int -> IO (UVector Int) #-}
growBy = UV.unsafeGrow
asList v = mapM (UV.unsafeRead v) [0 .. UV.length v - 1]
instance VecFamily (UVector Double) Double where
{-# SPECIALIZE INLINE getNth :: UVector Double -> Int -> IO Double #-}
getNth = UV.unsafeRead
{-# SPECIALIZE INLINE setNth :: UVector Double -> Int -> Double -> IO () #-}
setNth = UV.unsafeWrite
{-# SPECIALIZE INLINE modifyNth :: UVector Double -> (Double -> Double) -> Int -> IO () #-}
modifyNth = UV.unsafeModify
{-# SPECIALIZE INLINE swapBetween:: UVector Double -> Int -> Int -> IO () #-}
swapBetween = UV.unsafeSwap
{-# SPECIALIZE INLINE newVec :: Int -> Double -> IO (UVector Double) #-}
newVec n x = do
v <- UV.new n
UV.set v x
return v
{-# SPECIALIZE INLINE setAll :: UVector Double -> Double -> IO () #-}
setAll = UV.set
{-# SPECIALIZE INLINE growBy :: UVector Double -> Int -> IO (UVector Double) #-}
growBy = UV.unsafeGrow
asList v = mapM (UV.unsafeRead v) [0 .. UV.length v - 1]
-------------------------------------------------------------------------------- Vec
-- | Another abstraction layer on 'UVector'.
--
-- __Note__: the 0-th element of @Vec Int@ is reserved for internal tasks. If you want to use it, use @UVector Int@.
newtype Vec a = Vec (UVector a)
instance VecFamily (Vec Int) Int where
{-# SPECIALIZE INLINE getNth :: Vec Int -> Int -> IO Int #-}
getNth (Vec v) = UV.unsafeRead v
{-# SPECIALIZE INLINE setNth :: Vec Int -> Int -> Int -> IO () #-}
setNth (Vec v) = UV.unsafeWrite v
{-# SPECIALIZE INLINE reset :: Vec Int -> IO () #-}
reset (Vec v) = setNth v 0 0
{-# SPECIALIZE INLINE asUVector :: Vec Int -> UVector Int #-}
asUVector (Vec a) = UV.unsafeTail a
{-# SPECIALIZE INLINE modifyNth :: Vec Int -> (Int -> Int) -> Int -> IO () #-}
modifyNth (Vec v) = UV.unsafeModify v
{-# SPECIALIZE INLINE swapBetween :: Vec Int -> Int -> Int -> IO () #-}
swapBetween (Vec v) = UV.unsafeSwap v
{-# SPECIALIZE INLINE newVec :: Int -> Int -> IO (Vec Int) #-}
newVec n x = Vec <$> newVec (n + 1) x
{-# SPECIALIZE INLINE setAll :: Vec Int -> Int -> IO () #-}
setAll (Vec v) = UV.set v
{-# SPECIALIZE INLINE growBy :: Vec Int -> Int -> IO (Vec Int) #-}
growBy (Vec v) n = Vec <$> UV.unsafeGrow v n
asList (Vec v) = mapM (getNth v) [1 .. UV.length v - 1]
instance VecFamily (Vec Double) Double where
{-# SPECIALIZE INLINE getNth :: Vec Double -> Int -> IO Double #-}
getNth (Vec v) = UV.unsafeRead v
{-# SPECIALIZE INLINE setNth :: Vec Double -> Int -> Double -> IO () #-}
setNth (Vec v) = UV.unsafeWrite v
{-# SPECIALIZE INLINE modifyNth :: Vec Double -> (Double -> Double) -> Int -> IO () #-}
modifyNth (Vec v) = UV.unsafeModify v
{-# SPECIALIZE INLINE swapBetween :: Vec Double -> Int -> Int -> IO () #-}
swapBetween (Vec v) = UV.unsafeSwap v
{-# SPECIALIZE INLINE newVec :: Int -> Double -> IO (Vec Double) #-}
newVec n x = Vec <$> newVec (n + 1) x
{-# SPECIALIZE INLINE setAll :: Vec Double -> Double -> IO () #-}
setAll (Vec v) = UV.set v
{-# SPECIALIZE INLINE growBy :: Vec Double -> Int -> IO (Vec Double) #-}
growBy (Vec v) n = Vec <$> UV.unsafeGrow v n
-------------------------------------------------------------------------------- SingleStorage
-- | Interface for single mutable data
class SingleStorage s t | s -> t where
-- | allocates and returns an new data.
new' :: t -> IO s
-- | gets the value.
get' :: s -> IO t
-- | sets the value.
set' :: s -> t -> IO ()
-- | calls an update function on it.
modify' :: s -> (t -> t) -> IO ()
{-# MINIMAL get', set' #-}
new' = undefined
modify' = undefined
-- | Mutable Int
-- __Note:__ Int' is the same with 'Stack'
type Int' = UV.IOVector Int
instance SingleStorage Int' Int where
{-# SPECIALIZE INLINE new' :: Int -> IO Int' #-}
new' k = do
s <- UV.new 1
UV.unsafeWrite s 0 k
return s
{-# SPECIALIZE INLINE get' :: Int' -> IO Int #-}
get' val = UV.unsafeRead val 0
{-# SPECIALIZE INLINE set' :: Int' -> Int -> IO () #-}
set' val !x = UV.unsafeWrite val 0 x
{-# SPECIALIZE INLINE modify' :: Int' -> (Int -> Int) -> IO () #-}
modify' val f = UV.unsafeModify val f 0
-- | Mutable Bool
type Bool' = UV.IOVector Bool
instance SingleStorage Bool' Bool where
{-# SPECIALIZE INLINE new' :: Bool -> IO Bool' #-}
new' k = do
s <- UV.new 1
UV.unsafeWrite s 0 k
return s
{-# SPECIALIZE INLINE get' :: Bool' -> IO Bool #-}
get' val = UV.unsafeRead val 0
{-# SPECIALIZE INLINE set' :: Bool' -> Bool -> IO () #-}
set' val !x = UV.unsafeWrite val 0 x
{-# SPECIALIZE INLINE modify' :: Bool' -> (Bool -> Bool) -> IO () #-}
modify' val f = UV.unsafeModify val f 0
-- | Mutable Double
type Double' = UV.IOVector Double
instance SingleStorage Double' Double where
{-# SPECIALIZE INLINE new' :: Double -> IO Double' #-}
new' k = do
s <- UV.new 1
UV.unsafeWrite s 0 k
return s
{-# SPECIALIZE INLINE get' :: Double' -> IO Double #-}
get' val = UV.unsafeRead val 0
{-# SPECIALIZE INLINE set' :: Double' -> Double -> IO () #-}
set' val !x = UV.unsafeWrite val 0 x
{-# SPECIALIZE INLINE modify' :: Double' -> (Double -> Double) -> IO () #-}
modify' val f = UV.unsafeModify val f 0
-------------------------------------------------------------------------------- Stack
-- | Interface on stacks
class SingleStorage s Int => StackFamily s t | s -> t where
-- | returns a new stack.
newStack :: Int -> IO s
-- | pushs an value to the tail of the stack.
pushTo :: s -> t-> IO ()
-- | pops the last element.
popFrom :: s -> IO ()
-- | peeks the last element.
lastOf :: s -> IO t
-- | shrinks the stack.
shrinkBy :: s -> Int -> IO ()
newStack = undefined
pushTo = undefined
popFrom = undefined
lastOf = undefined
shrinkBy = undefined
-- | Alias of @Vec Int@. The 0-th element holds the number of elements.
type Stack = Vec Int
instance SingleStorage Stack Int where
{-# SPECIALIZE INLINE get' :: Stack -> IO Int #-}
get' (Vec v) = UV.unsafeRead v 0
{-# SPECIALIZE INLINE set' :: Stack -> Int -> IO () #-}
set' (Vec v) !x = UV.unsafeWrite v 0 x
{-# SPECIALIZE INLINE modify' :: Stack -> (Int -> Int) -> IO () #-}
modify' (Vec v) f = UV.unsafeModify v f 0
instance StackFamily Stack Int where
{-# SPECIALIZE INLINE newStack :: Int -> IO Stack #-}
newStack n = newVec n 0
{-# SPECIALIZE INLINE pushTo :: Stack -> Int -> IO () #-}
pushTo (Vec v) x = do
i <- (+ 1) <$> UV.unsafeRead v 0
UV.unsafeWrite v i x
UV.unsafeWrite v 0 i
{-# SPECIALIZE INLINE popFrom :: Stack -> IO () #-}
popFrom (Vec v) = UV.unsafeModify v (subtract 1) 0
{-# SPECIALIZE INLINE lastOf :: Stack -> IO Int #-}
lastOf (Vec v) = UV.unsafeRead v =<< UV.unsafeRead v 0
{-# SPECIALIZE INLINE shrinkBy :: Stack -> Int -> IO () #-}
shrinkBy (Vec v) k = UV.unsafeModify v (subtract k) 0
-- | returns a new 'Stack' from @[Int]@.
{-# INLINABLE newStackFromList #-}
newStackFromList :: [Int] -> IO Stack
newStackFromList !l = Vec <$> U.unsafeThaw (U.fromList (length l : l))