module Data.Hashabler.Internal where
import Data.Word
import Data.Int
import Data.Bits
import Data.Char
import Data.List
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B
import qualified Data.ByteString.Lazy.Internal as BL (foldlChunks, ByteString)
#if MIN_VERSION_bytestring(0,10,4)
import qualified Data.ByteString.Short.Internal as BSh
#endif
import qualified Data.Text as T
import qualified Data.Text.Internal as T
import qualified Data.Text.Array as T (Array(..))
import qualified Data.Primitive as P
import qualified Data.Text.Lazy as TL (foldlChunks, Text)
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Storable (peekByteOff)
import Control.Exception(assert)
import Data.Version(Version, versionBranch)
import Data.Unique(Unique, hashUnique)
import Foreign.C (CInt(..))
import GHC.Conc(ThreadId(..))
import GHC.Prim(ThreadId#)
import Data.Typeable
import GHC.Fingerprint.Type(Fingerprint(..))
#if __GLASGOW_HASKELL__ >= 710
#else
import Data.Typeable.Internal(TypeRep(..))
#endif
import System.Mem.StableName
import Data.Ratio (Ratio, denominator, numerator)
#ifdef MIN_VERSION_integer_gmp
import GHC.Exts (Int(..))
import GHC.Integer.GMP.Internals (Integer(..))
# if MIN_VERSION_integer_gmp(1,0,0)
import GHC.Integer.GMP.Internals (BigNat(BN#))
# endif
#endif
#if MIN_VERSION_base(4,8,0)
import Data.Void (Void, absurd)
import GHC.Natural (Natural(..))
# ifdef MIN_VERSION_integer_gmp
import GHC.Exts (Word(..))
# endif
#endif
#include "MachDeps.h"
import MachDeps
#if WORD_SIZE_IN_BITS == 32
#define LOG_SIZEOF_WORD 2
#elif WORD_SIZE_IN_BITS == 64
#define LOG_SIZEOF_WORD 3
#else
#error We only know how to support 32-bit and 64-bit systems, sorry.
#endif
import Unsafe.Coerce
# if MIN_VERSION_bytestring(0,10,6)
import Data.ByteString.Internal(accursedUnutterablePerformIO)
# else
import System.IO.Unsafe (unsafeDupablePerformIO)
accursedUnutterablePerformIO :: IO a -> a
accursedUnutterablePerformIO = unsafeDupablePerformIO
# endif
coerceInt32Word32 :: Int32 -> Word32
coerceInt32Word32 =
# if WORD_SIZE_IN_BITS == 32
unsafeCoerce
# else
fromIntegral
# endif
coerceInt64Word64 :: Int64 -> Word64
coerceInt64Word64 = unsafeCoerce
#if WORD_SIZE_IN_BITS == 32
unsafeCoerceIntWord32 :: Int -> Word32
unsafeCoerceIntWord32 = unsafeCoerce
#endif
#if MIN_VERSION_base(4,7,0)
#else
byteSwap32 :: Word32 -> Word32
byteSwap32 = _byteSwap32
# if WORD_SIZE_IN_BITS == 64
byteSwap64 :: Word64 -> Word64
byteSwap64 = _byteSwap64
# endif
#endif
_byteSwap32 :: Word32 -> Word32
_byteSwap32 = \w->
let mask0 = 0xFF000000
mask1 = 0x00FF0000
mask2 = 0x0000FF00
mask3 = 0x000000FF
in (unsafeShiftR (w .&. mask0) 24) .|.
(unsafeShiftR (w .&. mask1) 8) .|.
(unsafeShiftL (w .&. mask2) 8) .|.
(unsafeShiftL (w .&. mask3) 24)
_byteSwap64 :: Word64 -> Word64
_byteSwap64 = \w->
let mask0 = 0xFF00000000000000
mask1 = 0x00FF000000000000
mask2 = 0x0000FF0000000000
mask3 = 0x000000FF00000000
mask4 = 0x00000000FF000000
mask5 = 0x0000000000FF0000
mask6 = 0x000000000000FF00
mask7 = 0x00000000000000FF
in (unsafeShiftR (w .&. mask0) 56) .|.
(unsafeShiftR (w .&. mask1) 40) .|.
(unsafeShiftR (w .&. mask2) 24) .|.
(unsafeShiftR (w .&. mask3) 8) .|.
(unsafeShiftL (w .&. mask4) 8) .|.
(unsafeShiftL (w .&. mask5) 24) .|.
(unsafeShiftL (w .&. mask6) 40) .|.
(unsafeShiftL (w .&. mask7) 56)
foreign import ccall unsafe "rts_getThreadId" getThreadId :: ThreadId# -> CInt
bytes16 :: Word16 -> (Word8, Word8)
bytes16 wd = (shifted 8, fromIntegral wd)
where shifted = fromIntegral . unsafeShiftR wd
bytes32 :: Word32 -> (Word8,Word8,Word8,Word8)
bytes32 wd = (shifted 24, shifted 16, shifted 8, fromIntegral wd)
where shifted = fromIntegral . unsafeShiftR wd
bytes64 :: Word64 -> (Word8,Word8,Word8,Word8,Word8,Word8,Word8,Word8)
bytes64 = \wd64->
# if WORD_SIZE_IN_BITS == 32
_bytes64_32 wd64
# else
_bytes64_64 wd64
# endif
_bytes64_64 :: Word64 -> (Word8,Word8,Word8,Word8,Word8,Word8,Word8,Word8)
_bytes64_64 wd = ( shifted 56, shifted 48, shifted 40, shifted 32
, shifted 24, shifted 16, shifted 8, fromIntegral wd)
where shifted = fromIntegral . unsafeShiftR wd
_bytes64_32 :: Word64 -> (Word8,Word8,Word8,Word8,Word8,Word8,Word8,Word8)
_bytes64_32 wd =
let (wd0, wd1) = words32 wd
(b0,b1,b2,b3) = bytes32 wd0
(b4,b5,b6,b7) = bytes32 wd1
in (b0,b1,b2,b3,b4,b5,b6,b7)
words32 :: Word64 -> (Word32, Word32)
words32 wd64 = (fromIntegral $ unsafeShiftR wd64 32, fromIntegral wd64)
newtype Hash32 a = Hash32 { hashWord32 :: Word32 }
deriving (Show, Read, Eq)
newtype Hash64 a = Hash64 { hashWord64 :: Word64 }
deriving (Show, Read, Eq)
data Hash128 a = Hash128 { hashWord128_0 :: !Word64, hashWord128_1 :: !Word64 }
deriving (Show, Read, Eq)
class Hashable a where
hash :: (HashState h)=> h -> a -> h
class HashState h where
mix8 :: h -> Word8 -> h
mix16 :: h -> Word16 -> h
mix32 :: h -> Word32 -> h
mix64 :: h -> Word64 -> h
mix16 h = \wd16->
let (wd8_0,wd8_1) = bytes16 wd16
in h `mix8` wd8_0 `mix8` wd8_1
mix32 h = \wd32->
let (b0,b1,b2,b3) = bytes32 wd32
in h `mix8` b0 `mix8` b1 `mix8` b2 `mix8` b3
mix64 h = \wd64->
let (w32_0, w32_1) = words32 wd64
in h `mix32` w32_0 `mix32` w32_1
fnvPrime32 :: Word32
fnvPrime64 :: Word64
fnvPrime32 = 16777619
fnvPrime64 = 1099511628211
fnvOffsetBasis32 :: FNV32
fnvOffsetBasis64 :: FNV64
fnvOffsetBasis32 = FNV32 2166136261
fnvOffsetBasis64 = FNV64 14695981039346656037
newtype FNV32 = FNV32 { fnv32 :: Word32 }
deriving (Eq, Ord, Read, Show)
newtype FNV64 = FNV64 { fnv64 :: Word64 }
deriving (Eq, Ord, Read, Show)
instance HashState FNV32 where
mix8 (FNV32 h32) = \b-> FNV32 $ (h32 `xor` fromIntegral b) * fnvPrime32
hashFNV32 :: Hashable a=> a -> Hash32 a
hashFNV32 = Hash32 . fnv32 . hash fnvOffsetBasis32
instance HashState FNV64 where
mix8 (FNV64 h64) = \b-> FNV64 $ (h64 `xor` fromIntegral b) * fnvPrime64
hashFNV64 :: Hashable a=> a -> Hash64 a
hashFNV64 = Hash64 . fnv64 . hash fnvOffsetBasis64
instance Hashable Integer where
#ifdef MIN_VERSION_integer_gmp
hash h = \i-> case i of
(S# n#) ->
let magWord = magnitudeAsWord (I# n#)
sign = _signByte (I# n#)
in mixConstructor sign $
# if WORD_SIZE_IN_BITS == 32
h `mix32` magWord
# else
h `mixSignificantMachWord64` magWord
# endif
# if MIN_VERSION_integer_gmp(1,0,0)
(Jp# bn) -> mixConstructor 0 $ hash32BigNatBytes h bn
(Jn# bn) -> mixConstructor 1 $ hash32BigNatBytes h bn
# else
(J# 0# _) -> mixConstructor 0 (h `mix32` 0)
(J# sz# ba#) ->
let numLimbs = abs (I# sz#)
sign = _signByte (I# sz#)
in assert ((I# sz#) /= minBound) $
mixConstructor sign $
hash32BigNatByteArrayBytes h numLimbs (P.ByteArray ba#)
# endif
#else
hash = _hash32Integer
#endif
_signByte :: Int -> Word8
_signByte n = fromIntegral ((fromIntegral n :: Word)
`unsafeShiftR` (WORD_SIZE_IN_BITS 1))
magnitudeAsWord :: Int
# if WORD_SIZE_IN_BITS == 32
-> Word32
# else
-> Word64
# endif
magnitudeAsWord = fromIntegral . abs
#if WORD_SIZE_IN_BITS == 64
mixSignificantMachWord64 :: (HashState h)=> h -> Word64 -> h
mixSignificantMachWord64 h w64 =
let (word32_0, word32_1) = words32 w64
in if word32_0 == 0
then h `mix32` word32_1
else h `mix32` word32_0 `mix32` word32_1
#endif
_hash32Integer :: (HashState h)=> h -> Integer -> h
_hash32Integer h i =
let (sgn, limbs) = _integerWords i
in mixConstructor sgn $
foldl' hash h limbs
_integerWords :: Integer -> (Word8, [Word32])
_integerWords nSigned = (sign , go (abs nSigned) []) where
sign = if nSigned < 0 then 1 else 0
go nMag acc = let (nMag', w32) = splitAtLastWord nMag
in (if nMag' == 0 then id else go nMag') (w32:acc)
splitAtLastWord :: Integer -> (Integer, Word32)
splitAtLastWord x =
assert (x >= 0) $
(x `shiftR` 32, fromIntegral x)
#ifdef MIN_VERSION_integer_gmp
# if MIN_VERSION_integer_gmp(1,0,0)
hash32BigNatBytes :: (HashState h)=> h -> BigNat -> h
hash32BigNatBytes h (BN# ba#) =
let ba = P.ByteArray ba#
szBytes = P.sizeofByteArray ba
numLimbs = szBytes `unsafeShiftR` LOG_SIZEOF_WORD
in assert (numLimbs >= 1 && (numLimbs * SIZEOF_HSWORD) == szBytes) $
hash32BigNatByteArrayBytes h numLimbs ba
instance Hashable BigNat where
hash h = mixConstructor 0 . hash32BigNatBytes h
# endif
hash32BigNatByteArrayBytes :: (HashState h)=> h -> Int -> P.ByteArray -> h
hash32BigNatByteArrayBytes h numLimbs ba =
assert (numLimbs > 0) $
let mostSigLimbIx = numLimbs 1
go !h' (1) = h'
go !h' !ix = let wd = P.indexByteArray ba ix
in go (h' `mixWord` wd) (ix 1)
# if WORD_SIZE_IN_BITS == 32
mixWord = mix32
in go h mostSigLimbIx
# else
mixWord h' wd = let (wd32_0, wd32_1) = words32 wd
in h' `mix32` wd32_0 `mix32` wd32_1
h0 = let mostSigLimb = P.indexByteArray ba mostSigLimbIx
in h `mixSignificantMachWord64` mostSigLimb
ix0 = mostSigLimbIx 1
in go h0 ix0
# endif
#endif
#if MIN_VERSION_base(4,8,0)
instance Hashable Natural where
hash h nat = case nat of
# if defined (MIN_VERSION_integer_gmp)
# if MIN_VERSION_integer_gmp(1,0,0)
(NatS# wd#) -> mixConstructor 0 $
# if WORD_SIZE_IN_BITS == 32
h `mix32` (fromIntegral $ W# wd#)
# else
h `mixSignificantMachWord64` (fromIntegral $ W# wd#)
# endif
(NatJ# bn) -> hash h bn
# else
n -> hash h $ toInteger n
# endif
# else
n -> hash h $ toInteger n
# endif
instance Hashable Void where
hash _ = absurd
#endif
instance (Integral a, Hashable a) => Hashable (Ratio a) where
hash s a = s `hash` numerator a `hash` denominator a
instance Hashable Int where
hash h i =
# if WORD_SIZE_IN_BITS == 32
mix32 h $ unsafeCoerceIntWord32 i
# else
_hash32_Int_64 h (fromIntegral i)
# endif
instance Hashable Word where
hash h w =
# if WORD_SIZE_IN_BITS == 32
hash h (fromIntegral w :: Word32)
# else
_hash32_Word_64 h (fromIntegral w)
# endif
_hash32_Int_64 :: (HashState h)=> h -> Int64 -> h
_hash32_Int_64 h = \i->
if i <= (fromIntegral (maxBound :: Int32)) &&
i >= (fromIntegral (minBound :: Int32))
then hash h (fromIntegral i :: Int32)
else hash h i
_hash32_Word_64 :: (HashState h)=> h -> Word64 -> h
_hash32_Word_64 h = \w->
if w <= (fromIntegral (maxBound :: Word32))
then hash h (fromIntegral w :: Word32)
else hash h w
instance Hashable Float where
hash h = hash h . (\x-> decodeFloat x)
instance Hashable Double where
hash h = hash h . (\x-> decodeFloat x)
instance Hashable Int8 where
hash h = mix8 h . fromIntegral
instance Hashable Int16 where
hash h = mix16 h . fromIntegral
instance Hashable Int32 where
hash h = mix32 h . coerceInt32Word32
instance Hashable Int64 where
hash h = mix64 h . coerceInt64Word64
instance Hashable Word8 where
hash = mix8
instance Hashable Word16 where
hash = mix16
instance Hashable Word32 where
hash = mix32
instance Hashable Word64 where
hash = mix64
mixConstructor :: (HashState h)
=> Word8
-> h
-> h
mixConstructor n = \h-> h `mix8` (0xFF n)
instance Hashable B.ByteString where
hash h = mixConstructor 0 .
hashByteString h
instance Hashable BL.ByteString where
hash h = mixConstructor 0 .
BL.foldlChunks hashByteString h
#if MIN_VERSION_bytestring(0,10,4)
instance Hashable BSh.ShortByteString where
hash h =
\(BSh.SBS ba_) ->
let ba = P.ByteArray ba_
in mixConstructor 0 $
hashByteArray h (P.sizeofByteArray ba) ba
#endif
instance Hashable T.Text where
hash h = mixConstructor 0 .
hashText h
instance Hashable TL.Text where
hash h = mixConstructor 0 .
TL.foldlChunks hashText h
instance Hashable P.ByteArray where
hash h = \ba-> mixConstructor 0 $
hashByteArray h (P.sizeofByteArray ba) ba
instance Hashable Char where
hash h = go where
go c | n < 0x10000 = h `mix16` fromIntegral n
| otherwise = h `mix16` lo `mix16` hi
where n = ord c
m = n 0x10000
lo = fromIntegral $ (m `unsafeShiftR` 10) + 0xD800
hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
instance Hashable ThreadId where
hash h = \(ThreadId tid)->
hash h (fromIntegral $ getThreadId tid :: Word)
instance Hashable TypeRep where
hash h = hash h . typeRepInt32
typeRepInt32 :: TypeRep -> Int32
typeRepInt32 =
# if __GLASGOW_HASKELL__ >= 710
(\(Fingerprint i64 _) -> fromIntegral i64) . typeRepFingerprint
# else
\(TypeRep (Fingerprint i64 _) _ _) -> fromIntegral i64
# endif
instance Hashable (StableName a) where
hash h = \x-> hash h $ hashStableName x
instance Hashable Version where
hash h = \x-> hash h $ versionBranch x
instance Hashable Unique where
hash h = \x-> hash h $ hashUnique x
instance Hashable Bool where
hash h = hash h . \b-> if b then (1::Word8) else 0
instance Hashable Ordering where
hash h = flip mixConstructor h . fromIntegral . fromEnum
instance Hashable a => Hashable [a] where
hash h = mixConstructor 0 .
hashFoldl' h
instance Hashable a => Hashable (Maybe a) where
hash h Nothing = mixConstructor 0 h
hash h (Just a) = mixConstructor 1 $ hash h a
instance (Hashable a, Hashable b) => Hashable (Either a b) where
hash h = either (mx 0) (mx 1) where
mx n = mixConstructor n . hash h
instance Hashable () where
hash = const . mixConstructor 0
instance (Hashable a1, Hashable a2) => Hashable (a1, a2) where
hash h (a,b) = h `hash` a `hash` b
instance (Hashable a1, Hashable a2, Hashable a3) => Hashable (a1, a2, a3) where
hash h (a,b,c) = h `hash` a `hash` b `hash` c
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4) => Hashable (a1, a2, a3, a4) where
hash h (a,b,c,d) = h `hash` a `hash` b `hash` c `hash` d
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5) => Hashable (a1, a2, a3, a4, a5) where
hash h (a,b,c,d,e) = h `hash` a `hash` b `hash` c `hash` d `hash` e
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6) => Hashable (a1, a2, a3, a4, a5, a6) where
hash h (a,b,c,d,e,f) = h `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6, Hashable a7) => Hashable (a1, a2, a3, a4, a5, a6, a7) where
hash h (a,b,c,d,e,f,g) = h `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6, Hashable a7, Hashable a8) => Hashable (a1, a2, a3, a4, a5, a6, a7, a8) where
hash hsh (a,b,c,d,e,f,g,h) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e, Hashable f, Hashable g, Hashable h, Hashable i)=> Hashable (a, b, c, d, e, f, g, h, i) where
hash hsh (a, b, c, d, e, f, g, h, i) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h `hash` i
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e, Hashable f, Hashable g, Hashable h, Hashable i, Hashable j)=> Hashable (a, b, c, d, e, f, g, h, i, j) where
hash hsh (a, b, c, d, e, f, g, h, i, j) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h `hash` i `hash` j
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e, Hashable f, Hashable g, Hashable h, Hashable i, Hashable j, Hashable k)=> Hashable (a, b, c, d, e, f, g, h, i, j, k) where
hash hsh (a, b, c, d, e, f, g, h, i, j, k) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h `hash` i `hash` j `hash` k
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e, Hashable f, Hashable g, Hashable h, Hashable i, Hashable j, Hashable k, Hashable l)=> Hashable (a, b, c, d, e, f, g, h, i, j, k, l) where
hash hsh (a, b, c, d, e, f, g, h, i, j, k, l) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h `hash` i `hash` j `hash` k `hash` l
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e, Hashable f, Hashable g, Hashable h, Hashable i, Hashable j, Hashable k, Hashable l, Hashable m)=> Hashable (a, b, c, d, e, f, g, h, i, j, k, l, m) where
hash hsh (a, b, c, d, e, f, g, h, i, j, k, l, m) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h `hash` i `hash` j `hash` k `hash` l `hash` m
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e, Hashable f, Hashable g, Hashable h, Hashable i, Hashable j, Hashable k, Hashable l, Hashable m, Hashable n)=> Hashable (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
hash hsh (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h `hash` i `hash` j `hash` k `hash` l `hash` m `hash` n
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e, Hashable f, Hashable g, Hashable h, Hashable i, Hashable j, Hashable k, Hashable l, Hashable m, Hashable n, Hashable o)=> Hashable (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
hash hsh (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = hsh `hash` a `hash` b `hash` c `hash` d `hash` e `hash` f `hash` g `hash` h `hash` i `hash` j `hash` k `hash` l `hash` m `hash` n `hash` o
mixType :: forall a t. StableHashable a=> TypeHash t -> TypeHash (t a)
mixType (TypeHash t)= TypeHash (t `xor` (typeHashWord (typeHash :: TypeHash a)))
newtype TypeHash (a :: k) = TypeHash { typeHashWord :: Word64 }
deriving (Eq, Read, Show, Bits)
typeHashOf :: StableHashable a=> a -> TypeHash a
typeHashOf _ = typeHash
typeHashOfProxy :: StableHashable a=> proxy a -> TypeHash a
typeHashOfProxy _ = typeHash
class Hashable a=> StableHashable a where
typeHash :: TypeHash a
instance StableHashable Int where
# if WORD_SIZE_IN_BITS == 32
typeHash = TypeHash 14906715774445347101
# else
typeHash = TypeHash 13382803217769822997
# endif
instance StableHashable Word where
# if WORD_SIZE_IN_BITS == 32
typeHash = TypeHash 10996918434311873249
# else
typeHash = TypeHash 943142231655442729
# endif
instance StableHashable Integer where
typeHash = TypeHash 96690694942656444
#ifdef MIN_VERSION_integer_gmp
# if MIN_VERSION_integer_gmp(1,0,0)
instance StableHashable BigNat where
typeHash = TypeHash 2111364012200171327
# endif
#endif
#if MIN_VERSION_base(4,8,0)
instance StableHashable Natural where
typeHash = TypeHash 11915819290390802320
instance StableHashable Void where
typeHash = TypeHash 13639848524738715571
#endif
instance (Integral a, StableHashable a) => StableHashable (Ratio a) where
typeHash = mixType (TypeHash 330184177609460989)
instance StableHashable Float where
typeHash = TypeHash 4320606117681153984
instance StableHashable Double where
typeHash = TypeHash 8849395475307970354
instance StableHashable Int8 where
typeHash = TypeHash 17471749136236681265
instance StableHashable Int16 where
typeHash = TypeHash 14440046210595456836
instance StableHashable Int32 where
typeHash = TypeHash 13431688382274668720
instance StableHashable Int64 where
typeHash = TypeHash 14806970576519879451
instance StableHashable Word8 where
typeHash = TypeHash 6643259480050182665
instance StableHashable Word16 where
typeHash = TypeHash 3765569608911963661
instance StableHashable Word32 where
typeHash = TypeHash 6402686280864807547
instance StableHashable Word64 where
typeHash = TypeHash 14652873008202722152
instance StableHashable B.ByteString where
typeHash = TypeHash 171314019417081845
instance StableHashable BL.ByteString where
typeHash = TypeHash 10099361054646539018
#if MIN_VERSION_bytestring(0,10,4)
instance StableHashable BSh.ShortByteString where
typeHash = TypeHash 15680327781389053206
#endif
instance StableHashable T.Text where
typeHash = TypeHash 14746544807555826150
instance StableHashable TL.Text where
typeHash = TypeHash 10657741718622626930
instance StableHashable P.ByteArray where
typeHash = TypeHash 9976019413528454024
instance StableHashable Char where
typeHash = TypeHash 4949001641339870281
instance StableHashable Version where
typeHash = TypeHash 702645064027678737
instance StableHashable Bool where
typeHash = TypeHash 2172478990419421580
instance StableHashable Ordering where
typeHash = TypeHash 9293112338546135338
instance StableHashable a => StableHashable [a] where
typeHash = mixType (TypeHash 8959911929979074606)
instance StableHashable a => StableHashable (Maybe a) where
typeHash = mixType (TypeHash 17404804613103585388)
instance (StableHashable a, StableHashable b) => StableHashable (Either a b) where
typeHash = mixType (TypeHash 2275317158072284048)
instance StableHashable () where
typeHash = TypeHash 6095166973227743591
instance (StableHashable a, StableHashable b) => StableHashable (a, b) where
typeHash = mixType $ mixType (TypeHash 12071780118071628513)
instance (StableHashable a, StableHashable b, StableHashable c) => StableHashable (a, b, c) where
typeHash = mixType $ mixType $ (TypeHash 4618299809208311661)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d) => StableHashable (a, b, c, d) where
typeHash = mixType $mixType $mixType $ (TypeHash 2134528412514930125)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e) => StableHashable (a, b, c, d, e) where
typeHash = mixType $mixType $mixType $mixType $ (TypeHash 6145113094462899758)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f) => StableHashable (a, b, c, d, e, f) where
typeHash = mixType $mixType $mixType $mixType $mixType $ (TypeHash 44771254230381456)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g) => StableHashable (a, b, c, d, e, f, g) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 9917360176431723073)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h) => StableHashable (a, b, c, d, e, f, g, h) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 2303481052083416811)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h, StableHashable i)=> StableHashable (a, b, c, d, e, f, g, h, i) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 6307505215888440984)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h, StableHashable i, StableHashable j)=> StableHashable (a, b, c, d, e, f, g, h, i, j) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 16862409449834578942)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h, StableHashable i, StableHashable j, StableHashable k)=> StableHashable (a, b, c, d, e, f, g, h, i, j, k) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 12571504671032409264)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h, StableHashable i, StableHashable j, StableHashable k, StableHashable l)=> StableHashable (a, b, c, d, e, f, g, h, i, j, k, l) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 18057402240390888799)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h, StableHashable i, StableHashable j, StableHashable k, StableHashable l, StableHashable m)=> StableHashable (a, b, c, d, e, f, g, h, i, j, k, l, m) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 1509508551579382043)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h, StableHashable i, StableHashable j, StableHashable k, StableHashable l, StableHashable m, StableHashable n)=> StableHashable (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 17220521008040723494)
instance (StableHashable a, StableHashable b, StableHashable c, StableHashable d, StableHashable e, StableHashable f, StableHashable g, StableHashable h, StableHashable i, StableHashable j, StableHashable k, StableHashable l, StableHashable m, StableHashable n, StableHashable o)=> StableHashable (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
typeHash = mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $mixType $ (TypeHash 17803228377227705691)
hashByteString :: (HashState h)=> h -> B.ByteString -> h
hashByteString h = \(B.PS fp off lenBytes) ->
accursedUnutterablePerformIO $
withForeignPtr fp $ \base ->
let !bytesRem = lenBytes .&. 7
!ixOutOfBounds = off+lenBytes
!bytesIx = ixOutOfBoundsbytesRem
hash8ByteLoop !hAcc !ix
| ix == bytesIx = hashRemainingBytes hAcc bytesIx
| otherwise = assert (ix < bytesIx) $ do
w64Dirty <- peekByteOff base ix
let w64 = clean8ByteChunk w64Dirty
hash8ByteLoop (hAcc `mix64` w64) (ix + 8)
hashRemainingBytes !hAcc !ix
| ix == ixOutOfBounds = return hAcc
| otherwise = assert (ix < ixOutOfBounds) $ do
byt <- peekByteOff base ix
hashRemainingBytes (hAcc `mix8` byt) (ix+1)
in hash8ByteLoop h off
hashText :: (HashState h)=> h -> T.Text -> h
hashText h = \(T.Text (T.Array ba_) off lenWord16) ->
let ba = P.ByteArray ba_
!word16sRem = lenWord16 .&. 3
!word16sIx = off+lenWord16word16sRem
!ixFinal = off+lenWord161
hash4Word16sLoop !hAcc !ix
| ix == word16sIx = hashRemainingWord16s hAcc word16sIx
| otherwise = assert (ix < word16sIx) $
let w0 = P.indexByteArray ba ix
w1 = P.indexByteArray ba (ix+1)
w2 = P.indexByteArray ba (ix+2)
w3 = P.indexByteArray ba (ix+3)
in hash4Word16sLoop (hAcc `mix16` w0 `mix16` w1 `mix16` w2 `mix16` w3) (ix + 4)
hashRemainingWord16s !hAcc !ix
| ix > ixFinal = hAcc
| otherwise = assert (ix <= ixFinal) $
let w0 = P.indexByteArray ba ix
in hashRemainingWord16s (hAcc `mix16` w0) (ix+1)
in hash4Word16sLoop h off
hashByteArray :: (HashState h)=> h -> Int -> P.ByteArray -> h
hashByteArray h !lenBytes ba =
let !bytesRem = lenBytes .&. 7
!bytesIx = lenBytesbytesRem
!ixFinal = lenBytes1
!bytesIxWd = bytesIx `unsafeShiftR` 3
hash8ByteLoop !hAcc !ix
| ix == bytesIxWd = hashRemainingBytes hAcc bytesIx
| otherwise = assert (ix < bytesIxWd) $
let w64Dirty = P.indexByteArray ba ix
w64 = clean8ByteChunk w64Dirty
in hash8ByteLoop (hAcc `mix64` w64) (ix + 1)
hashRemainingBytes !hAcc !ix
| ix > ixFinal = hAcc
| otherwise = assert (ix <= ixFinal) $
let b0 = P.indexByteArray ba ix
in hashRemainingBytes (hAcc `mix8` b0) (ix+1)
in hash8ByteLoop h 0
clean8ByteChunk :: Word64 -> Word64
clean8ByteChunk w64Dirty
| littleEndian =
# if WORD_SIZE_IN_BITS == 64
byteSwap64 w64Dirty
# else
let (w32Dirty_0, w32Dirty_1) = words32 w64Dirty
w64_0 = (fromIntegral $ byteSwap32 w32Dirty_0) `unsafeShiftL` 32
w64_1 = fromIntegral $ byteSwap32 w32Dirty_1
in w64_0 .|. w64_1
# endif
| otherwise = w64Dirty
hashFoldl' :: (Hashable a, HashState h)=> h -> [a] -> h
hashFoldl' = foldl' (\h' a-> h' `hash` a)
hashLeftUnfolded :: (Hashable a, HashState h)=> h -> [a] -> h
hashLeftUnfolded = go
where go !h [] = h
go !h (a1:a2:a3:a4:a5:a6:as) = go (h `hash` a1 `hash` a2 `hash` a3 `hash` a4 `hash` a5 `hash` a6) as
go !h (a1:as) = go (h `hash` a1) as