{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
module Data.HashTable.Internal.IntArray
( IntArray
, Elem
, elemMask
, primWordToElem
, elemToInt
, elemToInt#
, newArray
, readArray
, writeArray
, length
, toPtr
) where
import Control.Monad.ST
import Data.Bits
import qualified Data.Primitive.ByteArray as A
#if !MIN_VERSION_primitive(0,7,0)
import Data.Primitive.Types (Addr (..))
#endif
import GHC.Exts
import GHC.Word
import Prelude hiding (length)
#ifdef BOUNDS_CHECKING
#define BOUNDS_MSG(sz,i) concat [ "[", __FILE__, ":", \
show (__LINE__ :: Int), \
"] bounds check exceeded: ", \
"size was ", show (sz), " i was ", show (i) ]
#define BOUNDS_CHECK(arr,i) let sz = (A.sizeofMutableByteArray (arr) \
`div` wordSizeInBytes) in \
if (i) < 0 || (i) >= sz \
then error (BOUNDS_MSG(sz,(i))) \
else return ()
#else
#define BOUNDS_CHECK(arr,i)
#endif
newtype IntArray s = IA (A.MutableByteArray s)
type Elem = Word16
primWordToElem :: Word# -> Elem
primWordToElem :: Word# -> Elem
primWordToElem Word#
w# = Word# -> Elem
W16# (Word# -> Word#
wordToWord16Compat# Word#
w#)
elemToInt :: Elem -> Int
elemToInt :: Elem -> Int
elemToInt Elem
e = let !i# :: Int#
i# = Elem -> Int#
elemToInt# Elem
e
in (Int# -> Int
I# Int#
i#)
elemToInt# :: Elem -> Int#
elemToInt# :: Elem -> Int#
elemToInt# (W16# Word#
w#) = Word# -> Int#
word2Int# (Word# -> Word#
word16ToWordCompat# Word#
w#)
elemMask :: Int
elemMask :: Int
elemMask = Int
0xffff
wordSizeInBytes :: Int
wordSizeInBytes :: Int
wordSizeInBytes = Elem -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (Elem
0::Elem) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
8
cacheLineSize :: Int
cacheLineSize :: Int
cacheLineSize = Int
64
newArray :: Int -> ST s (IntArray s)
newArray :: Int -> ST s (IntArray s)
newArray Int
n = do
let !sz :: Int
sz = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
wordSizeInBytes
!MutableByteArray s
arr <- Int -> Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> Int -> m (MutableByteArray (PrimState m))
A.newAlignedPinnedByteArray Int
sz Int
cacheLineSize
MutableByteArray (PrimState (ST s))
-> Int -> Int -> Word8 -> ST s ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> Int -> Int -> Word8 -> m ()
A.fillByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
arr Int
0 Int
sz Word8
0
IntArray s -> ST s (IntArray s)
forall (m :: * -> *) a. Monad m => a -> m a
return (IntArray s -> ST s (IntArray s))
-> IntArray s -> ST s (IntArray s)
forall a b. (a -> b) -> a -> b
$! MutableByteArray s -> IntArray s
forall s. MutableByteArray s -> IntArray s
IA MutableByteArray s
arr
readArray :: IntArray s -> Int -> ST s Elem
readArray :: IntArray s -> Int -> ST s Elem
readArray (IA MutableByteArray s
a) Int
idx = do
BOUNDS_CHECK(a,idx)
MutableByteArray (PrimState (ST s)) -> Int -> ST s Elem
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
A.readByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
a Int
idx
writeArray :: IntArray s -> Int -> Elem -> ST s ()
writeArray :: IntArray s -> Int -> Elem -> ST s ()
writeArray (IA MutableByteArray s
a) Int
idx Elem
val = do
BOUNDS_CHECK(a,idx)
MutableByteArray (PrimState (ST s)) -> Int -> Elem -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
A.writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
a Int
idx Elem
val
length :: IntArray s -> Int
length :: IntArray s -> Int
length (IA MutableByteArray s
a) = MutableByteArray s -> Int
forall s. MutableByteArray s -> Int
A.sizeofMutableByteArray MutableByteArray s
a Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
wordSizeInBytes
toPtr :: IntArray s -> Ptr a
toPtr :: IntArray s -> Ptr a
toPtr (IA MutableByteArray s
a) = Addr# -> Ptr a
forall a. Addr# -> Ptr a
Ptr Addr#
a#
where
#if MIN_VERSION_primitive(0,7,0)
!(Ptr !Addr#
a#) = MutableByteArray s -> Ptr Word8
forall s. MutableByteArray s -> Ptr Word8
A.mutableByteArrayContents MutableByteArray s
a
#else
!(Addr !a#) = A.mutableByteArrayContents a
#endif
#if MIN_VERSION_base(4,16,0)
word16ToWordCompat# :: Word16# -> Word#
word16ToWordCompat# = word16ToWord#
wordToWord16Compat# :: Word# -> Word16#
wordToWord16Compat# = wordToWord16#
#else
word16ToWordCompat# :: Word# -> Word#
word16ToWordCompat# :: Word# -> Word#
word16ToWordCompat# Word#
x = Word#
x
wordToWord16Compat# :: Word# -> Word#
wordToWord16Compat# :: Word# -> Word#
wordToWord16Compat# Word#
x = Word#
x
#endif