hw-rankselect-0.13.0.0: src/HaskellWorks/Data/RankSelect/CsPoppy/Internal/Lookup.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MultiWayIf #-}
module HaskellWorks.Data.RankSelect.CsPoppy.Internal.Lookup where
import Data.Word
import HaskellWorks.Data.AtIndex
import HaskellWorks.Data.Bits.BitWise
import Prelude hiding (drop, length, pi, take)
import qualified Data.Vector.Storable as DVS
binarySearchPBounds :: (Word64 -> Bool) -> DVS.Vector Word64 -> Word64 -> Word64 -> Word64
binarySearchPBounds p v = loop
where loop :: Word64 -> Word64 -> Word64
loop !l !u
| u <= l = l
| otherwise = let e = v !!! fromIntegral k in if p e then loop l k else loop (k + 1) u
where k = (u + l) .>. 1
{-# INLINE binarySearchPBounds #-}
lookupLayerMXFrom :: Word64 -> Word64 -> Word64 -> DVS.Vector Word64 -> Word64
lookupLayerMXFrom prev i r v | i < length v =
let mw = v !!! fromIntegral i :: Word64
mx = ( mw .&. 0x00000000ffffffff ) :: Word64
in if r <= mx
then prev
else lookupLayerMXFrom i (i + 1) r v
lookupLayerMXFrom prev _ _ _ = prev
{-# INLINE lookupLayerMXFrom #-}
lookupLayerMFrom1 :: Word64 -> Word64 -> Word64 -> DVS.Vector Word64 -> (Word64, Word64)
lookupLayerMFrom1 i _ r v
| r <= mx = error "This shouldn't happen"
| r <= ma = (mx, j * 4 )
| r <= mb = (ma, j * 4 + 1)
| r <= mc = (mb, j * 4 + 2)
| otherwise = (mc, j * 4 + 3)
where j = lookupLayerMXFrom 0 i r v
mw = v !!! fromIntegral j :: Word64
mx = ( mw .&. 0x00000000ffffffff ) :: Word64
ma = mx + ((mw .&. 0x000003ff00000000) .>. 32) :: Word64
mb = ma + ((mw .&. 0x000ffc0000000000) .>. 42) :: Word64
mc = mb + ((mw .&. 0x3ff0000000000000) .>. 52) :: Word64
{-# INLINE lookupLayerMFrom1 #-}
lookupLayerMFrom2 :: Word64 -> Word64 -> Word64 -> DVS.Vector Word64 -> (Word64, Word64)
lookupLayerMFrom2 i j r v =
let cmp w = (r - 1) < (w .&. 0xffffffff)
!k = (binarySearchPBounds cmp v i j - 1) `max` 0
!mw = v !!! fromIntegral k :: Word64
!mx = ( mw .&. 0x00000000ffffffff ) :: Word64
!ma = mx + ((mw .&. 0x000003ff00000000) .>. 32) :: Word64
!mb = ma + ((mw .&. 0x000ffc0000000000) .>. 42) :: Word64
!mc = mb + ((mw .&. 0x3ff0000000000000) .>. 52) :: Word64
in if
| r <= mx -> (0 , 0 )
| r <= ma -> (mx, k * 4 )
| r <= mb -> (ma, k * 4 + 1)
| r <= mc -> (mb, k * 4 + 2)
| otherwise -> (mc, k * 4 + 3)
{-# INLINE lookupLayerMFrom2 #-}