module HaskellWorks.Data.BalancedParens.Internal.Vector.Storable
  ( lastOrZero
  , reword
  , dropTake
  , dropTakeFill
  , pageFill
  ) where

import qualified Data.Vector.Storable as DVS

lastOrZero :: (DVS.Storable a, Integral a) => DVS.Vector a -> a
lastOrZero :: Vector a -> a
lastOrZero Vector a
v = if Bool -> Bool
not (Vector a -> Bool
forall a. Storable a => Vector a -> Bool
DVS.null Vector a
v) then Vector a -> a
forall a. Storable a => Vector a -> a
DVS.last Vector a
v else a
0
{-# INLINE lastOrZero #-}

reword :: (DVS.Storable a, Integral a, DVS.Storable b, Num b) => DVS.Vector a -> DVS.Vector b
reword :: Vector a -> Vector b
reword Vector a
v = Int -> (Int -> b) -> Vector b
forall a. Storable a => Int -> (Int -> a) -> Vector a
DVS.generate (Vector a -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector a
v) (\Int
i -> a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Vector a
v Vector a -> Int -> a
forall a. Storable a => Vector a -> Int -> a
DVS.! Int
i))
{-# INLINE reword #-}

dropTake :: DVS.Storable a => Int -> Int -> DVS.Vector a -> DVS.Vector a
dropTake :: Int -> Int -> Vector a -> Vector a
dropTake Int
n Int
o = Int -> Vector a -> Vector a
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take Int
o (Vector a -> Vector a)
-> (Vector a -> Vector a) -> Vector a -> Vector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Vector a -> Vector a
forall a. Storable a => Int -> Vector a -> Vector a
DVS.drop Int
n
{-# INLINE dropTake #-}

dropTakeFill :: DVS.Storable a => Int -> Int -> a -> DVS.Vector a -> DVS.Vector a
dropTakeFill :: Int -> Int -> a -> Vector a -> Vector a
dropTakeFill Int
n Int
o a
a Vector a
v =  let r :: Vector a
r = Int -> Vector a -> Vector a
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take Int
o (Int -> Vector a -> Vector a
forall a. Storable a => Int -> Vector a -> Vector a
DVS.drop Int
n Vector a
v) in
                        let len :: Int
len = Vector a -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector a
r in
                        if Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
o then Vector a
r else [Vector a] -> Vector a
forall a. Storable a => [Vector a] -> Vector a
DVS.concat [Vector a
r, [a] -> Vector a
forall a. Storable a => [a] -> Vector a
DVS.fromList (Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
o Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
len) a
a)]
{-# INLINE dropTakeFill #-}

-- | Return the n-th page of size s from the input vector.  In the case where there isn't
-- sufficient data to fill the page from the input vector, then the remainder of the page
-- is filled with a.
pageFill :: DVS.Storable a
  => Int          -- ^ The n-th page to retrieve
  -> Int          -- ^ The page size
  -> a            -- ^ The element value to fill the page when input vector has insufficient values
  -> DVS.Vector a -- ^ The input vector
  -> DVS.Vector a -- ^ The page
pageFill :: Int -> Int -> a -> Vector a -> Vector a
pageFill Int
n Int
s = Int -> Int -> a -> Vector a -> Vector a
forall a. Storable a => Int -> Int -> a -> Vector a -> Vector a
dropTakeFill (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
s) Int
s
{-# INLINE pageFill #-}