{-# LANGUAGE FlexibleInstances #-} module HaskellWorks.Data.BalancedParens.FindClose ( FindClose(..) ) where import Data.Word import HaskellWorks.Data.BalancedParens.CloseAt import HaskellWorks.Data.BalancedParens.FindCloseN import HaskellWorks.Data.Bits.BitShown import HaskellWorks.Data.Bits.BitWise import HaskellWorks.Data.Bits.Broadword.Type import HaskellWorks.Data.Naive import HaskellWorks.Data.Positioning import qualified Data.Vector.Storable as DVS import qualified HaskellWorks.Data.BalancedParens.Internal.Broadword.FindClose.Vector16 as BWV16 import qualified HaskellWorks.Data.BalancedParens.Internal.Broadword.FindClose.Vector32 as BWV32 import qualified HaskellWorks.Data.BalancedParens.Internal.Broadword.FindClose.Vector64 as BWV64 import qualified HaskellWorks.Data.BalancedParens.Internal.Broadword.FindClose.Vector8 as BWV8 import qualified HaskellWorks.Data.BalancedParens.Internal.Broadword.Word64 as W64 class FindClose v where -- | Find the closing parenthesis that machines the open parenthesis at the current position. -- -- If the parenthesis at the current position is an close parenthesis, then return the current position. -- -- Indexes are 1-based. 1 corresponds to open and 0 corresponds to close. -- -- If we run out of bits in the supplied bit-string, the implementation my either return Nothing, or -- assume all the bits that follow are zeros. -- -- >>> :set -XTypeApplications -- >>> import Data.Maybe -- >>> import HaskellWorks.Data.Bits.BitRead -- >>> findClose (fromJust (bitRead @Word64 "00000000")) 1 -- Just 1 -- >>> findClose (fromJust (bitRead @Word64 "10101010")) 1 -- Just 2 -- >>> findClose (fromJust (bitRead @Word64 "10101010")) 2 -- Just 2 -- >>> findClose (fromJust (bitRead @Word64 "10101010")) 3 -- Just 4 -- >>> findClose (fromJust (bitRead @Word64 "11010010")) 1 -- Just 6 -- >>> findClose (fromJust (bitRead @Word64 "11110000")) 1 -- Just 8 findClose :: v -> Count -> Maybe Count instance (FindClose a) => FindClose (BitShown a) where findClose = findClose . bitShown {-# INLINE findClose #-} instance FindClose [Bool] where findClose v p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose (DVS.Vector Word8) where findClose = BWV8.findClose {-# INLINE findClose #-} instance FindClose (DVS.Vector Word16) where findClose = BWV16.findClose {-# INLINE findClose #-} instance FindClose (DVS.Vector Word32) where findClose = BWV32.findClose {-# INLINE findClose #-} instance FindClose (DVS.Vector Word64) where findClose = BWV64.findClose {-# INLINE findClose #-} instance FindClose (Naive (DVS.Vector Word8)) where findClose (Naive v) p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose (Naive (DVS.Vector Word16)) where findClose (Naive v) p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose (Naive (DVS.Vector Word32)) where findClose (Naive v) p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose (Naive (DVS.Vector Word64)) where findClose (Naive v) p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose Word8 where findClose v p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose Word16 where findClose v p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose Word32 where findClose v p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose Word64 where findClose = findClose . Broadword {-# INLINE findClose #-} instance FindClose (Naive Word64) where findClose v p = if v `closeAt` p then Just p else findCloseN v 1 (p + 1) {-# INLINE findClose #-} instance FindClose (Broadword Word64) where findClose (Broadword w) p = let x = w .>. (p - 1) in case negate (x .&. 1) .&. W64.findUnmatchedClose x of 127 -> Nothing r -> let r' = fromIntegral r + p in if r' > 64 then Nothing else Just r' {-# INLINE findClose #-}