hw-rankselect-0.2.0.1: src/HaskellWorks/Data/Succinct/BalancedParens/RangeMinMax/L3.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE TypeFamilies #-}
module HaskellWorks.Data.Succinct.BalancedParens.RangeMinMax.L3
( RangeMinMaxL3(..)
, mkRangeMinMaxL3
) where
import Data.Int
import qualified Data.Vector as DV
import qualified Data.Vector.Storable as DVS
import Data.Word
import HaskellWorks.Data.Bits.BitLength
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Succinct.BalancedParens.Internal
import HaskellWorks.Data.Succinct.BalancedParens.NewCloseAt
import HaskellWorks.Data.Succinct.BalancedParens.RangeMinMax.Internal
import HaskellWorks.Data.Succinct.BalancedParens.RangeMinMax.L0
import HaskellWorks.Data.Succinct.BalancedParens.RangeMinMax.L1
import HaskellWorks.Data.Succinct.BalancedParens.RangeMinMax.L2
import HaskellWorks.Data.Succinct.BalancedParens.RangeMinMax.Simple
import HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank0
import HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank1
import HaskellWorks.Data.Succinct.Excess.MinMaxExcess1
import HaskellWorks.Data.Vector.VectorLike
data RangeMinMaxL3 = RangeMinMaxL3
{ rangeMinMaxL3Base :: !RangeMinMaxL2
, rangeMinMaxL3Min :: !(DVS.Vector Int16)
, rangeMinMaxL3Max :: !(DVS.Vector Int16)
, rangeMinMaxL3Excess :: !(DVS.Vector Int16)
}
instance RangeMinMaxLevel RangeMinMaxL3 where
rmmFactor _ = 32
rmmBinWords v = rmmFactor v * rmmBinWords (rmmBase v)
rmmBins = DVS.length . rangeMinMaxL3Min
{-# INLINE rmmFactor #-}
{-# INLINE rmmBinWords #-}
{-# INLINE rmmBins #-}
class MkRangeMinMaxL3 a where
mkRangeMinMaxL3 :: a -> RangeMinMaxL3
instance MkRangeMinMaxL3 RangeMinMaxL2 where
mkRangeMinMaxL3 rmmL2 = result
where bp = rangeMinMaxSimpleBP (rangeMinMaxSimple (rangeMinMaxL1Base (rangeMinMaxL2Base rmmL2)))
lenL3 = (DVS.length (rangeMinMaxL2Min rmmL2) `div` rmmFactor result) + 1 :: Int
allMinMaxL3 = DV.constructN lenL3 genMinMaxL3
genMinMaxL3 v = let len = DV.length v in minMaxExcess1 (DVS.take (rmmBinWords result) (DVS.drop (len * rmmBinWords result) bp))
rangeMinMaxL3ExcessA = DVS.constructN lenL3 (\v -> let (_, e, _) = allMinMaxL3 DV.! DVS.length v in fromIntegral e) :: DVS.Vector Int16
result = RangeMinMaxL3
{ rangeMinMaxL3Base = rmmL2
, rangeMinMaxL3Min = DVS.constructN lenL3 (\v -> let (minE, _, _) = allMinMaxL3 DV.! DVS.length v in fromIntegral minE)
, rangeMinMaxL3Max = DVS.constructN lenL3 (\v -> let (_, _, maxE) = allMinMaxL3 DV.! DVS.length v in fromIntegral maxE)
, rangeMinMaxL3Excess = rangeMinMaxL3ExcessA
}
instance MkRangeMinMaxL3 RangeMinMaxSimple where
mkRangeMinMaxL3 = mkRangeMinMaxL3 . mkRangeMinMaxL2
instance MkRangeMinMaxL3 (DVS.Vector Word64) where
mkRangeMinMaxL3 = mkRangeMinMaxL3 . mkRangeMinMaxSimple
{-# INLINE mkRangeMinMaxL3 #-}
instance TestBit RangeMinMaxL3 where
(.?.) = (.?.) . rangeMinMaxL3Base
{-# INLINE (.?.) #-}
instance Rank1 RangeMinMaxL3 where
rank1 = rank1 . rangeMinMaxL3Base
{-# INLINE rank1 #-}
instance Rank0 RangeMinMaxL3 where
rank0 = rank0 . rangeMinMaxL3Base
{-# INLINE rank0 #-}
instance BitLength RangeMinMaxL3 where
bitLength = bitLength . rangeMinMaxL3Base
{-# INLINE bitLength #-}
instance RangeMinMaxDerived RangeMinMaxL3 where
type RangeMinMaxBase RangeMinMaxL3 = RangeMinMaxL2
rmmBase = rangeMinMaxL3Base
{-# INLINE rmmBase #-}
instance RangeMinMax RangeMinMaxL3 where
rmmFindCloseDispatch v s p = if p `mod` rmmBinBits v == 0
then rmmFindCloseN v s p
else rmmFindCloseDispatch (rmmBase v) s p
rmmFindCloseN v s p =
let i = p `div` rmmBinBits v in
let minE = fromIntegral (mins !!! fromIntegral i) :: Int in
if fromIntegral s + minE <= 0
then rmmFindCloseN (rmmBase v) s p
else if v `newCloseAt` p && s <= 1
then Just p
else let excess = fromIntegral (excesses !!! fromIntegral i) :: Int in
rmmFindClose v (fromIntegral (excess + fromIntegral s)) (p + rmmBinBits v)
where mins = rangeMinMaxL3Min v
excesses = rangeMinMaxL3Excess v
{-# INLINE rmmFindCloseDispatch #-}
{-# INLINE rmmFindCloseN #-}
instance OpenAt RangeMinMaxL3 where
openAt = openAt . rangeMinMaxL3Base
{-# INLINE openAt #-}
instance CloseAt RangeMinMaxL3 where
closeAt = closeAt . rangeMinMaxL3Base
{-# INLINE closeAt #-}
instance NewCloseAt RangeMinMaxL3 where
newCloseAt = newCloseAt . rangeMinMaxL3Base
{-# INLINE newCloseAt #-}
instance BalancedParens RangeMinMaxL3 where
findOpenN = findOpenN . rangeMinMaxL3Base
findCloseN v s p = (+ 1) `fmap` rmmFindClose v (fromIntegral s) (p - 1)
{-# INLINE findOpenN #-}
{-# INLINE findCloseN #-}