{-# LANGUAGE CPP, BangPatterns, MagicHash, CApiFFI, UnliftedFFITypes #-}
{-# LANGUAGE Trustworthy #-}
module Data.Hashable.LowLevel (
Salt,
defaultSalt,
hashInt,
hashInt64,
hashWord64,
hashPtrWithSalt,
hashByteArrayWithSalt,
) where
#include "MachDeps.h"
import Data.Array.Byte (ByteArray (..))
import Foreign.Ptr (Ptr, castPtr)
import GHC.Base (ByteArray#)
#ifdef HASHABLE_RANDOM_SEED
import System.IO.Unsafe (unsafePerformIO)
#endif
import Data.Hashable.Imports
import Data.Hashable.Mix
import Data.Hashable.XXH3
#ifdef HASHABLE_RANDOM_SEED
initialSeed :: Word64
initialSeed = unsafePerformIO initialSeedC
{-# NOINLINE initialSeed #-}
foreign import capi "HsHashable.h hs_hashable_init" initialSeedC :: IO Word64
#endif
defaultSalt :: Salt
#ifdef HASHABLE_RANDOM_SEED
defaultSalt = hashInt defaultSalt' (fromIntegral initialSeed)
#else
defaultSalt :: Salt
defaultSalt = Salt
defaultSalt'
#endif
{-# INLINE defaultSalt #-}
defaultSalt' :: Salt
#if WORD_SIZE_IN_BITS == 64
defaultSalt' :: Salt
defaultSalt' = -Salt
3750763034362895579
#else
defaultSalt' = -2128831035
#endif
{-# INLINE defaultSalt' #-}
hashInt :: Salt -> Int -> Salt
hashInt :: Salt -> Salt -> Salt
hashInt !Salt
s !Salt
x = Word -> Salt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Word -> Word
mixHash (Salt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Salt
s) (Salt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Salt
x))
hashInt64 :: Salt -> Int64 -> Salt
hashWord64 :: Salt -> Word64 -> Salt
#if WORD_SIZE_IN_BITS == 64
hashInt64 :: Salt -> Int64 -> Salt
hashInt64 !Salt
s !Int64
x = Salt -> Salt -> Salt
hashInt Salt
s (Int64 -> Salt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
x)
hashWord64 :: Salt -> Word64 -> Salt
hashWord64 !Salt
s !Word64
x = Salt -> Salt -> Salt
hashInt Salt
s (Word64 -> Salt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
x)
#else
hashInt64 !s !x = hashInt (hashInt s (fromIntegral x)) (fromIntegral (x `unsafeShiftR` 32))
hashWord64 !s !x = hashInt (hashInt s (fromIntegral x)) (fromIntegral (x `unsafeShiftR` 32))
#endif
hashPtrWithSalt :: Ptr a
-> Int
-> Salt
-> IO Salt
hashPtrWithSalt :: forall a. Ptr a -> Salt -> Salt -> IO Salt
hashPtrWithSalt Ptr a
ptr Salt
len Salt
salt =
Word64 -> Salt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Salt) -> IO Word64 -> IO Salt
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Ptr Word8 -> Salt -> Word64 -> IO Word64
xxh3_64bit_withSeed_ptr (Ptr a -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr a
ptr) Salt
len (Salt -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Salt
salt)
hashByteArrayWithSalt
:: ByteArray#
-> Int
-> Int
-> Salt
-> Salt
hashByteArrayWithSalt :: ByteArray# -> Salt -> Salt -> Salt -> Salt
hashByteArrayWithSalt ByteArray#
ba !Salt
off !Salt
len !Salt
salt =
Word64 -> Salt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteArray -> Salt -> Salt -> Word64 -> Word64
xxh3_64bit_withSeed_ba (ByteArray# -> ByteArray
ByteArray ByteArray#
ba) Salt
off Salt
len (Salt -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Salt
salt))