{-# OPTIONS_GHC-funbox-strict-fields #-}

{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE DeriveAnyClass      #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE Rank2Types          #-}
{-# LANGUAGE ScopedTypeVariables #-}

module HaskellWorks.Data.RankSelect.CsPoppy
    ( CsPoppy(..)
    , makeCsPoppy
    ) where

import Control.DeepSeq
import Data.Word
import GHC.Generics
import HaskellWorks.Data.BalancedParens.BalancedParens
import HaskellWorks.Data.BalancedParens.CloseAt
import HaskellWorks.Data.BalancedParens.Enclose
import HaskellWorks.Data.BalancedParens.FindClose
import HaskellWorks.Data.BalancedParens.FindCloseN
import HaskellWorks.Data.BalancedParens.FindOpen
import HaskellWorks.Data.BalancedParens.FindOpenN
import HaskellWorks.Data.BalancedParens.NewCloseAt
import HaskellWorks.Data.BalancedParens.OpenAt
import HaskellWorks.Data.Bits.BitLength
import HaskellWorks.Data.Bits.BitRead
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Bits.PopCount.PopCount0
import HaskellWorks.Data.Bits.PopCount.PopCount1
import HaskellWorks.Data.FromForeignRegion
import HaskellWorks.Data.RankSelect.Base.Rank0
import HaskellWorks.Data.RankSelect.Base.Rank1
import HaskellWorks.Data.RankSelect.Base.Select0
import HaskellWorks.Data.RankSelect.Base.Select1
import HaskellWorks.Data.RankSelect.CsPoppy.Internal.CsInterleaved
import HaskellWorks.Data.RankSelect.CsPoppy.Internal.Vector
import HaskellWorks.Data.Vector.AsVector64
import Prelude                                                     hiding (drop, length, pi, take)

import qualified Data.Vector.Storable                                 as DVS
import qualified HaskellWorks.Data.RankSelect.CsPoppy.Internal.Alpha0 as A0
import qualified HaskellWorks.Data.RankSelect.CsPoppy.Internal.Alpha1 as A1

data CsPoppy = CsPoppy
  { CsPoppy -> Vector Word64
csPoppyBits   :: !(DVS.Vector Word64)
  , CsPoppy -> CsPoppyIndex
csPoppyIndex0 :: !A0.CsPoppyIndex
  , CsPoppy -> CsPoppyIndex
csPoppyIndex1 :: !A1.CsPoppyIndex
  } deriving (CsPoppy -> CsPoppy -> Bool
(CsPoppy -> CsPoppy -> Bool)
-> (CsPoppy -> CsPoppy -> Bool) -> Eq CsPoppy
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CsPoppy -> CsPoppy -> Bool
$c/= :: CsPoppy -> CsPoppy -> Bool
== :: CsPoppy -> CsPoppy -> Bool
$c== :: CsPoppy -> CsPoppy -> Bool
Eq, Int -> CsPoppy -> ShowS
[CsPoppy] -> ShowS
CsPoppy -> String
(Int -> CsPoppy -> ShowS)
-> (CsPoppy -> String) -> ([CsPoppy] -> ShowS) -> Show CsPoppy
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CsPoppy] -> ShowS
$cshowList :: [CsPoppy] -> ShowS
show :: CsPoppy -> String
$cshow :: CsPoppy -> String
showsPrec :: Int -> CsPoppy -> ShowS
$cshowsPrec :: Int -> CsPoppy -> ShowS
Show, CsPoppy -> ()
(CsPoppy -> ()) -> NFData CsPoppy
forall a. (a -> ()) -> NFData a
rnf :: CsPoppy -> ()
$crnf :: CsPoppy -> ()
NFData, (forall x. CsPoppy -> Rep CsPoppy x)
-> (forall x. Rep CsPoppy x -> CsPoppy) -> Generic CsPoppy
forall x. Rep CsPoppy x -> CsPoppy
forall x. CsPoppy -> Rep CsPoppy x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CsPoppy x -> CsPoppy
$cfrom :: forall x. CsPoppy -> Rep CsPoppy x
Generic)

instance FromForeignRegion CsPoppy where
  fromForeignRegion :: ForeignRegion -> CsPoppy
fromForeignRegion = Vector Word64 -> CsPoppy
makeCsPoppy (Vector Word64 -> CsPoppy)
-> (ForeignRegion -> Vector Word64) -> ForeignRegion -> CsPoppy
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignRegion -> Vector Word64
forall a. FromForeignRegion a => ForeignRegion -> a
fromForeignRegion

instance AsVector64 CsPoppy where
  asVector64 :: CsPoppy -> Vector Word64
asVector64 = Vector Word64 -> Vector Word64
forall a. AsVector64 a => a -> Vector Word64
asVector64 (Vector Word64 -> Vector Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Vector Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE asVector64 #-}

instance BitLength CsPoppy where
  bitLength :: CsPoppy -> Word64
bitLength = Vector Word64 -> Word64
forall v. BitLength v => v -> Word64
bitLength (Vector Word64 -> Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE bitLength #-}

instance PopCount0 CsPoppy where
  popCount0 :: CsPoppy -> Word64
popCount0 CsPoppy
v = CsInterleaved -> Word64
getCsiTotal (Word64 -> CsInterleaved
CsInterleaved (Vector Word64 -> Word64
lastOrZero (CsPoppyIndex -> Vector Word64
A0.csPoppyLayerM (CsPoppy -> CsPoppyIndex
csPoppyIndex0 CsPoppy
v))))
  {-# INLINE popCount0 #-}

instance PopCount1 CsPoppy where
  popCount1 :: CsPoppy -> Word64
popCount1 CsPoppy
v = CsInterleaved -> Word64
getCsiTotal (Word64 -> CsInterleaved
CsInterleaved (Vector Word64 -> Word64
lastOrZero (CsPoppyIndex -> Vector Word64
A1.csPoppyLayerM (CsPoppy -> CsPoppyIndex
csPoppyIndex1 CsPoppy
v))))
  {-# INLINE popCount1 #-}

makeCsPoppy :: DVS.Vector Word64 -> CsPoppy
makeCsPoppy :: Vector Word64 -> CsPoppy
makeCsPoppy Vector Word64
v = CsPoppy :: Vector Word64 -> CsPoppyIndex -> CsPoppyIndex -> CsPoppy
CsPoppy
  { csPoppyBits :: Vector Word64
csPoppyBits   = Vector Word64
v
  , csPoppyIndex0 :: CsPoppyIndex
csPoppyIndex0 = Vector Word64 -> CsPoppyIndex
A0.makeCsPoppyIndex Vector Word64
v
  , csPoppyIndex1 :: CsPoppyIndex
csPoppyIndex1 = Vector Word64 -> CsPoppyIndex
A1.makeCsPoppyIndex Vector Word64
v
  }

instance TestBit CsPoppy where
  .?. :: CsPoppy -> Position -> Bool
(.?.) = Vector Word64 -> Position -> Bool
forall a. TestBit a => a -> Position -> Bool
(.?.) (Vector Word64 -> Position -> Bool)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Position -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE (.?.) #-}

instance BitRead CsPoppy where
  bitRead :: String -> Maybe CsPoppy
bitRead = (Vector Word64 -> CsPoppy)
-> Maybe (Vector Word64) -> Maybe CsPoppy
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Vector Word64 -> CsPoppy
makeCsPoppy (Maybe (Vector Word64) -> Maybe CsPoppy)
-> (String -> Maybe (Vector Word64)) -> String -> Maybe CsPoppy
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe (Vector Word64)
forall a. BitRead a => String -> Maybe a
bitRead

instance Rank0 CsPoppy where
  rank0 :: CsPoppy -> Word64 -> Word64
rank0 (CsPoppy !Vector Word64
v CsPoppyIndex
i CsPoppyIndex
_) = Vector Word64 -> CsPoppyIndex -> Word64 -> Word64
A0.rank0On Vector Word64
v CsPoppyIndex
i
  {-# INLINE rank0 #-}

instance Rank1 CsPoppy where
  rank1 :: CsPoppy -> Word64 -> Word64
rank1 (CsPoppy !Vector Word64
v CsPoppyIndex
_ CsPoppyIndex
i) = Vector Word64 -> CsPoppyIndex -> Word64 -> Word64
A1.rank1On Vector Word64
v CsPoppyIndex
i
  {-# INLINE rank1 #-}

instance Select0 CsPoppy where
  select0 :: CsPoppy -> Word64 -> Word64
select0 (CsPoppy !Vector Word64
v CsPoppyIndex
i CsPoppyIndex
_) = Vector Word64 -> CsPoppyIndex -> Word64 -> Word64
A0.select0On Vector Word64
v CsPoppyIndex
i
  {-# INLINE select0 #-}

instance Select1 CsPoppy where
  select1 :: CsPoppy -> Word64 -> Word64
select1 (CsPoppy !Vector Word64
v CsPoppyIndex
_ CsPoppyIndex
i) = Vector Word64 -> CsPoppyIndex -> Word64 -> Word64
A1.select1On Vector Word64
v CsPoppyIndex
i
  {-# INLINE select1 #-}

instance OpenAt CsPoppy where
  openAt :: CsPoppy -> Word64 -> Bool
openAt = Vector Word64 -> Word64 -> Bool
forall v. OpenAt v => v -> Word64 -> Bool
openAt (Vector Word64 -> Word64 -> Bool)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE openAt #-}

instance CloseAt CsPoppy where
  closeAt :: CsPoppy -> Word64 -> Bool
closeAt = Vector Word64 -> Word64 -> Bool
forall v. CloseAt v => v -> Word64 -> Bool
closeAt (Vector Word64 -> Word64 -> Bool)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE closeAt #-}

instance NewCloseAt CsPoppy where
  newCloseAt :: CsPoppy -> Word64 -> Bool
newCloseAt = Vector Word64 -> Word64 -> Bool
forall v. NewCloseAt v => v -> Word64 -> Bool
newCloseAt (Vector Word64 -> Word64 -> Bool)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE newCloseAt #-}

instance FindOpenN CsPoppy where
  findOpenN :: CsPoppy -> Word64 -> Word64 -> Maybe Word64
findOpenN = Vector Word64 -> Word64 -> Word64 -> Maybe Word64
forall v. FindOpenN v => v -> Word64 -> Word64 -> Maybe Word64
findOpenN (Vector Word64 -> Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64)
-> CsPoppy
-> Word64
-> Word64
-> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE findOpenN #-}

instance FindOpen CsPoppy where
  findOpen :: CsPoppy -> Word64 -> Maybe Word64
findOpen = Vector Word64 -> Word64 -> Maybe Word64
forall v. FindOpen v => v -> Word64 -> Maybe Word64
findOpen (Vector Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE findOpen #-}

instance FindClose CsPoppy where
  findClose :: CsPoppy -> Word64 -> Maybe Word64
findClose = Vector Word64 -> Word64 -> Maybe Word64
forall v. FindClose v => v -> Word64 -> Maybe Word64
findClose (Vector Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE findClose #-}

instance FindCloseN CsPoppy where
  findCloseN :: CsPoppy -> Word64 -> Word64 -> Maybe Word64
findCloseN = Vector Word64 -> Word64 -> Word64 -> Maybe Word64
forall v. FindCloseN v => v -> Word64 -> Word64 -> Maybe Word64
findCloseN (Vector Word64 -> Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64)
-> CsPoppy
-> Word64
-> Word64
-> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE findCloseN #-}

instance Enclose CsPoppy where
  enclose :: CsPoppy -> Word64 -> Maybe Word64
enclose = Vector Word64 -> Word64 -> Maybe Word64
forall v. Enclose v => v -> Word64 -> Maybe Word64
enclose (Vector Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE enclose #-}

instance BalancedParens CsPoppy where
  firstChild :: CsPoppy -> Word64 -> Maybe Word64
firstChild  = Vector Word64 -> Word64 -> Maybe Word64
forall v. BalancedParens v => v -> Word64 -> Maybe Word64
firstChild  (Vector Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  nextSibling :: CsPoppy -> Word64 -> Maybe Word64
nextSibling = Vector Word64 -> Word64 -> Maybe Word64
forall v. BalancedParens v => v -> Word64 -> Maybe Word64
nextSibling (Vector Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  parent :: CsPoppy -> Word64 -> Maybe Word64
parent      = Vector Word64 -> Word64 -> Maybe Word64
forall v. BalancedParens v => v -> Word64 -> Maybe Word64
parent      (Vector Word64 -> Word64 -> Maybe Word64)
-> (CsPoppy -> Vector Word64) -> CsPoppy -> Word64 -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsPoppy -> Vector Word64
csPoppyBits
  {-# INLINE firstChild  #-}
  {-# INLINE nextSibling #-}
  {-# INLINE parent      #-}