{-# OPTIONS_GHC-funbox-strict-fields #-}
{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE Rank2Types          #-}
{-# LANGUAGE ScopedTypeVariables #-}

module HaskellWorks.Data.RankSelect.CsPoppy.Internal.Reference
    ( makeCsPoppyLayerM
    ) where

import Data.Word
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Length
import HaskellWorks.Data.RankSelect.CsPoppy.Internal.Vector

import qualified Data.Vector.Storable as DVS

makeCsPoppyLayerM :: DVS.Vector Word64 -> DVS.Vector Word64
makeCsPoppyLayerM :: Vector Word64 -> Vector Word64
makeCsPoppyLayerM Vector Word64
blocks = Int -> (Vector Word64 -> Word64) -> Vector Word64
forall a. Storable a => Int -> (Vector a -> a) -> Vector a
DVS.constructN (((Vector Word64 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word64
blocks Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
4) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Vector Word64 -> Word64
genLayer1
  where genLayer1 :: DVS.Vector Word64 -> Word64
        genLayer1 :: Vector Word64 -> Word64
genLayer1 Vector Word64
u =
          let i :: Position
i  = Vector Word64 -> Position
forall v. Length v => v -> Position
end Vector Word64
u                          in
          let lx :: Word64
lx = Vector Word64 -> Word64
lastOrZero Vector Word64
u                   in
          let la :: Word64
la = Vector Word64 -> Position -> Word64
indexOrZero Vector Word64
blocks (Position
i Position -> Position -> Position
forall a. Num a => a -> a -> a
* Position
4 Position -> Position -> Position
forall a. Num a => a -> a -> a
- Position
4) in
          let lb :: Word64
lb = Vector Word64 -> Position -> Word64
indexOrZero Vector Word64
blocks (Position
i Position -> Position -> Position
forall a. Num a => a -> a -> a
* Position
4 Position -> Position -> Position
forall a. Num a => a -> a -> a
- Position
3) in
          let lc :: Word64
lc = Vector Word64 -> Position -> Word64
indexOrZero Vector Word64
blocks (Position
i Position -> Position -> Position
forall a. Num a => a -> a -> a
* Position
4 Position -> Position -> Position
forall a. Num a => a -> a -> a
- Position
2) in
          let ld :: Word64
ld = Vector Word64 -> Position -> Word64
indexOrZero Vector Word64
blocks (Position
i Position -> Position -> Position
forall a. Num a => a -> a -> a
* Position
4 Position -> Position -> Position
forall a. Num a => a -> a -> a
- Position
1) in
          let nx :: Word64
nx = Word64
lx Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ (Word64
la Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
lb Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
lc Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
ld)       in
          let na :: Word64
na = Vector Word64 -> Position -> Word64
indexOrZero Vector Word64
blocks (Position
i Position -> Position -> Position
forall a. Num a => a -> a -> a
* Position
4 Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Position
0) in
          let nb :: Word64
nb = Vector Word64 -> Position -> Word64
indexOrZero Vector Word64
blocks (Position
i Position -> Position -> Position
forall a. Num a => a -> a -> a
* Position
4 Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Position
1) in
          let nc :: Word64
nc = Vector Word64 -> Position -> Word64
indexOrZero Vector Word64
blocks (Position
i Position -> Position -> Position
forall a. Num a => a -> a -> a
* Position
4 Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Position
2) in
          (   ( Word64
nx         Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x00000000ffffffff)
          Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. ((Word64
na Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
32) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x000003ff00000000)
          Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. ((Word64
nb Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
42) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x000ffc0000000000)
          Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. ((Word64
nc Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
52) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x3ff0000000000000))