-- |
-- Module      : Foundation.Hashing.FNV.FNV
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : good
--
-- Fowler Noll Vo Hash (1 and 1a / 32 / 64 bits versions)
-- <http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function>
--
{-# LANGUAGE MagicHash                  #-}
{-# LANGUAGE BangPatterns               #-}
module Foundation.Hashing.FNV
    (
    -- * types
      FNV1Hash32(..)
    , FNV1Hash64(..)
    , FNV1_32
    , FNV1a_32
    , FNV1_64
    , FNV1a_64
    ) where

import           Basement.Block (Block(..))
import           Basement.Compat.Base
import qualified Basement.UArray as A
import           Basement.Types.OffsetSize
import           Basement.PrimType
import           Basement.IntegralConv
import           Foundation.Numerical
import           Foundation.Hashing.Hasher
import           Data.Bits
import           GHC.ST

-- | FNV1(a) hash (32 bit variants)
newtype FNV1Hash32 = FNV1Hash32 Word32
    deriving (Int -> FNV1Hash32 -> ShowS
[FNV1Hash32] -> ShowS
FNV1Hash32 -> String
(Int -> FNV1Hash32 -> ShowS)
-> (FNV1Hash32 -> String)
-> ([FNV1Hash32] -> ShowS)
-> Show FNV1Hash32
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FNV1Hash32] -> ShowS
$cshowList :: [FNV1Hash32] -> ShowS
show :: FNV1Hash32 -> String
$cshow :: FNV1Hash32 -> String
showsPrec :: Int -> FNV1Hash32 -> ShowS
$cshowsPrec :: Int -> FNV1Hash32 -> ShowS
Show,FNV1Hash32 -> FNV1Hash32 -> Bool
(FNV1Hash32 -> FNV1Hash32 -> Bool)
-> (FNV1Hash32 -> FNV1Hash32 -> Bool) -> Eq FNV1Hash32
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FNV1Hash32 -> FNV1Hash32 -> Bool
$c/= :: FNV1Hash32 -> FNV1Hash32 -> Bool
== :: FNV1Hash32 -> FNV1Hash32 -> Bool
$c== :: FNV1Hash32 -> FNV1Hash32 -> Bool
Eq,Eq FNV1Hash32
Eq FNV1Hash32
-> (FNV1Hash32 -> FNV1Hash32 -> Ordering)
-> (FNV1Hash32 -> FNV1Hash32 -> Bool)
-> (FNV1Hash32 -> FNV1Hash32 -> Bool)
-> (FNV1Hash32 -> FNV1Hash32 -> Bool)
-> (FNV1Hash32 -> FNV1Hash32 -> Bool)
-> (FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32)
-> (FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32)
-> Ord FNV1Hash32
FNV1Hash32 -> FNV1Hash32 -> Bool
FNV1Hash32 -> FNV1Hash32 -> Ordering
FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
$cmin :: FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
max :: FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
$cmax :: FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
>= :: FNV1Hash32 -> FNV1Hash32 -> Bool
$c>= :: FNV1Hash32 -> FNV1Hash32 -> Bool
> :: FNV1Hash32 -> FNV1Hash32 -> Bool
$c> :: FNV1Hash32 -> FNV1Hash32 -> Bool
<= :: FNV1Hash32 -> FNV1Hash32 -> Bool
$c<= :: FNV1Hash32 -> FNV1Hash32 -> Bool
< :: FNV1Hash32 -> FNV1Hash32 -> Bool
$c< :: FNV1Hash32 -> FNV1Hash32 -> Bool
compare :: FNV1Hash32 -> FNV1Hash32 -> Ordering
$ccompare :: FNV1Hash32 -> FNV1Hash32 -> Ordering
$cp1Ord :: Eq FNV1Hash32
Ord)

-- | FNV1(a) hash (64 bit variants)
newtype FNV1Hash64 = FNV1Hash64 Word64
    deriving (Int -> FNV1Hash64 -> ShowS
[FNV1Hash64] -> ShowS
FNV1Hash64 -> String
(Int -> FNV1Hash64 -> ShowS)
-> (FNV1Hash64 -> String)
-> ([FNV1Hash64] -> ShowS)
-> Show FNV1Hash64
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FNV1Hash64] -> ShowS
$cshowList :: [FNV1Hash64] -> ShowS
show :: FNV1Hash64 -> String
$cshow :: FNV1Hash64 -> String
showsPrec :: Int -> FNV1Hash64 -> ShowS
$cshowsPrec :: Int -> FNV1Hash64 -> ShowS
Show,FNV1Hash64 -> FNV1Hash64 -> Bool
(FNV1Hash64 -> FNV1Hash64 -> Bool)
-> (FNV1Hash64 -> FNV1Hash64 -> Bool) -> Eq FNV1Hash64
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FNV1Hash64 -> FNV1Hash64 -> Bool
$c/= :: FNV1Hash64 -> FNV1Hash64 -> Bool
== :: FNV1Hash64 -> FNV1Hash64 -> Bool
$c== :: FNV1Hash64 -> FNV1Hash64 -> Bool
Eq,Eq FNV1Hash64
Eq FNV1Hash64
-> (FNV1Hash64 -> FNV1Hash64 -> Ordering)
-> (FNV1Hash64 -> FNV1Hash64 -> Bool)
-> (FNV1Hash64 -> FNV1Hash64 -> Bool)
-> (FNV1Hash64 -> FNV1Hash64 -> Bool)
-> (FNV1Hash64 -> FNV1Hash64 -> Bool)
-> (FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64)
-> (FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64)
-> Ord FNV1Hash64
FNV1Hash64 -> FNV1Hash64 -> Bool
FNV1Hash64 -> FNV1Hash64 -> Ordering
FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
$cmin :: FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
max :: FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
$cmax :: FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
>= :: FNV1Hash64 -> FNV1Hash64 -> Bool
$c>= :: FNV1Hash64 -> FNV1Hash64 -> Bool
> :: FNV1Hash64 -> FNV1Hash64 -> Bool
$c> :: FNV1Hash64 -> FNV1Hash64 -> Bool
<= :: FNV1Hash64 -> FNV1Hash64 -> Bool
$c<= :: FNV1Hash64 -> FNV1Hash64 -> Bool
< :: FNV1Hash64 -> FNV1Hash64 -> Bool
$c< :: FNV1Hash64 -> FNV1Hash64 -> Bool
compare :: FNV1Hash64 -> FNV1Hash64 -> Ordering
$ccompare :: FNV1Hash64 -> FNV1Hash64 -> Ordering
$cp1Ord :: Eq FNV1Hash64
Ord)

