packages feed

hw-rankselect-0.2.0.1: src/HaskellWorks/Data/Succinct/BalancedParens/Internal.hs

{-# LANGUAGE FlexibleInstances #-}

module HaskellWorks.Data.Succinct.BalancedParens.Internal
  ( BalancedParens(..)
  , OpenAt(..)
  , CloseAt(..)
  , depth
  , subtreeSize
  ) where

import           Control.Monad
import qualified Data.Vector.Storable                                       as DVS
import           Data.Word
import           HaskellWorks.Data.Bits.BitLength
import           HaskellWorks.Data.Bits.BitShown
import           HaskellWorks.Data.Bits.BitWise
import           HaskellWorks.Data.Positioning
import           HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank0
import           HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank1

class OpenAt v where
  openAt      :: v -> Count -> Bool

class CloseAt v where
  closeAt     :: v -> Count -> Bool

class (OpenAt v, CloseAt v) => BalancedParens v where
  -- TODO Second argument should be Int
  findOpenN   :: v -> Count -> Count -> Maybe Count
  findCloseN  :: v -> Count -> Count -> Maybe Count

  enclose     :: v -> Count -> Maybe Count
  firstChild  :: v -> Count -> Maybe Count
  nextSibling :: v -> Count -> Maybe Count
  parent      :: v -> Count -> Maybe Count
  findOpen    :: v -> Count -> Maybe Count
  findClose   :: v -> Count -> Maybe Count
  findOpen    v p = if v `openAt`  p then Just p else findOpenN  v (Count 0) (p - 1)
  findClose   v p = if v `closeAt` p then Just p else findCloseN v (Count 1) (p + 1)
  firstChild  v p = if openAt v p && openAt v (p + 1)   then Just (p + 1) else Nothing
  nextSibling v p = if closeAt v p
    then Nothing
    else openAt v `mfilter` (findClose v p >>= (\q ->
      if p /= q
        then return (q + 1)
        else Nothing))
  parent      v p = enclose   v p >>= (\r -> if r >= 1 then return r      else Nothing)
  enclose     v   = findOpenN v (Count 1)
  {-# INLINE findOpen     #-}
  {-# INLINE findClose    #-}
  {-# INLINE firstChild   #-}
  {-# INLINE nextSibling  #-}
  {-# INLINE parent       #-}
  {-# INLINE enclose      #-}

depth :: (BalancedParens v, Rank0 v, Rank1 v) => v -> Count -> Maybe Count
depth v p = (\q -> rank1 v q - rank0 v q) <$> findOpen v p

subtreeSize :: BalancedParens v => v -> Count -> Maybe Count
subtreeSize v p = (\q -> (q - p + 1) `quot` 2) <$> findClose v p

closeAt' :: TestBit a => a -> Count -> Bool
closeAt' v c = not (v .?. toPosition (c - 1))
{-# INLINE closeAt' #-}

openAt' :: (BitLength a, TestBit a) => a -> Count -> Bool
openAt' v c = (0 <= c && c < bitLength v) && (v .?. toPosition (c - 1))
{-# INLINE openAt' #-}

-----

findOpen' :: (BitLength a, TestBit a) => a -> Count -> Count -> Maybe Count
findOpen' v c p = if 0 < p && p <= bitLength v
  then if v `openAt'` p
    then if c == 0
      then Just p
      else findOpen' v (c - 1) (p - 1)
    else findOpen' v (c + 1) (p - 1)
  else Nothing
{-# INLINE findOpen' #-}

findClose' :: (BitLength a, TestBit a) => a -> Count -> Count -> Maybe Count
findClose' v c p = if 0 < p && p <= bitLength v
  then if v `closeAt'` p
    then if c <= 1
      then Just p
      else findClose' v (c - 1) (p + 1)
    else findClose' v (c + 1) (p + 1)
  else Nothing
{-# INLINE findClose' #-}

instance (BitLength a, TestBit a) => OpenAt (BitShown a) where
  openAt = openAt' . bitShown
  {-# INLINE openAt      #-}

instance (BitLength a, TestBit a) => CloseAt (BitShown a) where
  closeAt = closeAt' . bitShown
  {-# INLINE closeAt     #-}

instance (BalancedParens a, TestBit a, BitLength a) => BalancedParens (BitShown a) where
  findOpenN  = findOpen'   . bitShown
  findCloseN = findClose'  . bitShown
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt [Bool] where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt [Bool] where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens [Bool] where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt (DVS.Vector Word8) where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt (DVS.Vector Word8) where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens (DVS.Vector Word8) where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt (DVS.Vector Word16) where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt (DVS.Vector Word16) where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens (DVS.Vector Word16) where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt (DVS.Vector Word32) where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt (DVS.Vector Word32) where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens (DVS.Vector Word32) where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt (DVS.Vector Word64) where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt (DVS.Vector Word64) where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens (DVS.Vector Word64) where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt Word8 where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt Word8 where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens Word8 where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt Word16 where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt Word16 where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens Word16 where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt Word32 where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt Word32 where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens Word32 where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}

instance OpenAt Word64 where
  openAt = openAt'
  {-# INLINE openAt      #-}

instance CloseAt Word64 where
  closeAt = closeAt'
  {-# INLINE closeAt     #-}

instance BalancedParens Word64 where
  findOpenN       = findOpen'
  findCloseN      = findClose'
  {-# INLINE findOpenN   #-}
  {-# INLINE findCloseN  #-}