{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_GHC -Wunused-imports #-}
module Agda.Utils.Hash where
import Data.ByteString as B
import Data.Word
import Data.Hash qualified as H
import Data.List qualified as L
import Data.Digest.Murmur64
import Data.Text.Encoding qualified as T
import Data.Text.Lazy (Text)
import Data.Text.Lazy qualified as T
import GHC.Exts
import Agda.Utils.FileName
import Agda.Utils.IO.UTF8 (readTextFile)
#include "MachDeps.h"
type Hash = Word64
hashSize :: Int
hashSize :: Int
hashSize = SIZEOF_WORD64
hashByteString :: ByteString -> Hash
hashByteString :: ByteString -> Hash
hashByteString = Hash -> Hash
H.asWord64 (Hash -> Hash) -> (ByteString -> Hash) -> ByteString -> Hash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Hash -> Word8 -> Hash) -> Hash -> ByteString -> Hash
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
B.foldl' (\Hash
h Word8
b -> Hash -> Hash -> Hash
H.combine Hash
h (Word8 -> Hash
H.hashWord8 Word8
b)) (Word8 -> Hash
H.hashWord8 Word8
0)
hashTextFile :: AbsolutePath -> IO Hash
hashTextFile :: AbsolutePath -> IO Hash
hashTextFile AbsolutePath
file = Text -> Hash
hashText (Text -> Hash) -> IO Text -> IO Hash
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Text
readTextFile (AbsolutePath -> String
filePath AbsolutePath
file)
hashText :: Text -> Hash
hashText :: Text -> Hash
hashText = ByteString -> Hash
hashByteString (ByteString -> Hash) -> (Text -> ByteString) -> Text -> Hash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
T.encodeUtf8 (Text -> ByteString) -> (Text -> Text) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.toStrict
combineHashes :: [Hash] -> Hash
combineHashes :: [Hash] -> Hash
combineHashes [Hash]
hs = Hash -> Hash
H.asWord64 (Hash -> Hash) -> Hash -> Hash
forall a b. (a -> b) -> a -> b
$ (Hash -> Hash -> Hash) -> Hash -> [Hash] -> Hash
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.foldl' Hash -> Hash -> Hash
H.combine (Word8 -> Hash
H.hashWord8 Word8
0) ([Hash] -> Hash) -> [Hash] -> Hash
forall a b. (a -> b) -> a -> b
$ (Hash -> Hash) -> [Hash] -> [Hash]
forall a b. (a -> b) -> [a] -> [b]
L.map Hash -> Hash
forall a. Hashable a => a -> Hash
H.hash [Hash]
hs
hashString :: String -> Word64
hashString :: String -> Hash
hashString = Hash64 -> Hash
asWord64 (Hash64 -> Hash) -> (String -> Hash64) -> String -> Hash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Hash64
forall a. Hashable64 a => a -> Hash64
hash64
factor :: Word
#if WORD_SIZE_IN_BITS == 64
factor :: Word
factor = Word
11400714819323198549
#else
factor = 2654435741
#endif
{-# INLINE combineWord #-}
combineWord :: Word -> Word -> Word
combineWord :: Word -> Word -> Word
combineWord Word
x Word
y = Word -> Word -> Word
foldedMul (Word -> Word -> Word
xor Word
x Word
y) Word
factor where
xor :: Word -> Word -> Word
xor (W# Word#
x) (W# Word#
y) = Word# -> Word
W# (Word# -> Word# -> Word#
xor# Word#
x Word#
y)
foldedMul :: Word -> Word -> Word
foldedMul (W# Word#
x) (W# Word#
y) = case Word# -> Word# -> (# Word#, Word# #)
timesWord2# Word#
x Word#
y of (# Word#
hi, Word#
lo #) -> Word# -> Word
W# (Word# -> Word# -> Word#
xor# Word#
hi Word#
lo)
{-# INLINE combineInt #-}
combineInt :: Int -> Int -> Int
combineInt :: Int -> Int -> Int
combineInt Int
x Int
y = Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Word -> Word
combineWord (Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
x) (Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
y))