{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
module Data.HashTable.Internal.Utils
( whichBucket
, nextBestPrime
, bumpSize
, shiftL
, shiftRL
, iShiftL
, iShiftRL
, nextHighestPowerOf2
, log2
, highestBitMask
, wordSize
, cacheLineSize
, numElemsInCacheLine
, cacheLineIntMask
, cacheLineIntBits
, forceSameType
, unsafeIOToST
) where
import Data.Bits hiding (shiftL)
import Data.HashTable.Internal.IntArray (Elem)
import Data.Vector (Vector)
import qualified Data.Vector as V
#if __GLASGOW_HASKELL__ >= 503
import GHC.Exts
#else
import qualified Data.Bits
import Data.Word
#endif
#if MIN_VERSION_base(4,4,0)
import Control.Monad.ST.Unsafe (unsafeIOToST)
#else
import Control.Monad.ST (unsafeIOToST)
#endif
wordSize :: Int
wordSize :: Int
wordSize = Int -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (0::Int)
cacheLineSize :: Int
cacheLineSize :: Int
cacheLineSize = 64
numElemsInCacheLine :: Int
numElemsInCacheLine :: Int
numElemsInCacheLine = Int
z
where
!z :: Int
z = Int
cacheLineSize Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` (Elem -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (0::Elem) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` 8)
cacheLineIntMask :: Int
cacheLineIntMask :: Int
cacheLineIntMask = Int
z
where
!z :: Int
z = Int
numElemsInCacheLine Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1
cacheLineIntBits :: Int
cacheLineIntBits :: Int
cacheLineIntBits = Word -> Int
log2 (Word -> Int) -> Word -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Word
forall a. Enum a => Int -> a
toEnum Int
numElemsInCacheLine
{-# INLINE whichBucket #-}
whichBucket :: Int -> Int -> Int
whichBucket :: Int -> Int -> Int
whichBucket !Int
h !Int
sz = Int
o
where
!o :: Int
o = Int
h Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
sz
binarySearch :: (Ord e) => Vector e -> e -> Int
binarySearch :: Vector e -> e -> Int
binarySearch = (e -> e -> Ordering) -> Vector e -> e -> Int
forall e. (e -> e -> Ordering) -> Vector e -> e -> Int
binarySearchBy e -> e -> Ordering
forall a. Ord a => a -> a -> Ordering
compare
{-# INLINE binarySearch #-}
binarySearchBy :: (e -> e -> Ordering)
-> Vector e
-> e
-> Int
binarySearchBy :: (e -> e -> Ordering) -> Vector e -> e -> Int
binarySearchBy cmp :: e -> e -> Ordering
cmp vec :: Vector e
vec e :: e
e = (e -> e -> Ordering) -> Vector e -> e -> Int -> Int -> Int
forall e.
(e -> e -> Ordering) -> Vector e -> e -> Int -> Int -> Int
binarySearchByBounds e -> e -> Ordering
cmp Vector e
vec e
e 0 (Vector e -> Int
forall a. Vector a -> Int
V.length Vector e
vec)
{-# INLINE binarySearchBy #-}
binarySearchByBounds :: (e -> e -> Ordering)
-> Vector e
-> e
-> Int
-> Int
-> Int
binarySearchByBounds :: (e -> e -> Ordering) -> Vector e -> e -> Int -> Int -> Int
binarySearchByBounds cmp :: e -> e -> Ordering
cmp vec :: Vector e
vec e :: e
e = Int -> Int -> Int
loop
where
loop :: Int -> Int -> Int
loop !Int
l !Int
u
| Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l = Int
l
| Bool
otherwise = let e' :: e
e' = Vector e -> Int -> e
forall a. Vector a -> Int -> a
V.unsafeIndex Vector e
vec Int
k
in case e -> e -> Ordering
cmp e
e' e
e of
LT -> Int -> Int -> Int
loop (Int
kInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Int
u
EQ -> Int
k
GT -> Int -> Int -> Int
loop Int
l Int
k
where k :: Int
k = (Int
u Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
l) Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` 1
{-# INLINE binarySearchByBounds #-}
primeSizes :: Vector Integer
primeSizes :: Vector Integer
primeSizes = [Integer] -> Vector Integer
forall a. [a] -> Vector a
V.fromList [ 19
, 31
, 37
, 43
, 47
, 53
, 61
, 67
, 79
, 89
, 97
, 107
, 113
, 127
, 137
, 149
, 157
, 167
, 181
, 193
, 211
, 233
, 257
, 281
, 307
, 331
, 353
, 389
, 409
, 421
, 443
, 467
, 503
, 523
, 563
, 593
, 631
, 653
, 673
, 701
, 733
, 769
, 811
, 877
, 937
, 1039
, 1117
, 1229
, 1367
, 1543
, 1637
, 1747
, 1873
, 2003
, 2153
, 2311
, 2503
, 2777
, 3079
, 3343
, 3697
, 5281
, 6151
, 7411
, 9901
, 12289
, 18397
, 24593
, 34651
, 49157
, 66569
, 73009
, 98317
, 118081
, 151051
, 196613
, 246011
, 393241
, 600011
, 786433
, 1050013
, 1572869
, 2203657
, 3145739
, 4000813
, 6291469
, 7801379
, 10004947
, 12582917
, 19004989
, 22752641
, 25165843
, 39351667
, 50331653
, 69004951
, 83004629
, 100663319
, 133004881
, 173850851
, 201326611
, 293954587
, 402653189
, 550001761
, 702952391
, 805306457
, 1102951999
, 1402951337
, 1610612741
, 1902802801
, 2147483647
, 3002954501
, 3902954959
, 4294967291
, 5002902979
, 6402754181
, 8589934583
, 17179869143
, 34359738337
, 68719476731
, 137438953447
, 274877906899 ]
nextBestPrime :: Int -> Int
nextBestPrime :: Int -> Int
nextBestPrime x :: Int
x = Integer -> Int
forall a. Enum a => a -> Int
fromEnum Integer
yi
where
xi :: Integer
xi = Int -> Integer
forall a. Enum a => Int -> a
toEnum Int
x
idx :: Int
idx = Vector Integer -> Integer -> Int
forall e. Ord e => Vector e -> e -> Int
binarySearch Vector Integer
primeSizes Integer
xi
yi :: Integer
yi = Vector Integer -> Int -> Integer
forall a. Vector a -> Int -> a
V.unsafeIndex Vector Integer
primeSizes Int
idx
bumpSize :: Double -> Int -> Int
bumpSize :: Double -> Int -> Int
bumpSize !Double
maxLoad !Int
s = Int -> Int
nextBestPrime (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$! Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
s Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
maxLoad)
shiftL :: Word -> Int -> Word
shiftRL :: Word -> Int -> Word
iShiftL :: Int -> Int -> Int
iShiftRL :: Int -> Int -> Int
#if __GLASGOW_HASKELL__
{-# INLINE shiftL #-}
shiftL :: Word -> Int -> Word
shiftL (W# x :: Word#
x) (I# i :: Int#
i)
= Word# -> Word
W# (Word# -> Int# -> Word#
shiftL# Word#
x Int#
i)
{-# INLINE shiftRL #-}
shiftRL :: Word -> Int -> Word
shiftRL (W# x :: Word#
x) (I# i :: Int#
i)
= Word# -> Word
W# (Word# -> Int# -> Word#
shiftRL# Word#
x Int#
i)
{-# INLINE iShiftL #-}
iShiftL :: Int -> Int -> Int
iShiftL (I# x :: Int#
x) (I# i :: Int#
i)
= Int# -> Int
I# (Int# -> Int# -> Int#
iShiftL# Int#
x Int#
i)
{-# INLINE iShiftRL #-}
iShiftRL :: Int -> Int -> Int
iShiftRL (I# x :: Int#
x) (I# i :: Int#
i)
= Int# -> Int
I# (Int# -> Int# -> Int#
iShiftRL# Int#
x Int#
i)
#else
shiftL x i = Data.Bits.shiftL x i
shiftRL x i = shiftR x i
iShiftL x i = shiftL x i
iShiftRL x i = shiftRL x i
#endif
{-# INLINE nextHighestPowerOf2 #-}
nextHighestPowerOf2 :: Word -> Word
nextHighestPowerOf2 :: Word -> Word
nextHighestPowerOf2 w :: Word
w = Word -> Word
highestBitMask (Word
wWord -> Word -> Word
forall a. Num a => a -> a -> a
-1) Word -> Word -> Word
forall a. Num a => a -> a -> a
+ 1
log2 :: Word -> Int
log2 :: Word -> Int
log2 w :: Word
w = Word -> Int -> Int
forall t. Num t => Word -> t -> t
go (Word -> Word
nextHighestPowerOf2 Word
w) 0
where
go :: Word -> t -> t
go 0 !t
i = t
it -> t -> t
forall a. Num a => a -> a -> a
-1
go !Word
n !t
i = Word -> t -> t
go (Word -> Int -> Word
shiftRL Word
n 1) (t
it -> t -> t
forall a. Num a => a -> a -> a
+1)
{-# INLINE highestBitMask #-}
highestBitMask :: Word -> Word
highestBitMask :: Word -> Word
highestBitMask !Word
x0 = case (Word
x0 Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word -> Int -> Word
shiftRL Word
x0 1) of
x1 :: Word
x1 -> case (Word
x1 Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word -> Int -> Word
shiftRL Word
x1 2) of
x2 :: Word
x2 -> case (Word
x2 Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word -> Int -> Word
shiftRL Word
x2 4) of
x3 :: Word
x3 -> case (Word
x3 Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word -> Int -> Word
shiftRL Word
x3 8) of
x4 :: Word
x4 -> case (Word
x4 Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word -> Int -> Word
shiftRL Word
x4 16) of
x5 :: Word
x5 -> Word
x5 Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word -> Int -> Word
shiftRL Word
x5 32
forceSameType :: Monad m => a -> a -> m ()
forceSameType :: a -> a -> m ()
forceSameType _ _ = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
{-# INLINE forceSameType #-}