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

module HaskellWorks.Data.RankSelect.CsPoppy.Internal.CsInterleaved
    ( CsInterleaved(..)
    , getCsiX
    , getCsiA
    , getCsiB
    , getCsiC
    , getCsiTotal
    , mkCsi
    , putCsiX
    , putCsiA
    , putCsiB
    , putCsiC
    ) where

import Data.Word
import Foreign.Ptr
import Foreign.Storable
import HaskellWorks.Data.Bits.BitWise

newtype CsInterleaved = CsInterleaved { CsInterleaved -> Word64
unCsInterleaved :: Word64 } deriving CsInterleaved -> CsInterleaved -> Bool
(CsInterleaved -> CsInterleaved -> Bool)
-> (CsInterleaved -> CsInterleaved -> Bool) -> Eq CsInterleaved
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CsInterleaved -> CsInterleaved -> Bool
$c/= :: CsInterleaved -> CsInterleaved -> Bool
== :: CsInterleaved -> CsInterleaved -> Bool
$c== :: CsInterleaved -> CsInterleaved -> Bool
Eq

instance Storable CsInterleaved where
  sizeOf :: CsInterleaved -> Int
sizeOf = Word64 -> Int
forall a. Storable a => a -> Int
sizeOf (Word64 -> Int)
-> (CsInterleaved -> Word64) -> CsInterleaved -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsInterleaved -> Word64
unCsInterleaved
  {-# INLINE sizeOf #-}
  alignment :: CsInterleaved -> Int
alignment = Word64 -> Int
forall a. Storable a => a -> Int
alignment (Word64 -> Int)
-> (CsInterleaved -> Word64) -> CsInterleaved -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsInterleaved -> Word64
unCsInterleaved
  {-# INLINE alignment #-}
  peekElemOff :: Ptr CsInterleaved -> Int -> IO CsInterleaved
peekElemOff Ptr CsInterleaved
ptr Int
i = Word64 -> CsInterleaved
CsInterleaved (Word64 -> CsInterleaved) -> IO Word64 -> IO CsInterleaved
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word64 -> Int -> IO Word64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr CsInterleaved -> Ptr Word64
forall a b. Ptr a -> Ptr b
castPtr Ptr CsInterleaved
ptr) Int
i
  {-# INLINE peekElemOff #-}
  pokeElemOff :: Ptr CsInterleaved -> Int -> CsInterleaved -> IO ()
pokeElemOff Ptr CsInterleaved
ptr Int
i = Ptr Word64 -> Int -> Word64 -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff (Ptr CsInterleaved -> Ptr Word64
forall a b. Ptr a -> Ptr b
castPtr Ptr CsInterleaved
ptr) Int
i (Word64 -> IO ())
-> (CsInterleaved -> Word64) -> CsInterleaved -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsInterleaved -> Word64
unCsInterleaved
  {-# INLINE pokeElemOff #-}

mkCsi :: Word64 -> Word64 -> Word64 -> Word64 -> CsInterleaved
mkCsi :: Word64 -> Word64 -> Word64 -> Word64 -> CsInterleaved
mkCsi Word64
x Word64
a Word64
b Word64
c = Word64 -> CsInterleaved
CsInterleaved
    (Word64 -> CsInterleaved) -> Word64 -> CsInterleaved
forall a b. (a -> b) -> a -> b
$   ((Word64
x Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0xffffffff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<.  Word64
0)
    Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. ((Word64
a Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&.      Word64
0x3ff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
32)
    Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. ((Word64
b Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&.      Word64
0x3ff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
42)
    Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. ((Word64
c Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&.      Word64
0x3ff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
52)

getCsiX :: CsInterleaved -> Word64
getCsiX :: CsInterleaved -> Word64
getCsiX (CsInterleaved Word64
i) = Word64
i Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0xffffffff

getCsiA :: CsInterleaved -> Word64
getCsiA :: CsInterleaved -> Word64
getCsiA (CsInterleaved Word64
i) = (Word64
i Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.>. Word64
32) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x3ff

getCsiB :: CsInterleaved -> Word64
getCsiB :: CsInterleaved -> Word64
getCsiB (CsInterleaved Word64
i) = (Word64
i Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.>. Word64
42) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x3ff

getCsiC :: CsInterleaved -> Word64
getCsiC :: CsInterleaved -> Word64
getCsiC (CsInterleaved Word64
i) = (Word64
i Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.>. Word64
52) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x3ff

getCsiTotal :: CsInterleaved -> Word64
getCsiTotal :: CsInterleaved -> Word64
getCsiTotal CsInterleaved
csi = CsInterleaved -> Word64
getCsiX CsInterleaved
csi Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ CsInterleaved -> Word64
getCsiA CsInterleaved
csi Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ CsInterleaved -> Word64
getCsiB CsInterleaved
csi Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ CsInterleaved -> Word64
getCsiC CsInterleaved
csi

putCsiX :: Word64 -> CsInterleaved -> CsInterleaved
putCsiX :: Word64 -> CsInterleaved -> CsInterleaved
putCsiX Word64
v (CsInterleaved Word64
i) = Word64 -> CsInterleaved
CsInterleaved (((Word64
v Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0xffffffff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<.  Word64
0) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. (Word64
i Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0xffffffff00000000))

putCsiA :: Word64 -> CsInterleaved -> CsInterleaved
putCsiA :: Word64 -> CsInterleaved -> CsInterleaved
putCsiA Word64
v (CsInterleaved Word64
i) = Word64 -> CsInterleaved
CsInterleaved (((Word64
v Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&.      Word64
0x3ff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
32) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. (Word64
i Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0xfffffc00ffffffff))

putCsiB :: Word64 -> CsInterleaved -> CsInterleaved
putCsiB :: Word64 -> CsInterleaved -> CsInterleaved
putCsiB Word64
v (CsInterleaved Word64
i) = Word64 -> CsInterleaved
CsInterleaved (((Word64
v Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&.      Word64
0x3ff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
42) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. (Word64
i Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0xfff003ffffffffff))

putCsiC :: Word64 -> CsInterleaved -> CsInterleaved
putCsiC :: Word64 -> CsInterleaved -> CsInterleaved
putCsiC Word64
v (CsInterleaved Word64
i) = Word64 -> CsInterleaved
CsInterleaved (((Word64
v Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&.      Word64
0x3ff) Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.<. Word64
52) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. (Word64
i Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0xc00fffffffffffff))

instance Show CsInterleaved where
  showsPrec :: Int -> CsInterleaved -> ShowS
showsPrec Int
_ CsInterleaved
i = (Word64, Word64, Word64, Word64) -> ShowS
forall a. Show a => a -> ShowS
shows (CsInterleaved -> Word64
getCsiX CsInterleaved
i, CsInterleaved -> Word64
getCsiA CsInterleaved
i, CsInterleaved -> Word64
getCsiB CsInterleaved
i, CsInterleaved -> Word64
getCsiC CsInterleaved
i)