    -- |
    -- 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
    $cshowsPrec :: Int -> FNV1Hash32 -> ShowS
    showsPrec :: Int -> FNV1Hash32 -> ShowS
    $cshow :: FNV1Hash32 -> String
    show :: FNV1Hash32 -> String
    $cshowList :: [FNV1Hash32] -> ShowS
    showList :: [FNV1Hash32] -> ShowS
    Show,FNV1Hash32 -> FNV1Hash32 -> Bool
    (FNV1Hash32 -> FNV1Hash32 -> Bool)
    -> (FNV1Hash32 -> FNV1Hash32 -> Bool) -> Eq FNV1Hash32
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FNV1Hash32 -> FNV1Hash32 -> Bool
    == :: FNV1Hash32 -> FNV1Hash32 -> Bool
    $c/= :: FNV1Hash32 -> FNV1Hash32 -> Bool
    /= :: 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
    $ccompare :: FNV1Hash32 -> FNV1Hash32 -> Ordering
    compare :: FNV1Hash32 -> FNV1Hash32 -> Ordering
    $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
    >= :: FNV1Hash32 -> FNV1Hash32 -> Bool
    $cmax :: FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
    max :: FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
    $cmin :: FNV1Hash32 -> FNV1Hash32 -> FNV1Hash32
    min :: FNV1Hash32 -> FNV1Hash32 -> 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
    $cshowsPrec :: Int -> FNV1Hash64 -> ShowS
    showsPrec :: Int -> FNV1Hash64 -> ShowS
    $cshow :: FNV1Hash64 -> String
    show :: FNV1Hash64 -> String
    $cshowList :: [FNV1Hash64] -> ShowS
    showList :: [FNV1Hash64] -> ShowS
    Show,FNV1Hash64 -> FNV1Hash64 -> Bool
    (FNV1Hash64 -> FNV1Hash64 -> Bool)
    -> (FNV1Hash64 -> FNV1Hash64 -> Bool) -> Eq FNV1Hash64
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FNV1Hash64 -> FNV1Hash64 -> Bool
    == :: FNV1Hash64 -> FNV1Hash64 -> Bool
    $c/= :: FNV1Hash64 -> FNV1Hash64 -> Bool
    /= :: 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
    $ccompare :: FNV1Hash64 -> FNV1Hash64 -> Ordering
    compare :: FNV1Hash64 -> FNV1Hash64 -> Ordering
    $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
    >= :: FNV1Hash64 -> FNV1Hash64 -> Bool
    $cmax :: FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
    max :: FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
    $cmin :: FNV1Hash64 -> FNV1Hash64 -> FNV1Hash64
    min :: FNV1Hash64 -> FNV1Hash64 -> 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 :: forall e. PrimType e => 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 :: forall e. PrimType e => 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 :: forall e. PrimType e => 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 :: forall e. PrimType e => 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 :: forall e. PrimType e => UArray e -> FNV1_32 -> FNV1_32
    fnv1_32_mixBa UArray a
    baA !FNV1_32
    initialState = (Block Word8 -> Offset Word8 -> FNV1_32)
    -> (Ptr Word8 -> Offset Word8 -> ST (ZonkAny 3) 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 (ZonkAny 3) 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 :: forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1_32
    goAddr (Ptr Addr#
    ptr) !Offset Word8
    start = FNV1_32 -> ST s FNV1_32
    forall a. a -> ST s a
    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 :: forall e. PrimType e => UArray e -> FNV1a_32 -> FNV1a_32
    fnv1a_32_mixBa UArray a
    baA !FNV1a_32
    initialState  = (Block Word8 -> Offset Word8 -> FNV1a_32)
    -> (Ptr Word8 -> Offset Word8 -> ST (ZonkAny 2) 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 (ZonkAny 2) 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 :: forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1a_32
    goAddr (Ptr Addr#
    ptr) !Offset Word8
    start = FNV1a_32 -> ST s FNV1a_32
    forall a. a -> ST s a
    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 :: forall e. PrimType e => UArray e -> FNV1_64 -> FNV1_64
    fnv1_64_mixBa UArray a
    baA !FNV1_64
    initialState = (Block Word8 -> Offset Word8 -> FNV1_64)
    -> (Ptr Word8 -> Offset Word8 -> ST (ZonkAny 1) 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 (ZonkAny 1) 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 :: forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1_64
    goAddr (Ptr Addr#
    ptr) !Offset Word8
    start = FNV1_64 -> ST s FNV1_64
    forall a. a -> ST s a
    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 :: forall e. PrimType e => UArray e -> FNV1a_64 -> FNV1a_64
    fnv1a_64_mixBa UArray a
    baA !FNV1a_64
    initialState = (Block Word8 -> Offset Word8 -> FNV1a_64)
    -> (Ptr Word8 -> Offset Word8 -> ST (ZonkAny 0) 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 (ZonkAny 0) 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 :: forall s. Ptr Word8 -> Offset Word8 -> ST s FNV1a_64
    goAddr (Ptr Addr#
    ptr) !Offset Word8
    start = FNV1a_64 -> ST s FNV1a_64
    forall a. a -> ST s a
    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 #-}