xor32 :: Word -> Word8 -> Word
xor32 :: Word -> Word8 -> Word
xor32 !Word
a !Word8
b = Word
a Word -> Word -> Word
forall a. Bits a => a -> a -> a
`xor` Word8 -> Word
forall a b. IntegralUpsize a b => a -> b
integralUpsize Word8
b
{-# INLINE xor32 #-}

xor64 :: Word64 -> Word8 -> Word64
xor64 :: Word64 -> Word8 -> Word64
xor64 !Word64
a !Word8
b = Word64
a Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`xor` Word8 -> Word64
forall a b. IntegralUpsize a b => a -> b
integralUpsize Word8
b
{-# INLINE xor64 #-}

-- | FNV1 32 bit state
newtype FNV1_32 = FNV1_32 Word

-- | FNV1 64 bit state
newtype FNV1_64 = FNV1_64 Word64

-- | FNV1a 32 bit state
newtype FNV1a_32 = FNV1a_32 Word

-- | FNV1a 64 bit state
newtype FNV1a_64 = FNV1a_64 Word64

fnv1_32_Mix8 :: Word8 -> FNV1_32 -> FNV1_32
fnv1_32_Mix8 :: Word8 -> FNV1_32 -> FNV1_32
fnv1_32_Mix8 !Word8
w (FNV1_32 Word
acc) = Word -> FNV1_32
FNV1_32 (Word
0x01000193 Word -> Word -> Word
forall a. Multiplicative a => a -> a -> a
* Word
acc Word -> Word8 -> Word
`xor32` Word8
w)
{-# INLINE fnv1_32_Mix8 #-}

fnv1a_32_Mix8 :: Word8 -> FNV1a_32 -> FNV1a_32
fnv1a_32_Mix8 :: Word8 -> FNV1a_32 -> FNV1a_32
fnv1a_32_Mix8 !Word8
w (FNV1a_32 Word
acc) = Word -> FNV1a_32
FNV1a_32 (Word
0x01000193 Word -> Word -> Word
forall a. Multiplicative a => a -> a -> a
* (Word
acc Word -> Word8 -> Word
`xor32` Word8
w))
{-# INLINE fnv1a_32_Mix8 #-}

fnv1_64_Mix8 :: Word8 -> FNV1_64 -> FNV1_64
fnv1_64_Mix8 :: Word8 -> FNV1_64 -> FNV1_64
fnv1_64_Mix8 !Word8
w (FNV1_64 Word64
acc) = Word64 -> FNV1_64
FNV1_64 (Word64
0x100000001b3 Word64 -> Word64 -> Word64
forall a. Multiplicative a => a -> a -> a
* Word64
acc Word64 -> Word8 -> Word64
`xor64` Word8
w)
{-# INLINE fnv1_64_Mix8 #-}

fnv1a_64_Mix8 :: Word8 -> FNV1a_64 -> FNV1a_64
fnv1a_64_Mix8 :: Word8 -> FNV1a_64 -> FNV1a_64
fnv1a_64_Mix8 !Word8
w (FNV1a_64 Word64
acc) = Word64 -> FNV1a_64
FNV1a_64 (Word64
0x100000001b3 Word64 -> Word64 -> Word64
forall a. Multiplicative a => a -> a -> a
* (Word64
acc Word64 -> Word8 -> Word64
`xor64` Word8
w))
{-# INLINE fnv1a_64_Mix8 #-}

instance Hasher FNV1_32 where
    type HashResult FNV1_32 = FNV1Hash32
    type HashInitParam FNV1_32 = Word
    hashNew :: FNV1_32
hashNew = Word -> FNV1_32
FNV1_32 Word
0
    hashNewParam :: HashInitParam FNV1_32 -> FNV1_32
hashNewParam HashInitParam FNV1_32
w = Word -> FNV1_32
FNV1_32 Word
HashInitParam FNV1_32
w
    hashEnd :: FNV1_32 -> HashResult FNV1_32
hashEnd (FNV1_32 Word
w) = Word32 -> FNV1Hash32
FNV1Hash32 (Word -> Word32
forall a b. IntegralDownsize a b => a -> b
integralDownsize Word
w)
    hashMix8 :: Word8 -> FNV1_32 -> FNV1_32
hashMix8 = Word8 -> FNV1_32 -> FNV1_32
fnv1_32_Mix8
    hashMixBytes :: UArray e -> FNV1_32 -> FNV1_32
hashMixBytes = UArray e -> FNV1_32 -> FNV1_32
forall e. PrimType e => UArray e -> FNV1_32 -> FNV1_32
fnv1_32_mixBa

instance Hasher FNV1a_32 where
    type HashResult FNV1a_32 = FNV1Hash32
    type HashInitParam FNV1a_32 = Word
    hashNew :: FNV1a_32
hashNew = Word -> FNV1a_32
FNV1a_32 Word
0
    hashNewParam :: HashInitParam FNV1a_32 -> FNV1a_32
hashNewParam HashInitParam FNV1a_32
w = Word -> FNV1a_32
FNV1a_32 Word
HashInitParam FNV1a_32
w
    hashEnd :: FNV1a_32 -> HashResult FNV1a_32
hashEnd (FNV1a_32 Word
w) = Word32 -> FNV1Hash32
FNV1Hash32 (Word -> Word32
forall a b. IntegralDownsize a b => a -> b
integralDownsize Word
w)
    hashMix8 :: Word8 -> FNV1a_32 -> FNV1a_32
hashMix8 = Word8 -> FNV1a_32 -> FNV1a_32
fnv1a_32_Mix8
    hashMixBytes :: UArray e -> FNV1a_32 -> FNV1a_32
hashMixBytes = UArray e -> FNV1a_32 -> FNV1a_32
forall e. PrimType e => UArray e -> FNV1a_32 -> FNV1a_32
fnv1a_32_mixBa

instance Hasher FNV1_64 where
    type HashResult FNV1_64 = FNV1Hash64
    type HashInitParam FNV1_64 = Word64
    hashNew :: FNV1_64
hashNew = Word64 -> FNV1_64
FNV1_64 Word64
0xcbf29ce484222325
    hashNewParam :: HashInitParam FNV1_64 -> FNV1_64
hashNewParam HashInitParam FNV1_64
w = Word64 -> FNV1_64
FNV1_64 Word64
HashInitParam FNV1_64
w
    hashEnd :: FNV1_64 -> HashResult FNV1_64
hashEnd (FNV1_64 Word64
w) = Word64 -> FNV1Hash64
FNV1Hash64 Word64
w
    hashMix8 :: Word8 -> FNV1_64 -> FNV1_64
hashMix8 = Word8 -> FNV1_64 -> FNV1_64
fnv1_64_Mix8
    hashMixBytes :: UArray e -> FNV1_64 -> FNV1_64
hashMixBytes = UArray e -> FNV1_64 -> FNV1_64
forall e. PrimType e => UArray e -> FNV1_64 -> FNV1_64
fnv1_64_mixBa

instance Hasher FNV1a_64 where
    type HashResult FNV1a_64 = FNV1Hash64
    type HashInitParam FNV1a_64 = Word64
    hashNew :: FNV1a_64
hashNew = Word64 -> FNV1a_64
FNV1a_64 Word64
0xcbf29ce484222325
    hashNewParam :: HashInitParam FNV1a_64 -> FNV1a_64
hashNewParam HashInitParam FNV1a_64
w = Word64 -> FNV1a_64
FNV1a_64 Word64
HashInitParam FNV1a_64
w
    hashEnd :: FNV1a_64 -> HashResult FNV1a_64
hashEnd (FNV1a_64 Word64
w) = Word64 -> FNV1Hash64
FNV1Hash64 Word64
w
    hashMix8 :: Word8 -> FNV1a_64 -> FNV1a_64
hashMix8 = Word8 -> FNV1a_64 -> FNV1a_64
fnv1a_64_Mix8
    hashMixBytes :: UArray e -> FNV1a_64 -> FNV1a_64
hashMixBytes = UArray e -> FNV1a_64 -> FNV1a_64
forall e. PrimType e => UArray e -> FNV1a_64 -> FNV1a_64
fnv1a_64_mixBa

-- | compute FNV1 (32 bit variant) of a raw piece of memory
fnv1_32_mixBa :: PrimType a => A.UArray a -> FNV1_32 -> FNV1_32
fnv1_32_mixBa :: UArray a -> FNV1_32 -> FNV1_32
fnv1_32_mixBa UArray a
baA !FNV1_32
initialState = (Block Word8 -> Offset Word8 -> FNV1_32)
-> (Ptr Word8 -> Offset Word8 -> ST Any FNV1_32)
-> UArray Word8
-> FNV1_32
forall ty a s.
(Block ty -> Offset ty -> a)
-> (Ptr ty -> Offset ty -> ST s a) -> UArray ty -> a
A.unsafeDewrap Block Word8 -> Offset Word8 -> FNV1_32
goVec Ptr Word8 -> Offset Word8 -> ST Any FNV1_32
forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1_32
goAddr UArray Word8
ba
  where
    ba :: A.UArray Word8
    ba :: UArray Word8
ba = UArray a -> UArray Word8
forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast UArray a
baA

    goVec :: Block Word8 -> Offset Word8 -> FNV1_32
    goVec :: Block Word8 -> Offset Word8 -> FNV1_32
goVec (Block !ByteArray#
ma) !Offset Word8
start = Offset Word8 -> FNV1_32 -> FNV1_32
loop Offset Word8
start FNV1_32
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1_32 -> FNV1_32
loop !Offset Word8
idx !FNV1_32
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1_32
acc
            | Bool
otherwise  = Offset Word8 -> FNV1_32 -> FNV1_32
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1_32 -> FNV1_32
forall st. Hasher st => Word8 -> st -> st
hashMix8 (ByteArray# -> Offset Word8 -> Word8
forall ty. PrimType ty => ByteArray# -> Offset ty -> ty
primBaIndex ByteArray#
ma Offset Word8
idx) FNV1_32
acc)
    {-# INLINE goVec #-}

    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1_32
    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1_32
goAddr (Ptr Addr#
ptr) !Offset Word8
start = FNV1_32 -> ST s FNV1_32
forall (m :: * -> *) a. Monad m => a -> m a
return (FNV1_32 -> ST s FNV1_32) -> FNV1_32 -> ST s FNV1_32
forall a b. (a -> b) -> a -> b
$ Offset Word8 -> FNV1_32 -> FNV1_32
loop Offset Word8
start FNV1_32
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1_32 -> FNV1_32
loop !Offset Word8
idx !FNV1_32
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1_32
acc
            | Bool
otherwise  = Offset Word8 -> FNV1_32 -> FNV1_32
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1_32 -> FNV1_32
forall st. Hasher st => Word8 -> st -> st
hashMix8 (Addr# -> Offset Word8 -> Word8
forall ty. PrimType ty => Addr# -> Offset ty -> ty
primAddrIndex Addr#
ptr Offset Word8
idx) FNV1_32
acc)
    {-# INLINE goAddr #-}

-- | compute FNV1a (32 bit variant) of a raw piece of memory
fnv1a_32_mixBa :: PrimType a => A.UArray a -> FNV1a_32 -> FNV1a_32
fnv1a_32_mixBa :: UArray a -> FNV1a_32 -> FNV1a_32
fnv1a_32_mixBa UArray a
baA !FNV1a_32
initialState  = (Block Word8 -> Offset Word8 -> FNV1a_32)
-> (Ptr Word8 -> Offset Word8 -> ST Any FNV1a_32)
-> UArray Word8
-> FNV1a_32
forall ty a s.
(Block ty -> Offset ty -> a)
-> (Ptr ty -> Offset ty -> ST s a) -> UArray ty -> a
A.unsafeDewrap Block Word8 -> Offset Word8 -> FNV1a_32
goVec Ptr Word8 -> Offset Word8 -> ST Any FNV1a_32
forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1a_32
goAddr UArray Word8
ba
  where
    ba :: A.UArray Word8
    ba :: UArray Word8
ba = UArray a -> UArray Word8
forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast UArray a
baA

    goVec :: Block Word8 -> Offset Word8 -> FNV1a_32
    goVec :: Block Word8 -> Offset Word8 -> FNV1a_32
goVec (Block !ByteArray#
ma) !Offset Word8
start = Offset Word8 -> FNV1a_32 -> FNV1a_32
loop Offset Word8
start FNV1a_32
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1a_32 -> FNV1a_32
loop !Offset Word8
idx !FNV1a_32
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1a_32
acc
            | Bool
otherwise  = Offset Word8 -> FNV1a_32 -> FNV1a_32
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1a_32 -> FNV1a_32
forall st. Hasher st => Word8 -> st -> st
hashMix8 (ByteArray# -> Offset Word8 -> Word8
forall ty. PrimType ty => ByteArray# -> Offset ty -> ty
primBaIndex ByteArray#
ma Offset Word8
idx) FNV1a_32
acc)
    {-# INLINE goVec #-}

    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1a_32
    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1a_32
goAddr (Ptr Addr#
ptr) !Offset Word8
start = FNV1a_32 -> ST s FNV1a_32
forall (m :: * -> *) a. Monad m => a -> m a
return (FNV1a_32 -> ST s FNV1a_32) -> FNV1a_32 -> ST s FNV1a_32
forall a b. (a -> b) -> a -> b
$ Offset Word8 -> FNV1a_32 -> FNV1a_32
loop Offset Word8
start FNV1a_32
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1a_32 -> FNV1a_32
loop !Offset Word8
idx !FNV1a_32
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1a_32
acc
            | Bool
otherwise  = Offset Word8 -> FNV1a_32 -> FNV1a_32
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1a_32 -> FNV1a_32
forall st. Hasher st => Word8 -> st -> st
hashMix8 (Addr# -> Offset Word8 -> Word8
forall ty. PrimType ty => Addr# -> Offset ty -> ty
primAddrIndex Addr#
ptr Offset Word8
idx) FNV1a_32
acc)
    {-# INLINE goAddr #-}

-- | compute FNV1 (64 bit variant) of a raw piece of memory
fnv1_64_mixBa :: PrimType a => A.UArray a -> FNV1_64 -> FNV1_64
fnv1_64_mixBa :: UArray a -> FNV1_64 -> FNV1_64
fnv1_64_mixBa UArray a
baA !FNV1_64
initialState = (Block Word8 -> Offset Word8 -> FNV1_64)
-> (Ptr Word8 -> Offset Word8 -> ST Any FNV1_64)
-> UArray Word8
-> FNV1_64
forall ty a s.
(Block ty -> Offset ty -> a)
-> (Ptr ty -> Offset ty -> ST s a) -> UArray ty -> a
A.unsafeDewrap Block Word8 -> Offset Word8 -> FNV1_64
goVec Ptr Word8 -> Offset Word8 -> ST Any FNV1_64
forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1_64
goAddr UArray Word8
ba
  where
    ba :: A.UArray Word8
    ba :: UArray Word8
ba = UArray a -> UArray Word8
forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast UArray a
baA

    goVec :: Block Word8 -> Offset Word8 -> FNV1_64
    goVec :: Block Word8 -> Offset Word8 -> FNV1_64
goVec (Block !ByteArray#
ma) !Offset Word8
start = Offset Word8 -> FNV1_64 -> FNV1_64
loop Offset Word8
start FNV1_64
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1_64 -> FNV1_64
loop !Offset Word8
idx !FNV1_64
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1_64
acc
            | Bool
otherwise  = Offset Word8 -> FNV1_64 -> FNV1_64
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1_64 -> FNV1_64
forall st. Hasher st => Word8 -> st -> st
hashMix8 (ByteArray# -> Offset Word8 -> Word8
forall ty. PrimType ty => ByteArray# -> Offset ty -> ty
primBaIndex ByteArray#
ma Offset Word8
idx) FNV1_64
acc)
    {-# INLINE goVec #-}

    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1_64
    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1_64
goAddr (Ptr Addr#
ptr) !Offset Word8
start = FNV1_64 -> ST s FNV1_64
forall (m :: * -> *) a. Monad m => a -> m a
return (FNV1_64 -> ST s FNV1_64) -> FNV1_64 -> ST s FNV1_64
forall a b. (a -> b) -> a -> b
$ Offset Word8 -> FNV1_64 -> FNV1_64
loop Offset Word8
start FNV1_64
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1_64 -> FNV1_64
loop !Offset Word8
idx !FNV1_64
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1_64
acc
            | Bool
otherwise  = Offset Word8 -> FNV1_64 -> FNV1_64
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1_64 -> FNV1_64
forall st. Hasher st => Word8 -> st -> st
hashMix8 (Addr# -> Offset Word8 -> Word8
forall ty. PrimType ty => Addr# -> Offset ty -> ty
primAddrIndex Addr#
ptr Offset Word8
idx) FNV1_64
acc)
    {-# INLINE goAddr #-}

-- | compute FNV1a (64 bit variant) of a raw piece of memory
fnv1a_64_mixBa :: PrimType a => A.UArray a -> FNV1a_64 -> FNV1a_64
fnv1a_64_mixBa :: UArray a -> FNV1a_64 -> FNV1a_64
fnv1a_64_mixBa UArray a
baA !FNV1a_64
initialState = (Block Word8 -> Offset Word8 -> FNV1a_64)
-> (Ptr Word8 -> Offset Word8 -> ST Any FNV1a_64)
-> UArray Word8
-> FNV1a_64
forall ty a s.
(Block ty -> Offset ty -> a)
-> (Ptr ty -> Offset ty -> ST s a) -> UArray ty -> a
A.unsafeDewrap Block Word8 -> Offset Word8 -> FNV1a_64
goVec Ptr Word8 -> Offset Word8 -> ST Any FNV1a_64
forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1a_64
goAddr UArray Word8
ba
  where
    ba :: A.UArray Word8
    ba :: UArray Word8
ba = UArray a -> UArray Word8
forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast UArray a
baA

    goVec :: Block Word8 -> Offset Word8 -> FNV1a_64
    goVec :: Block Word8 -> Offset Word8 -> FNV1a_64
goVec (Block !ByteArray#
ma) !Offset Word8
start = Offset Word8 -> FNV1a_64 -> FNV1a_64
loop Offset Word8
start FNV1a_64
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1a_64 -> FNV1a_64
loop !Offset Word8
idx !FNV1a_64
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1a_64
acc
            | Bool
otherwise  = Offset Word8 -> FNV1a_64 -> FNV1a_64
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1a_64 -> FNV1a_64
forall st. Hasher st => Word8 -> st -> st
hashMix8 (ByteArray# -> Offset Word8 -> Word8
forall ty. PrimType ty => ByteArray# -> Offset ty -> ty
primBaIndex ByteArray#
ma Offset Word8
idx) FNV1a_64
acc)
    {-# INLINE goVec #-}

    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1a_64
    goAddr :: Ptr Word8 -> Offset Word8 -> ST s FNV1a_64
goAddr (Ptr Addr#
ptr) !Offset Word8
start = FNV1a_64 -> ST s FNV1a_64
forall (m :: * -> *) a. Monad m => a -> m a
return (FNV1a_64 -> ST s FNV1a_64) -> FNV1a_64 -> ST s FNV1a_64
forall a b. (a -> b) -> a -> b
$ Offset Word8 -> FNV1a_64 -> FNV1a_64
loop Offset Word8
start FNV1a_64
initialState
      where
        !len :: Offset Word8
len = Offset Word8
start Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` UArray Word8 -> CountOf Word8
forall ty. UArray ty -> CountOf ty
A.length UArray Word8
ba
        loop :: Offset Word8 -> FNV1a_64 -> FNV1a_64
loop !Offset Word8
idx !FNV1a_64
acc
            | Offset Word8
idx Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word8
len = FNV1a_64
acc
            | Bool
otherwise  = Offset Word8 -> FNV1a_64 -> FNV1a_64
loop (Offset Word8
idx Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word8 -> FNV1a_64 -> FNV1a_64
forall st. Hasher st => Word8 -> st -> st
hashMix8 (Addr# -> Offset Word8 -> Word8
forall ty. PrimType ty => Addr# -> Offset ty -> ty
primAddrIndex Addr#
ptr Offset Word8
idx) FNV1a_64
acc)
    {-# INLINE goAddr #-}