mono-hash (empty) → 0.1.0.0
raw patch · 15 files changed
+2881/−0 lines, 15 filesdep +basedep +bytestringdep +criterion
Dependencies added: base, bytestring, criterion, deepseq, mono-hash, mono-traversable, tasty, tasty-hunit, text, wide-word
Files
- CHANGELOG.md +7/−0
- LICENSE +29/−0
- README.md +160/−0
- bench/Main.hs +92/−0
- mono-hash.cabal +102/−0
- src/Data/Hash/Mono/FNV.hs +92/−0
- src/Data/Hash/Mono/HalfSipHash.hs +170/−0
- src/Data/Hash/Mono/Internal.hs +43/−0
- src/Data/Hash/Mono/Internal/ByteFoldable.hs +163/−0
- src/Data/Hash/Mono/SipHash.hs +171/−0
- test/Main.hs +362/−0
- test/Test/Data/ByteFoldable.hs +48/−0
- test/Test/Data/FNV.hs +1078/−0
- test/Test/Data/HalfSipHash.hs +182/−0
- test/Test/Data/SipHash.hs +182/−0
+ CHANGELOG.md view
@@ -0,0 +1,7 @@+# Revision history for mono-hash++## 0.1.0.0 -- 2026-10-25++* First release.+* FNV-1 and FNV-1a for monomorphic containers.+* SipHash-c-d and HalfSipHash-c-d for monomorphic containers.
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2025, Philipp Hagenlocher+++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of the copyright holder nor the names of its+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,160 @@+# mono-hash++[](https://hackage.haskell.org/package/mono-hash)+[](https://github.com/phagenlocher/mono-hash/actions/workflows/haskell-ci.yml)++Hashing for monomorphic containers: FNV-1/FNV-1a, SipHash, and HalfSipHash for+any [`MonoFoldable`](https://hackage.haskell.org/package/mono-traversable/docs/Data-MonoTraversable.html#t:MonoFoldable),+including `ByteString`, lazy `ByteString`, `Text`, `String`, and lists of+fixed-width words.++## Motivation++This library hashes data in monomorphic containers irrespective of their+structure. Because only the concatenated element bytes matter, changing the+container while keeping the same bytes leaves the hash unchanged. Below, the+`ByteString` and `Vector Word64` hold exactly the same bytes; each formatted+line of the `ByteString` is one `Word64` in the vector:++```haskell+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE TypeApplications #-}++import qualified Data.ByteString as BS+import qualified Data.Vector as V+import Data.Hash.Mono.SipHash (sipHash)+import Data.Tree (Tree (..))+import Data.WideWord.Word128 (Word128)+import Data.Word (Word32, Word64)++key :: Word128+key = 0x000102030405060708090a0b0c0d0e0f++bytes :: BS.ByteString+bytes =+ BS.pack+ [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77+ , 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff+ , 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef+ ]++vector :: V.Vector Word64+vector =+ V.fromList+ [ 0x00_11_22_33_44_55_66_77+ , 0x88_99_aa_bb_cc_dd_ee_ff+ , 0x01_23_45_67_89_ab_cd_ef+ ]++sipHash @Word64 2 4 key bytes+-- 0x6d003ad777121d05++sipHash @Word64 2 4 key vector+-- 0x6d003ad777121d05+```++The same works for any `MonoFoldable`. `Data.Tree.Tree` from `containers`+already has a `MonoFoldable` instance in `mono-traversable`, and it folds in+pre-order:++```haskell+-- Pre-order traversal: the same 24 bytes as six Word32s.+tree :: Tree Word32+tree =+ Node+ 0x00_11_22_33+ [ Node 0x44_55_66_77 []+ , Node 0x88_99_aa_bb []+ , Node 0xcc_dd_ee_ff+ [ Node 0x01_23_45_67 []+ , Node 0x89_ab_cd_ef []+ ]+ ]++sipHash @Word64 2 4 key tree+-- 0x6d003ad777121d05+```++## Usage++```haskell+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++import Data.Hash.Mono.FNV (fnv1a)+import Data.Hash.Mono.HalfSipHash (halfSipHash)+import Data.Hash.Mono.SipHash (sipHash)+import Data.Text (Text)+import Data.WideWord.Word128 (Word128)+import Data.Word (Word32, Word64)++-- FNV-1a with a 64-bit result+fnv1a @Word64 ("hello" :: Text)++-- SipHash-2-4 with a 128-bit key and a 64-bit result+sipHash @Word64 2 4 (0x000102030405060708090a0b0c0d0e0f :: Word128) ("hello" :: Text)++-- HalfSipHash-2-4 with a 64-bit key and a 32-bit result+halfSipHash @Word32 2 4 (0x0001020304050607 :: Word64) ("hello" :: Text)+```++The result type is selected with a type application (or type inference of course):++| Function | Result type |+| -------------- | ---------------------------------------- |+| `fnv1`/`fnv1a` | `Word32`, `Word64`, `Word128`, `Word256` |+| `sipHash` | `Word64`, `Word128` |+| `halfSipHash` | `Word32`, `Word64` |++## Encoding and byte order++Hashing is defined over the concatenation of the elements' byte encodings.+The encoding is not type-tagged, so `[0x01, 0x02 :: Word8]` and+`[0x0102 :: Word16]` hash the same bytes.++`Word8` and `Int8` contribute one byte. Wider integers contribute+their bit pattern most significant byte first; signed integers use two's+complement. `Char` contributes UTF-8; a lone surrogate, which `String` can+contain but UTF-8 cannot represent, uses the 3-byte+[WTF-8](https://wtf-8.codeberg.page) form. `String` and `Text` are+hashed character by character, while `ByteString` contributes its raw bytes.+The library provides instances for `Word8`, `Word16`, `Word32`, `Word64`,+`Word128`, `Word256`, `Int8`, `Int16`, `Int32`, `Int64`, and `Char`.++## Custom element types++Give the element type a `ByteFoldable` instance to hash containers of your+own type:++```haskell+import Data.Hash.Mono.FNV (fnv1a)+import Data.Hash.Mono.Internal.ByteFoldable (ByteFoldable (..))+import Data.Word (Word8, Word64)++data Rgb = Rgb Word8 Word8 Word8++instance ByteFoldable Rgb where+ foldlBytes f z (Rgb r g b) = f (f (f z r) g) b++-- Hashes [Rgb 0x12 0x34 0x56] as the bytes 0x12 0x34 0x56.+fnv1a @Word64 [Rgb 0x12 0x34 0x56]+```++The bytes an instance emits are the bytes hashed, so changing an instance+changes every hash of containers holding that element type.++## Formatting and linting++Sources are formatted with [fourmolu](https://github.com/fourmolu/fourmolu) and+linted with [hlint](https://github.com/ndmitchell/hlint). CI checks both, using+the versions pinned in `.github/workflows/ci.yml`, so run them before opening+a pull request:++```console+fourmolu --mode inplace $(git ls-files '*.hs')+hlint src test bench+```++## License++BSD-3-Clause. See [LICENSE](LICENSE).
+ bench/Main.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++module Main (main) where++import Control.DeepSeq (NFData, force)+import Control.Exception (evaluate)+import Criterion (Benchmark, bench, bgroup, whnf)+import Criterion.Main (defaultMain)+import qualified Data.ByteString as BS+import Data.Hash.Mono.FNV (fnv1, fnv1a)+import Data.Hash.Mono.HalfSipHash (halfSipHash)+import Data.Hash.Mono.SipHash (sipHash)+import qualified Data.Text as T+import Data.WideWord.Word128 (Word128)+import Data.WideWord.Word256 (Word256)+import Data.Word (Word32, Word64)++newtype Sizes a = Sizes [(String, a)]++mkSizes :: (Int -> a) -> Sizes a+mkSizes f =+ Sizes+ [ ("small input", f 10)+ , ("medium input", f 1000)+ , ("large input", f 100000)+ , ("huge input", f 10000000)+ ]++-- | Smaller sizes for element types with a large in-memory footprint.+mkElementSizes :: (Int -> a) -> Sizes a+mkElementSizes f =+ Sizes+ [ ("small input", f 100)+ , ("medium input", f 1000)+ , ("large input", f 10000)+ ]++forceSizes :: (NFData a) => Sizes a -> IO (Sizes a)+forceSizes sizes@(Sizes xs) = do+ _ <- evaluate $ force xs+ pure sizes++mkBench :: (a -> b) -> Sizes a -> [Benchmark]+mkBench fun (Sizes xs) = [bench name (whnf fun x) | (name, x) <- xs]++main :: IO ()+main = do+ strings <- forceSizes $ mkSizes (`replicate` 'a')+ bytes <- forceSizes $ mkSizes (`BS.replicate` 97)+ texts <- forceSizes $ mkSizes (\n -> T.replicate n (T.singleton 'a'))+ word128s <- forceSizes $ mkElementSizes (\n -> [fromIntegral i :: Word128 | i <- [0 .. n - 1]])+ word256s <- forceSizes $ mkElementSizes (\n -> [fromIntegral i :: Word256 | i <- [0 .. n - 1]])++ boundaryInputs <-+ evaluate $+ force+ [ (n, BS.replicate n 97)+ | n <- [254, 255, 256, 257, 258, 511, 512, 513]+ ]++ defaultMain+ [ bgroup "FNV1 Word32" $ mkBench (fnv1 @Word32) strings+ , bgroup "FNV1a Word32" $ mkBench (fnv1a @Word32) strings+ , bgroup "FNV1 Word64" $ mkBench (fnv1 @Word64) strings+ , bgroup "FNV1a Word64" $ mkBench (fnv1a @Word64) strings+ , bgroup "FNV1 Word128" $ mkBench (fnv1 @Word128) strings+ , bgroup "FNV1a Word128" $ mkBench (fnv1a @Word128) strings+ , bgroup "FNV1 Word256" $ mkBench (fnv1 @Word256) strings+ , bgroup "FNV1a Word256" $ mkBench (fnv1a @Word256) strings+ , bgroup "SipHash-2-4 Word64" $ mkBench (sipHash @Word64 2 4 0xc0ffee) strings+ , bgroup "SipHash-2-4 Word128" $ mkBench (sipHash @Word128 2 4 0xc0ffee) strings+ , bgroup "HalfSipHash-2-4 Word32" $ mkBench (halfSipHash @Word32 2 4 0xc0ffee) strings+ , bgroup "HalfSipHash-2-4 Word64" $ mkBench (halfSipHash @Word64 2 4 0xc0ffee) strings+ , bgroup "FNV1a Word64/ByteString" $ mkBench (fnv1a @Word64) bytes+ , bgroup "FNV1a Word64/Text" $ mkBench (fnv1a @Word64) texts+ , bgroup "SipHash-2-4 Word64/ByteString" $ mkBench (sipHash @Word64 2 4 0xc0ffee) bytes+ , bgroup "SipHash-2-4 Word64/Text" $ mkBench (sipHash @Word64 2 4 0xc0ffee) texts+ , bgroup "HalfSipHash-2-4 Word32/ByteString" $ mkBench (halfSipHash @Word32 2 4 0xc0ffee) bytes+ , bgroup "HalfSipHash-2-4 Word32/Text" $ mkBench (halfSipHash @Word32 2 4 0xc0ffee) texts+ , bgroup+ "SipHash-2-4 Word64 length boundary"+ [ bench (show n) $ whnf (sipHash @Word64 2 4 0xc0ffee) input+ | (n, input) <- boundaryInputs+ ]+ , bgroup "FNV1a Word64/[Word128]" $ mkBench (fnv1a @Word64) word128s+ , bgroup "FNV1a Word256/[Word128]" $ mkBench (fnv1a @Word256) word128s+ , bgroup "SipHash-2-4 Word64/[Word128]" $ mkBench (sipHash @Word64 2 4 0xc0ffee) word128s+ , bgroup "FNV1a Word64/[Word256]" $ mkBench (fnv1a @Word64) word256s+ , bgroup "FNV1a Word256/[Word256]" $ mkBench (fnv1a @Word256) word256s+ , bgroup "SipHash-2-4 Word64/[Word256]" $ mkBench (sipHash @Word64 2 4 0xc0ffee) word256s+ ]
+ mono-hash.cabal view
@@ -0,0 +1,102 @@+cabal-version: 3.0+name: mono-hash+version: 0.1.0.0+synopsis: Hashing for monomorphic containers.+description:+ FNV, SipHash, and HalfSipHash hashing for monomorphic containers.+license: BSD-3-Clause+license-file: LICENSE+author: Philipp Hagenlocher+maintainer: me@philipphagenlocher.de+category: Data+build-type: Simple+homepage: https://github.com/phagenlocher/mono-hash#readme+bug-reports: https://github.com/phagenlocher/mono-hash/issues+extra-doc-files:+ CHANGELOG.md+ README.md+tested-with:+ ghc ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8 || ==9.6.7+ || ==9.8.4 || ==9.10.3 || ==9.12.4 || ==9.14.1++source-repository head+ type: git+ location: https://github.com/phagenlocher/mono-hash++common warnings+ ghc-options: -Wall++library+ import: warnings+ ghc-options: -O2++ exposed-modules:+ Data.Hash.Mono.FNV+ Data.Hash.Mono.HalfSipHash+ Data.Hash.Mono.Internal.ByteFoldable+ Data.Hash.Mono.SipHash++ other-modules:+ Data.Hash.Mono.Internal++ build-depends:+ base >=4.14.3.0 && <5,+ mono-traversable >=1.0.21 && <1.1,+ wide-word >=0.1.7 && <0.2++ hs-source-dirs: src++ default-language: Haskell2010++ default-extensions:+ ConstraintKinds+ FlexibleContexts+ ImportQualifiedPost+ InstanceSigs+ ScopedTypeVariables++test-suite mono-hash-test+ import: warnings++ default-language: Haskell2010++ other-modules:+ Test.Data.ByteFoldable+ Test.Data.FNV+ Test.Data.SipHash+ Test.Data.HalfSipHash++ type: exitcode-stdio-1.0++ hs-source-dirs: test++ main-is: Main.hs++ build-depends:+ base >=4.14.3.0 && <5,+ bytestring >=0.10 && <0.13,+ mono-hash,+ tasty >=1.4 && <1.6,+ tasty-hunit >=0.10 && <0.11,+ text >=1.2 && <2.2,+ wide-word >=0.1.7 && <0.2,++benchmark mono-hash-bench+ type: exitcode-stdio-1.0++ hs-source-dirs: bench++ default-language: Haskell2010++ ghc-options: -O2++ main-is: Main.hs++ build-depends:+ base >=4.14.3.0 && <5,+ bytestring >=0.10 && <0.13,+ criterion >=1.5 && <1.7,+ deepseq >=1.4 && <1.6,+ mono-hash,+ text >=1.2 && <2.2,+ wide-word >=0.1.7 && <0.2,
+ src/Data/Hash/Mono/FNV.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE BangPatterns #-}++-- | FNV-1 and FNV-1a hashes for any 'MonoFoldable' container.+module Data.Hash.Mono.FNV (+ FNVData,+ FNVResult,+ HasFNVBasis,+ fnv1,+ fnv1a,+)+where++import Data.Bits (Bits (xor))+import Data.Hash.Mono.Internal.ByteFoldable (ByteFoldable (..))+import Data.MonoTraversable (Element, MonoFoldable (ofoldl'))+import Data.WideWord.Word128 (Word128)+import Data.WideWord.Word256 (Word256)+import Data.Word (Word32, Word64, Word8)++-- | Offset basis and prime for an FNV result width.+class HasFNVBasis a where+ -- | Offset basis used to seed the hash.+ fnvOffsetBasis :: a++ -- | Prime applied once per input byte.+ fnvPrime :: a++instance HasFNVBasis Word32 where+ fnvOffsetBasis :: Word32+ fnvOffsetBasis = 2166136261++ fnvPrime :: Word32+ fnvPrime = 16777619++instance HasFNVBasis Word64 where+ fnvOffsetBasis :: Word64+ fnvOffsetBasis = 14695981039346656037++ fnvPrime :: Word64+ fnvPrime = 1099511628211++instance HasFNVBasis Word128 where+ fnvOffsetBasis :: Word128+ fnvOffsetBasis = 144066263297769815596495629667062367629++ fnvPrime :: Word128+ fnvPrime = 309485009821345068724781371++instance HasFNVBasis Word256 where+ fnvOffsetBasis :: Word256+ fnvOffsetBasis = 100029257958052580907070968620625704837092796014241193945225284501741471925557++ fnvPrime :: Word256+ fnvPrime = 374144419156711147060143317175368453031918731002211++-- | Constraint for types that can be used as an FNV result.+type FNVResult a = (HasFNVBasis a, Bits a, Num a)++-- | Constraint for containers hashed with FNV.+type FNVData a = (MonoFoldable a, ByteFoldable (Element a))++fnvGeneric :: forall result mono. (FNVData mono, FNVResult result) => (result -> Word8 -> result) -> mono -> result+fnvGeneric fnvRound = ofoldl' (foldlBytes fnvRound) fnvOffsetBasis+{-# INLINE fnvGeneric #-}++{- | FNV-1 hash of a monomorphic container.++Example:+@+fnv1 \@'Word64' \"hello\"+@+-}+fnv1 :: forall result mono. (FNVData mono, FNVResult result) => mono -> result+fnv1 = fnvGeneric fnvRound+ where+ fnvRound :: result -> Word8 -> result+ fnvRound !acc !octet = (acc * fnvPrime) `xor` fromIntegral octet+{-# INLINEABLE fnv1 #-}++{- | FNV-1a hash of a monomorphic container.++Example:+@+fnv1a \@'Word64' \"hello\"+@+-}+fnv1a :: forall result mono. (FNVData mono, FNVResult result) => mono -> result+fnv1a = fnvGeneric fnvRound+ where+ fnvRound :: result -> Word8 -> result+ fnvRound !acc !octet = (acc `xor` fromIntegral octet) * fnvPrime+{-# INLINEABLE fnv1a #-}
+ src/Data/Hash/Mono/HalfSipHash.hs view
@@ -0,0 +1,170 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE TypeApplications #-}++-- | HalfSipHash-@c@-@d@ for any 'MonoFoldable' container.+module Data.Hash.Mono.HalfSipHash (+ HalfSipHashData,+ HalfSipHashResult,+ halfSipHash,+)+where++import Data.Bits (Bits (rotateL, shiftL, shiftR, xor, (.&.), (.|.)))+import Data.Hash.Mono.Internal (byteSwap32)+import Data.Hash.Mono.Internal.ByteFoldable (ByteFoldable (..))+import Data.MonoTraversable (Element, MonoFoldable (ofoldl'))+import Data.Word (Word32, Word64, Word8)++-- | Result types that 'halfSipHash' can produce.+class HalfSipHashResult a where+ -- | Adjust the initial state for the selected result type.+ initialize :: HalfSipData -> HalfSipData++ -- | Run the finalization rounds and return the hash.+ finalization :: Word -> HalfSipData -> a++instance HalfSipHashResult Word32 where+ initialize :: HalfSipData -> HalfSipData+ initialize = id++ finalization :: Word -> HalfSipData -> Word32+ finalization d (HalfSipData !v0 !v1 !v2 !v3) =+ let v2' = v2 `xor` 0xff+ (HalfSipData !_ v1' _ !v3') = halfSipRounds d (HalfSipData v0 v1 v2' v3)+ in v1' `xor` v3'++instance HalfSipHashResult Word64 where+ initialize :: HalfSipData -> HalfSipData+ initialize (HalfSipData !v0 !v1 !v2 !v3) = HalfSipData v0 (v1 `xor` 0xee) v2 v3++ finalization :: Word -> HalfSipData -> Word64+ finalization d (HalfSipData !v0 !v1 !v2 !v3) =+ let v2' = v2 `xor` 0xee+ (HalfSipData !v0' !v1' !v2'' !v3') = halfSipRounds d (HalfSipData v0 v1 v2' v3)+ word0 = v1' `xor` v3'+ v1'' = v1' `xor` 0xdd+ (HalfSipData _ !v1''' _ !v3'') = halfSipRounds d (HalfSipData v0' v1'' v2'' v3')+ word1 = v1''' `xor` v3''+ in (fromIntegral word1 `shiftL` 32) + fromIntegral word0++-- | Constraint for containers hashed with HalfSipHash.+type HalfSipHashData a = (MonoFoldable a, ByteFoldable (Element a))++-- | HalfSipHash internal state, consisting of four 32-bit words.+data HalfSipData = HalfSipData+ { hv0 :: {-# UNPACK #-} !Word32+ , hv1 :: {-# UNPACK #-} !Word32+ , hv2 :: {-# UNPACK #-} !Word32+ , hv3 :: {-# UNPACK #-} !Word32+ }++-- | Internal HalfSipHash accumulator.+data HalfSipStream = HalfSipStream+ { hsData :: {-# UNPACK #-} !HalfSipData+ -- ^ HalfSipHash state.+ , hsWord :: {-# UNPACK #-} !Word32+ -- ^ Input bytes buffered so far, in little-endian order.+ , hsCount :: {-# UNPACK #-} !Int+ -- ^ Number of bytes buffered in 'hsWord' (0-3).+ , hsLen :: {-# UNPACK #-} !Word8+ -- ^ Total number of input bytes, modulo 256.+ }++{- | Compute HalfSipHash-@c@-@d@ of a monomorphic container.++@c@ and @d@ are the compression and finalization round counts;+HalfSipHash-2-4 is the standard variant.++Byte order: the 'Word64' key holds the 8 reference key bytes in+big-endian order, and each 32-bit half is then read as a little-endian+word. The result is the reference implementation's output word: a+'Word32' result is the 32-bit tag. A 'Word64' result packs the first+32-bit tag word in the low half and the second in the high half; its+little-endian serialization is the 8-byte reference digest.++Example:+@+halfSipHash \@'Word32' 2 4 0xc0ffee \"hello\"+@+-}+halfSipHash :: forall result mono. (HalfSipHashData mono, HalfSipHashResult result) => Word -> Word -> Word64 -> mono -> result+halfSipHash c d key mono =+ case ofoldl' (foldlBytes (step c)) initStream mono of+ HalfSipStream{hsData = state, hsWord = word, hsLen = len} ->+ finalization d (compress c state (word .|. (fromIntegral len `shiftL` 24)))+ where+ initData :: HalfSipData+ initData =+ HalfSipData+ { hv0 = k0+ , hv1 = k1+ , hv2 = k0 `xor` 0x6c796765+ , hv3 = k1 `xor` 0x74656462+ }+ where+ k0 :: Word32+ k0 = byteSwap32 . fromIntegral $ key `shiftR` 32++ k1 :: Word32+ k1 = byteSwap32 . fromIntegral $ key .&. 0xffffffff++ initStream :: HalfSipStream+ initStream =+ HalfSipStream+ { hsData = initialize @result initData+ , hsWord = 0+ , hsCount = 0+ , hsLen = 0+ }+{-# INLINEABLE halfSipHash #-}++step :: Word -> HalfSipStream -> Word8 -> HalfSipStream+step c HalfSipStream{hsData = d, hsWord = word, hsCount = n, hsLen = len} !b =+ let word' = word .|. (fromIntegral b `shiftL` (8 * n))+ len' = len + 1+ in if n == 3+ then HalfSipStream{hsData = compress c d word', hsWord = 0, hsCount = 0, hsLen = len'}+ else HalfSipStream{hsData = d, hsWord = word', hsCount = n + 1, hsLen = len'}+{-# INLINE step #-}++compress :: Word -> HalfSipData -> Word32 -> HalfSipData+compress c (HalfSipData !v0 !v1 !v2 !v3) m =+ let v3' = v3 `xor` m+ (HalfSipData !v0' !v1' !v2' !v3'') = halfSipRounds c (HalfSipData v0 v1 v2 v3')+ v0'' = v0' `xor` m+ in HalfSipData v0'' v1' v2' v3''+{-# INLINE compress #-}++halfSipRound :: HalfSipData -> HalfSipData+halfSipRound (HalfSipData !v0 !v1 !v2 !v3) =+ let v0' = v0 + v1+ v1' = v1 `rotateL` 5+ v1'' = v1' `xor` v0'+ v0'' = v0' `rotateL` 16+ v2' = v2 + v3+ v3' = v3 `rotateL` 8+ v3'' = v3' `xor` v2'+ v0''' = v0'' + v3''+ v3''' = v3'' `rotateL` 7+ v3'''' = v3''' `xor` v0'''+ v2'' = v2' + v1''+ v1''' = v1'' `rotateL` 13+ v1'''' = v1''' `xor` v2''+ v2''' = v2'' `rotateL` 16+ in HalfSipData v0''' v1'''' v2''' v3''''+{-# INLINE halfSipRound #-}++halfSipRoundN :: Word -> HalfSipData -> HalfSipData+halfSipRoundN 0 !x = x+halfSipRoundN n !x = halfSipRoundN (n - 1) $! halfSipRound x++-- | Unrolled variant of 'halfSipRoundN' for the small counts used in practice.+halfSipRounds :: Word -> HalfSipData -> HalfSipData+halfSipRounds 1 !x = halfSipRound x+halfSipRounds 2 !x = halfSipRound (halfSipRound x)+halfSipRounds 3 !x = halfSipRound (halfSipRound (halfSipRound x))+halfSipRounds 4 !x = halfSipRound (halfSipRound (halfSipRound (halfSipRound x)))+halfSipRounds n !x = halfSipRoundN n x+{-# INLINE halfSipRounds #-}
+ src/Data/Hash/Mono/Internal.hs view
@@ -0,0 +1,43 @@+-- | Internal helpers shared by the hash implementations.+module Data.Hash.Mono.Internal (+ byteSwap64,+ byteSwap32,+)+where++import Data.Bits (Bits (shiftL, shiftR, (.&.)))+import Data.Word (Word32, Word64)++-- | Byte-swap a 'Word64'.+byteSwap64 :: Word64 -> Word64+byteSwap64 w =+ let c0 = (w `shiftR` 56) .&. 0xff+ c1 = (w `shiftR` 48) .&. 0xff+ c2 = (w `shiftR` 40) .&. 0xff+ c3 = (w `shiftR` 32) .&. 0xff+ c4 = (w `shiftR` 24) .&. 0xff+ c5 = (w `shiftR` 16) .&. 0xff+ c6 = (w `shiftR` 8) .&. 0xff+ c7 = w .&. 0xff+ in c0+ + (c1 `shiftL` 8)+ + (c2 `shiftL` 16)+ + (c3 `shiftL` 24)+ + (c4 `shiftL` 32)+ + (c5 `shiftL` 40)+ + (c6 `shiftL` 48)+ + (c7 `shiftL` 56)+{-# INLINEABLE byteSwap64 #-}++-- | Byte-swap a 'Word32'.+byteSwap32 :: Word32 -> Word32+byteSwap32 w =+ let c0 = (w `shiftR` 24) .&. 0xff+ c1 = (w `shiftR` 16) .&. 0xff+ c2 = (w `shiftR` 8) .&. 0xff+ c3 = w .&. 0xff+ in c0+ + (c1 `shiftL` 8)+ + (c2 `shiftL` 16)+ + (c3 `shiftL` 24)+{-# INLINEABLE byteSwap32 #-}
+ src/Data/Hash/Mono/Internal/ByteFoldable.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE InstanceSigs #-}++-- | Byte encoding for types.+module Data.Hash.Mono.Internal.ByteFoldable (+ ByteFoldable (..),+)+where++import Data.Bits (Bits (shiftR, (.&.)))+import Data.Char qualified as Char+import Data.Int (Int16, Int32, Int64, Int8)+import Data.WideWord.Word128 (Word128 (..))+import Data.WideWord.Word256 (Word256 (..))+import Data.Word (Word16, Word32, Word64, Word8)++{- | Types with a fixed byte encoding.++An instance must define a fixed order for the bytes to be folded.+-}+class ByteFoldable a where+ -- | Fold over the bytes of a value.+ foldlBytes :: (b -> Word8 -> b) -> b -> a -> b++{- | 'Char' is encoded as+<https://wtf-8.codeberg.page WTF-8>, the UTF-8 encoding extended to+lone surrogates. For all other code points the bytes are ordinary UTF-8.++'Char' can represent lone surrogates, which strict UTF-8 cannot encode.+Replacing them, as @Text@ does with @U+FFFD@, would be lossy and would let+distinct strings produce the same bytes. WTF-8 instead uses the ordinary+three-byte shape for them, so every 'Char' has an encoding, the encoding+stays injective, and valid text remains plain UTF-8. A 'String' and a+@Text@ containing a lone surrogate therefore encode differently.+-}+instance ByteFoldable Char where+ foldlBytes f z c+ | n < 0x80 = f z (fromIntegral n)+ | n < 0x800 =+ f+ (f z (fromIntegral (0xc0 + (n `shiftR` 6))))+ (fromIntegral (0x80 + (n .&. 0x3f)))+ | n < 0x10000 =+ f+ ( f+ (f z (fromIntegral (0xe0 + (n `shiftR` 12))))+ (fromIntegral (0x80 + ((n `shiftR` 6) .&. 0x3f)))+ )+ (fromIntegral (0x80 + (n .&. 0x3f)))+ | otherwise =+ f+ ( f+ ( f+ (f z (fromIntegral (0xf0 + (n `shiftR` 18))))+ (fromIntegral (0x80 + ((n `shiftR` 12) .&. 0x3f)))+ )+ (fromIntegral (0x80 + ((n `shiftR` 6) .&. 0x3f)))+ )+ (fromIntegral (0x80 + (n .&. 0x3f)))+ where+ n :: Int+ n = Char.ord c+ {-# INLINE foldlBytes #-}++instance ByteFoldable Word8 where+ foldlBytes f = f+ {-# INLINE foldlBytes #-}++{- | Encoded as its two's-complement bit pattern, the same bytes as the+corresponding 'Word8'.+-}+instance ByteFoldable Int8 where+ foldlBytes f z i = foldlBytes f z (fromIntegral i :: Word8)+ {-# INLINE foldlBytes #-}++-- | Encoded as two bytes, most significant first.+instance ByteFoldable Word16 where+ foldlBytes f z w =+ f (f z (fromIntegral (w `shiftR` 8))) (fromIntegral w)+ {-# INLINE foldlBytes #-}++{- | Encoded as its two's-complement bit pattern, the same bytes as the+corresponding 'Word16'.+-}+instance ByteFoldable Int16 where+ foldlBytes f z i = foldlBytes f z (fromIntegral i :: Word16)+ {-# INLINE foldlBytes #-}++-- | Encoded as four bytes, most significant first.+instance ByteFoldable Word32 where+ foldlBytes f z w =+ f+ ( f+ ( f+ (f z (fromIntegral (w `shiftR` 24)))+ (fromIntegral (w `shiftR` 16))+ )+ (fromIntegral (w `shiftR` 8))+ )+ (fromIntegral w)+ {-# INLINE foldlBytes #-}++{- | Encoded as its two's-complement bit pattern, the same bytes as the+corresponding 'Word32'.+-}+instance ByteFoldable Int32 where+ foldlBytes f z i = foldlBytes f z (fromIntegral i :: Word32)+ {-# INLINE foldlBytes #-}++-- | Encoded as eight bytes, most significant first.+instance ByteFoldable Word64 where+ foldlBytes f z w =+ f+ ( f+ ( f+ ( f+ ( f+ ( f+ ( f+ (f z (fromIntegral (w `shiftR` 56)))+ (fromIntegral (w `shiftR` 48))+ )+ (fromIntegral (w `shiftR` 40))+ )+ (fromIntegral (w `shiftR` 32))+ )+ (fromIntegral (w `shiftR` 24))+ )+ (fromIntegral (w `shiftR` 16))+ )+ (fromIntegral (w `shiftR` 8))+ )+ (fromIntegral w)+ {-# INLINE foldlBytes #-}++{- | Encoded as its two's-complement bit pattern, the same bytes as the+corresponding 'Word64'.+-}+instance ByteFoldable Int64 where+ foldlBytes f z i = foldlBytes f z (fromIntegral i :: Word64)+ {-# INLINE foldlBytes #-}++-- | Encoded as sixteen bytes, most significant first.+instance ByteFoldable Word128 where+ foldlBytes f z w =+ foldlBytes f (foldlBytes f z (word128Hi64 w)) (word128Lo64 w)+ {-# INLINE foldlBytes #-}++-- | Encoded as thirty-two bytes, most significant first.+instance ByteFoldable Word256 where+ foldlBytes f z w =+ foldlBytes+ f+ ( foldlBytes+ f+ ( foldlBytes+ f+ (foldlBytes f z (word256hi w))+ (word256m1 w)+ )+ (word256m0 w)+ )+ (word256lo w)+ {-# INLINE foldlBytes #-}
+ src/Data/Hash/Mono/SipHash.hs view
@@ -0,0 +1,171 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE TypeApplications #-}++-- | SipHash-@c@-@d@ for any 'MonoFoldable' container.+module Data.Hash.Mono.SipHash (+ SipHashData,+ SipHashResult,+ sipHash,+)+where++import Data.Bits (Bits (rotateL, shiftL, xor, (.|.)))+import Data.Hash.Mono.Internal (byteSwap64)+import Data.Hash.Mono.Internal.ByteFoldable (ByteFoldable (..))+import Data.MonoTraversable (Element, MonoFoldable (ofoldl'))+import Data.WideWord.Word128 (Word128 (..))+import Data.Word (Word64, Word8)++-- | Result types that 'sipHash' can produce.+class SipHashResult a where+ -- | Adjust the initial state for the selected result type.+ initialize :: SipData -> SipData++ -- | Run the finalization rounds and return the hash.+ finalization :: Word -> SipData -> a++instance SipHashResult Word64 where+ initialize :: SipData -> SipData+ initialize = id++ finalization :: Word -> SipData -> Word64+ finalization d (SipData !v0 !v1 !v2 !v3) =+ let v2' = v2 `xor` 0xff+ (SipData !v0' !v1' !v2'' !v3') = sipRounds d (SipData v0 v1 v2' v3)+ in v0' `xor` v1' `xor` v2'' `xor` v3'++instance SipHashResult Word128 where+ initialize :: SipData -> SipData+ initialize (SipData !v0 !v1 !v2 !v3) = SipData v0 (v1 `xor` 0xee) v2 v3++ finalization :: Word -> SipData -> Word128+ finalization d (SipData !v0 !v1 !v2 !v3) =+ let v2' = v2 `xor` 0xee+ (SipData !v0' !v1' !v2'' !v3') = sipRounds d (SipData v0 v1 v2' v3)+ word0 = v0' `xor` v1' `xor` v2'' `xor` v3'+ v1'' = v1' `xor` 0xdd+ (SipData !v0'' !v1''' !v2''' !v3'') = sipRounds d (SipData v0' v1'' v2'' v3')+ word1 = v0'' `xor` v1''' `xor` v2''' `xor` v3''+ in Word128 word1 word0++-- | Constraint for containers hashable with SipHash.+type SipHashData a = (MonoFoldable a, ByteFoldable (Element a))++-- | SipHash internal state.+data SipData = SipData+ { sv0 :: {-# UNPACK #-} !Word64+ , sv1 :: {-# UNPACK #-} !Word64+ , sv2 :: {-# UNPACK #-} !Word64+ , sv3 :: {-# UNPACK #-} !Word64+ }++-- | Internal SipHash accumulator.+data SipStream = SipStream+ { ssData :: {-# UNPACK #-} !SipData+ -- ^ SipHash state.+ , ssWord :: {-# UNPACK #-} !Word64+ -- ^ Input bytes buffered so far, in little-endian order.+ , ssCount :: {-# UNPACK #-} !Int+ -- ^ Number of bytes buffered in 'ssWord'.+ , ssLen :: {-# UNPACK #-} !Word8+ -- ^ Total number of input bytes, modulo 256.+ }++{- | Compute SipHash-@c@-@d@ of a monomorphic container.++@c@ and @d@ are the compression and finalization round counts;+SipHash-2-4 is the standard variant.++Byte order: the @Word128@ key holds the 16 reference key bytes in+big-endian order, and each 64-bit half is then read as a little-endian+word. The result is the reference implementation's output word: a+'Word64' result is the 64-bit tag. A @Word128@ result packs the first+64-bit tag word in the low half and the second in the high half; its+little-endian serialization is the 16-byte reference digest.++Example:+@+sipHash \@'Word64' 2 4 0xc0ffee \"hello\"+@+-}+sipHash :: forall result mono. (SipHashData mono, SipHashResult result) => Word -> Word -> Word128 -> mono -> result+sipHash c d key mono =+ case ofoldl' (foldlBytes (step c)) initStream mono of+ SipStream{ssData = state, ssWord = word, ssLen = len} ->+ finalization d (compress c state (word .|. (fromIntegral len `shiftL` 56)))+ where+ initData :: SipData+ initData =+ SipData+ { sv0 = k0 `xor` 0x736f6d6570736575+ , sv1 = k1 `xor` 0x646f72616e646f6d+ , sv2 = k0 `xor` 0x6c7967656e657261+ , sv3 = k1 `xor` 0x7465646279746573+ }+ where+ k0 :: Word64+ k0 = byteSwap64 $ word128Hi64 key++ k1 :: Word64+ k1 = byteSwap64 $ word128Lo64 key++ initStream :: SipStream+ initStream =+ SipStream+ { ssData = initialize @result initData+ , ssWord = 0+ , ssCount = 0+ , ssLen = 0+ }+{-# INLINEABLE sipHash #-}++step :: Word -> SipStream -> Word8 -> SipStream+step c SipStream{ssData = d, ssWord = word, ssCount = n, ssLen = len} !b =+ let word' = word .|. (fromIntegral b `shiftL` (8 * n))+ len' = len + 1+ in if n == 7+ then SipStream{ssData = compress c d word', ssWord = 0, ssCount = 0, ssLen = len'}+ else SipStream{ssData = d, ssWord = word', ssCount = n + 1, ssLen = len'}+{-# INLINE step #-}++compress :: Word -> SipData -> Word64 -> SipData+compress c (SipData !v0 !v1 !v2 !v3) m =+ let v3' = v3 `xor` m+ (SipData !v0' !v1' !v2' !v3'') = sipRounds c (SipData v0 v1 v2 v3')+ v0'' = v0' `xor` m+ in SipData v0'' v1' v2' v3''+{-# INLINE compress #-}++sipRound :: SipData -> SipData+sipRound (SipData !v0 !v1 !v2 !v3) =+ let v0' = v0 + v1+ v1' = v1 `rotateL` 13+ v1'' = v1' `xor` v0'+ v0'' = v0' `rotateL` 32+ v2' = v2 + v3+ v3' = v3 `rotateL` 16+ v3'' = v3' `xor` v2'+ v0''' = v0'' + v3''+ v3''' = v3'' `rotateL` 21+ v3'''' = v3''' `xor` v0'''+ v2'' = v2' + v1''+ v1''' = v1'' `rotateL` 17+ v1'''' = v1''' `xor` v2''+ v2''' = v2'' `rotateL` 32+ in SipData v0''' v1'''' v2''' v3''''+{-# INLINE sipRound #-}++sipRoundN :: Word -> SipData -> SipData+sipRoundN 0 !x = x+sipRoundN n !x = sipRoundN (n - 1) $! sipRound x++-- | Unrolled variant of 'sipRoundN' for the small counts used in practice.+sipRounds :: Word -> SipData -> SipData+sipRounds 1 !x = sipRound x+sipRounds 2 !x = sipRound (sipRound x)+sipRounds 3 !x = sipRound (sipRound (sipRound x))+sipRounds 4 !x = sipRound (sipRound (sipRound (sipRound x)))+sipRounds n !x = sipRoundN n x+{-# INLINE sipRounds #-}
+ test/Main.hs view
@@ -0,0 +1,362 @@+{-# LANGUAGE TypeApplications #-}++module Main (main) where++import Data.Bits (Bits, shiftL, shiftR, (.&.))+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import qualified Data.ByteString.Lazy as BSL+import qualified Data.ByteString.Lazy.Char8 as BSLC+import Data.Hash.Mono.FNV (fnv1, fnv1a)+import Data.Hash.Mono.HalfSipHash+import Data.Hash.Mono.SipHash+import Data.Int (Int16, Int32, Int64, Int8)+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import Data.WideWord.Word128 (Word128)+import Data.WideWord.Word256 (Word256)+import Data.Word (Word16, Word32, Word64, Word8)+import qualified Test.Data.ByteFoldable+import qualified Test.Data.FNV+import qualified Test.Data.HalfSipHash+import qualified Test.Data.SipHash+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.HUnit (assertBool, testCase, (@?=))++main :: IO ()+main = defaultMain tests++{- | Code points spanning the one- to four-byte UTF-8 ranges, including the+boundaries between them.+-}+charEncodingInput :: String+charEncodingInput = "\x00\x7f\x80\x7ff\x800\xffff\x10000\x1234\x1F600\x10FFFF"++-- | UTF-8 bytes of a 'Char'; lone surrogates use the 3-byte WTF-8 form.+charBytes :: Char -> [Word8]+charBytes c+ | n < 0x80 = [fromIntegral n]+ | n < 0x800 = [byte 0xc0 6, byte 0x80 0]+ | n < 0x10000 = [byte 0xe0 12, byte 0x80 6, byte 0x80 0]+ | otherwise = [byte 0xf0 18, byte 0x80 12, byte 0x80 6, byte 0x80 0]+ where+ n = fromEnum c+ byte mask shift = fromIntegral (mask + ((n `shiftR` shift) .&. 0x3f))++-- | UTF-8 bytes of a 'String'.+utf8 :: String -> BS.ByteString+utf8 = TE.encodeUtf8 . T.pack++-- | Big-endian bytes of a fixed-width word.+wordBytes :: (Bits a, Integral a) => Int -> a -> [Word8]+wordBytes width w =+ [fromIntegral (w `shiftR` (8 * i)) | i <- [width - 1, width - 2 .. 0]]++packWords :: (Bits a, Integral a) => Int -> [a] -> BS.ByteString+packWords width = BS.pack . concatMap (wordBytes width)++word16Samples :: [Word16]+word16Samples = [0x0102, 0x0304, 0xfffe]++word32Samples :: [Word32]+word32Samples = [0x01020304, 0x05060708, 0xdeadbeef]++word64Samples :: [Word64]+word64Samples = [0x0102030405060708, 0x1112131415161718, 0xdeadbeefcafed00d]++-- | Boundary values for the signed element types.+int8Samples :: [Int8]+int8Samples = [minBound, -1, 0, 1, maxBound]++int16Samples :: [Int16]+int16Samples = [minBound, -1, 0, 1, maxBound]++int32Samples :: [Int32]+int32Samples = [minBound, -1, 0, 1, maxBound]++int64Samples :: [Int64]+int64Samples = [minBound, -1, 0, 1, maxBound]++-- | Big-endian two's-complement encoding of the signed sample lists.+int8SampleBytes :: BS.ByteString+int8SampleBytes = BS.pack [0x80, 0xff, 0x00, 0x01, 0x7f]++int16SampleBytes :: BS.ByteString+int16SampleBytes =+ BS.pack [0x80, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xff]++int32SampleBytes :: BS.ByteString+int32SampleBytes =+ BS.pack+ [ 0x80+ , 0x00+ , 0x00+ , 0x00+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x01+ , 0x7f+ , 0xff+ , 0xff+ , 0xff+ ]++int64SampleBytes :: BS.ByteString+int64SampleBytes =+ BS.pack+ [ 0x80+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x00+ , 0x01+ , 0x7f+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ , 0xff+ ]++word128Sample :: Word128+word128Sample =+ (fromIntegral (0x0102030405060708 :: Word64) `shiftL` 64)+ + fromIntegral (0x1112131415161718 :: Word64)++word256Sample :: Word256+word256Sample =+ (fromIntegral (0x2122232425262728 :: Word64) `shiftL` 192)+ + (fromIntegral (0x3132333435363738 :: Word64) `shiftL` 128)+ + (fromIntegral (0x4142434445464748 :: Word64) `shiftL` 64)+ + fromIntegral (0x5152535455565758 :: Word64)++tests :: TestTree+tests =+ testGroup+ "Tests"+ [ goldenSamples+ , inputEncoding+ , encodingCollisions+ , Test.Data.ByteFoldable.tests+ ]++{- | Hashes must match the reference vectors in 'Test.Data.SipHash',+'Test.Data.HalfSipHash', and 'Test.Data.FNV'.+-}+goldenSamples :: TestTree+goldenSamples =+ testGroup+ "Golden Samples"+ [ testGroup+ "FNV"+ [ testCase "FNV1 Word32 String matches UTF-8 bytes" $ fmap (fnv1 @Word32) (Test.Data.FNV.inputs @String) @?= fmap (fnv1 @Word32 . utf8) (Test.Data.FNV.inputs @String)+ , testCase "FNV1a Word32 String matches UTF-8 bytes" $ fmap (fnv1a @Word32) (Test.Data.FNV.inputs @String) @?= fmap (fnv1a @Word32 . utf8) (Test.Data.FNV.inputs @String)+ , testCase "FNV1 Word64 String matches UTF-8 bytes" $ fmap (fnv1 @Word64) (Test.Data.FNV.inputs @String) @?= fmap (fnv1 @Word64 . utf8) (Test.Data.FNV.inputs @String)+ , testCase "FNV1a Word64 String matches UTF-8 bytes" $ fmap (fnv1a @Word64) (Test.Data.FNV.inputs @String) @?= fmap (fnv1a @Word64 . utf8) (Test.Data.FNV.inputs @String)+ , testCase "FNV1 Word32 Text matches UTF-8 bytes" $ fmap (fnv1 @Word32) (Test.Data.FNV.inputs @Text) @?= fmap (fnv1 @Word32 . TE.encodeUtf8) (Test.Data.FNV.inputs @Text)+ , testCase "FNV1a Word32 Text matches UTF-8 bytes" $ fmap (fnv1a @Word32) (Test.Data.FNV.inputs @Text) @?= fmap (fnv1a @Word32 . TE.encodeUtf8) (Test.Data.FNV.inputs @Text)+ , testCase "FNV1 Word64 Text matches UTF-8 bytes" $ fmap (fnv1 @Word64) (Test.Data.FNV.inputs @Text) @?= fmap (fnv1 @Word64 . TE.encodeUtf8) (Test.Data.FNV.inputs @Text)+ , testCase "FNV1a Word64 Text matches UTF-8 bytes" $ fmap (fnv1a @Word64) (Test.Data.FNV.inputs @Text) @?= fmap (fnv1a @Word64 . TE.encodeUtf8) (Test.Data.FNV.inputs @Text)+ , testCase "FNV1a Word32 non-ASCII String" $ fmap (fnv1a @Word32) Test.Data.FNV.utf8Inputs @?= Test.Data.FNV.fnv1aVectorsForWord32Utf8+ , testCase "FNV1a Word32 non-ASCII Text" $ fmap ((fnv1a @Word32) . T.pack) Test.Data.FNV.utf8Inputs @?= Test.Data.FNV.fnv1aVectorsForWord32Utf8+ , testCase "FNV1a Word64 non-ASCII String" $ fmap (fnv1a @Word64) Test.Data.FNV.utf8Inputs @?= Test.Data.FNV.fnv1aVectorsForWord64Utf8+ , testCase "FNV1a Word64 non-ASCII Text" $ fmap ((fnv1a @Word64) . T.pack) Test.Data.FNV.utf8Inputs @?= Test.Data.FNV.fnv1aVectorsForWord64Utf8+ , testCase "FNV1 Word32 ByteString" $ fmap (fnv1 @Word32) (Test.Data.FNV.inputs @BS.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord32+ , testCase "FNV1a Word32 ByteString" $ fmap (fnv1a @Word32) (Test.Data.FNV.inputs @BS.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord32+ , testCase "FNV1 Word64 ByteString" $ fmap (fnv1 @Word64) (Test.Data.FNV.inputs @BS.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord64+ , testCase "FNV1a Word64 ByteString" $ fmap (fnv1a @Word64) (Test.Data.FNV.inputs @BS.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord64+ , testCase "FNV1 Word32 Lazy ByteString" $ fmap (fnv1 @Word32) (Test.Data.FNV.inputs @BSL.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord32+ , testCase "FNV1a Word32 Lazy ByteString" $ fmap (fnv1a @Word32) (Test.Data.FNV.inputs @BSL.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord32+ , testCase "FNV1 Word64 Lazy ByteString" $ fmap (fnv1 @Word64) (Test.Data.FNV.inputs @BSL.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord64+ , testCase "FNV1a Word64 Lazy ByteString" $ fmap (fnv1a @Word64) (Test.Data.FNV.inputs @BSL.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord64+ , testCase "FNV1 Word32 ByteString Char8" $ fmap (fnv1 @Word32) (Test.Data.FNV.inputs @BSC.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord32+ , testCase "FNV1a Word32 ByteString Char8" $ fmap (fnv1a @Word32) (Test.Data.FNV.inputs @BSC.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord32+ , testCase "FNV1 Word64 ByteString Char8" $ fmap (fnv1 @Word64) (Test.Data.FNV.inputs @BSC.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord64+ , testCase "FNV1a Word64 ByteString Char8" $ fmap (fnv1a @Word64) (Test.Data.FNV.inputs @BSC.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord64+ , testCase "FNV1 Word32 Lazy ByteString Char8" $ fmap (fnv1 @Word32) (Test.Data.FNV.inputs @BSLC.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord32+ , testCase "FNV1a Word32 Lazy ByteString Char8" $ fmap (fnv1a @Word32) (Test.Data.FNV.inputs @BSLC.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord32+ , testCase "FNV1 Word64 Lazy ByteString Char8" $ fmap (fnv1 @Word64) (Test.Data.FNV.inputs @BSLC.ByteString) @?= Test.Data.FNV.fnv1VectorsForWord64+ , testCase "FNV1a Word64 Lazy ByteString Char8" $ fmap (fnv1a @Word64) (Test.Data.FNV.inputs @BSLC.ByteString) @?= Test.Data.FNV.fnv1aVectorsForWord64+ ]+ , testGroup+ "SipHash"+ [ testCase "SipHash-2-4 Word64 String" $ fmap (sipHash @Word64 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @String) @?= Test.Data.SipHash.sipHash24VectorsForWord64+ , testCase "SipHash-2-4 Word64 Text" $ fmap (sipHash @Word64 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @Text) @?= Test.Data.SipHash.sipHash24VectorsForWord64+ , testCase "SipHash-2-4 Word64 ByteString" $ fmap (sipHash @Word64 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BS.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord64+ , testCase "SipHash-2-4 Word64 Lazy ByteString" $ fmap (sipHash @Word64 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BSL.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord64+ , testCase "SipHash-2-4 Word64 ByteString Char8" $ fmap (sipHash @Word64 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BSC.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord64+ , testCase "SipHash-2-4 Word64 Lazy ByteString Char8" $ fmap (sipHash @Word64 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BSLC.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord64+ , testCase "SipHash-2-4 Word128 String" $ fmap (sipHash @Word128 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @String) @?= Test.Data.SipHash.sipHash24VectorsForWord128+ , testCase "SipHash-2-4 Word128 Text" $ fmap (sipHash @Word128 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @Text) @?= Test.Data.SipHash.sipHash24VectorsForWord128+ , testCase "SipHash-2-4 Word128 ByteString" $ fmap (sipHash @Word128 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BS.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord128+ , testCase "SipHash-2-4 Word128 Lazy ByteString" $ fmap (sipHash @Word128 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BSL.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord128+ , testCase "SipHash-2-4 Word128 ByteString Char8" $ fmap (sipHash @Word128 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BSC.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord128+ , testCase "SipHash-2-4 Word128 Lazy ByteString Char8" $ fmap (sipHash @Word128 2 4 Test.Data.SipHash.key) (Test.Data.SipHash.inputs @BSLC.ByteString) @?= Test.Data.SipHash.sipHash24VectorsForWord128+ , testCase "SipHash-2-4 Word64 boundary lengths" $ fmap (sipHash @Word64 2 4 Test.Data.SipHash.key) Test.Data.SipHash.boundaryInputs @?= Test.Data.SipHash.boundaryVectorsForWord64+ ]+ , testGroup+ "HalfSipHash"+ [ testCase "HalfSipHash-2-4 Word32 String" $ fmap (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @String) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord32+ , testCase "HalfSipHash-2-4 Word32 Text" $ fmap (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @Text) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord32+ , testCase "HalfSipHash-2-4 Word32 ByteString" $ fmap (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BS.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord32+ , testCase "HalfSipHash-2-4 Word32 Lazy ByteString" $ fmap (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BSL.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord32+ , testCase "HalfSipHash-2-4 Word32 ByteString Char8" $ fmap (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BSC.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord32+ , testCase "HalfSipHash-2-4 Word32 Lazy ByteString Char8" $ fmap (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BSLC.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord32+ , testCase "HalfSipHash-2-4 Word64 String" $ fmap (halfSipHash @Word64 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @String) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord64+ , testCase "HalfSipHash-2-4 Word64 Text" $ fmap (halfSipHash @Word64 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @Text) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord64+ , testCase "HalfSipHash-2-4 Word64 ByteString" $ fmap (halfSipHash @Word64 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BS.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord64+ , testCase "HalfSipHash-2-4 Word64 Lazy ByteString" $ fmap (halfSipHash @Word64 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BSL.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord64+ , testCase "HalfSipHash-2-4 Word64 ByteString Char8" $ fmap (halfSipHash @Word64 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BSC.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord64+ , testCase "HalfSipHash-2-4 Word64 Lazy ByteString Char8" $ fmap (halfSipHash @Word64 2 4 Test.Data.HalfSipHash.key) (Test.Data.HalfSipHash.inputs @BSLC.ByteString) @?= Test.Data.HalfSipHash.halfSipHash24VectorsForWord64+ , testCase "HalfSipHash-2-4 Word32 boundary lengths" $ fmap (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) Test.Data.HalfSipHash.boundaryInputs @?= Test.Data.HalfSipHash.boundaryVectorsForWord32+ ]+ ]++{- | Every element type must feed the hash the same bytes its explicit+byte encoding does, so typed inputs and byte inputs agree.+-}+inputEncoding :: TestTree+inputEncoding =+ testGroup+ "Input Encoding"+ [ testGroup+ "FNV"+ [ testCase "FNV1a Word64 Char encoding matches bytes" $ do+ let bytes = BS.pack (concatMap charBytes charEncodingInput)+ bytes @?= TE.encodeUtf8 (T.pack charEncodingInput)+ fnv1a @Word64 charEncodingInput @?= fnv1a @Word64 bytes+ fnv1a @Word64 (T.pack charEncodingInput) @?= fnv1a @Word64 bytes+ fnv1a @Word64 "\xD800" @?= fnv1a @Word64 (BS.pack [0xed, 0xa0, 0x80])+ , testCase "FNV1a Word64 word elements match bytes" $ do+ fnv1a @Word64 [word128Sample] @?= fnv1a @Word64 (BS.pack (wordBytes 16 word128Sample))+ fnv1a @Word64 [word256Sample] @?= fnv1a @Word64 (BS.pack (wordBytes 32 word256Sample))+ , testCase "FNV1 Word64 small word elements match bytes" $ do+ fnv1 @Word64 word16Samples @?= fnv1 @Word64 (packWords 2 word16Samples)+ fnv1 @Word64 word32Samples @?= fnv1 @Word64 (packWords 4 word32Samples)+ fnv1 @Word64 word64Samples @?= fnv1 @Word64 (packWords 8 word64Samples)+ , testCase "FNV1a Word64 small word elements match bytes" $ do+ fnv1a @Word64 word16Samples @?= fnv1a @Word64 (packWords 2 word16Samples)+ fnv1a @Word64 word32Samples @?= fnv1a @Word64 (packWords 4 word32Samples)+ fnv1a @Word64 word64Samples @?= fnv1a @Word64 (packWords 8 word64Samples)+ , testCase "FNV1a Word64 signed elements match two's complement bytes" $ do+ fnv1a @Word64 int8Samples @?= fnv1a @Word64 int8SampleBytes+ fnv1a @Word64 int16Samples @?= fnv1a @Word64 int16SampleBytes+ fnv1a @Word64 int32Samples @?= fnv1a @Word64 int32SampleBytes+ fnv1a @Word64 int64Samples @?= fnv1a @Word64 int64SampleBytes+ ]+ , testGroup+ "SipHash"+ [ testCase "SipHash-2-4 Word64 Char encoding matches bytes" $ do+ let bytes = BS.pack (concatMap charBytes charEncodingInput)+ bytes @?= TE.encodeUtf8 (T.pack charEncodingInput)+ sipHash @Word64 2 4 Test.Data.SipHash.key charEncodingInput @?= sipHash @Word64 2 4 Test.Data.SipHash.key bytes+ sipHash @Word64 2 4 Test.Data.SipHash.key (T.pack charEncodingInput) @?= sipHash @Word64 2 4 Test.Data.SipHash.key bytes+ , testCase "SipHash-2-4 Word64 word elements match bytes" $ do+ sipHash @Word64 2 4 Test.Data.SipHash.key [word128Sample] @?= sipHash @Word64 2 4 Test.Data.SipHash.key (BS.pack (wordBytes 16 word128Sample))+ sipHash @Word64 2 4 Test.Data.SipHash.key [word256Sample] @?= sipHash @Word64 2 4 Test.Data.SipHash.key (BS.pack (wordBytes 32 word256Sample))+ , testCase "SipHash-2-4 Word64 small word elements match bytes" $ do+ sipHash @Word64 2 4 Test.Data.SipHash.key word16Samples @?= sipHash @Word64 2 4 Test.Data.SipHash.key (packWords 2 word16Samples)+ sipHash @Word64 2 4 Test.Data.SipHash.key word32Samples @?= sipHash @Word64 2 4 Test.Data.SipHash.key (packWords 4 word32Samples)+ sipHash @Word64 2 4 Test.Data.SipHash.key word64Samples @?= sipHash @Word64 2 4 Test.Data.SipHash.key (packWords 8 word64Samples)+ , testCase "SipHash-2-4 Word64 signed elements match two's complement bytes" $ do+ sipHash @Word64 2 4 Test.Data.SipHash.key int8Samples @?= sipHash @Word64 2 4 Test.Data.SipHash.key int8SampleBytes+ sipHash @Word64 2 4 Test.Data.SipHash.key int16Samples @?= sipHash @Word64 2 4 Test.Data.SipHash.key int16SampleBytes+ sipHash @Word64 2 4 Test.Data.SipHash.key int32Samples @?= sipHash @Word64 2 4 Test.Data.SipHash.key int32SampleBytes+ sipHash @Word64 2 4 Test.Data.SipHash.key int64Samples @?= sipHash @Word64 2 4 Test.Data.SipHash.key int64SampleBytes+ ]+ , testGroup+ "HalfSipHash"+ [ testCase "HalfSipHash-2-4 Word32 Char encoding matches bytes" $ do+ let bytes = BS.pack (concatMap charBytes charEncodingInput)+ bytes @?= TE.encodeUtf8 (T.pack charEncodingInput)+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key charEncodingInput @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key bytes+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key (T.pack charEncodingInput) @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key bytes+ , testCase "HalfSipHash-2-4 Word32 word elements match bytes" $ do+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key [word128Sample] @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key (BS.pack (wordBytes 16 word128Sample))+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key [word256Sample] @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key (BS.pack (wordBytes 32 word256Sample))+ , testCase "HalfSipHash-2-4 Word32 small word elements match bytes" $ do+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key word16Samples @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key (packWords 2 word16Samples)+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key word32Samples @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key (packWords 4 word32Samples)+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key word64Samples @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key (packWords 8 word64Samples)+ , testCase "HalfSipHash-2-4 Word32 signed elements match two's complement bytes" $ do+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int8Samples @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int8SampleBytes+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int16Samples @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int16SampleBytes+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int32Samples @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int32SampleBytes+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int64Samples @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key int64SampleBytes+ ]+ ]++{- | Distinct texts that the old, non-prefix-free 'Char' encoding mapped to+the same bytes must hash differently.+-}+encodingCollisions :: TestTree+encodingCollisions =+ testGroup+ "Encoding Collisions"+ [ testGroup+ "FNV"+ [ testCase "FNV1a Word64 String" $ checkCollisions (fnv1a @Word64) id+ , testCase "FNV1a Word64 Text" $ checkCollisions (fnv1a @Word64) T.pack+ ]+ , testGroup+ "SipHash"+ [ testCase "SipHash-2-4 Word64 String" $ checkCollisions (sipHash @Word64 2 4 Test.Data.SipHash.key) id+ , testCase "SipHash-2-4 Word64 Text" $ checkCollisions (sipHash @Word64 2 4 Test.Data.SipHash.key) T.pack+ ]+ , testGroup+ "HalfSipHash"+ [ testCase "HalfSipHash-2-4 Word32 String" $ checkCollisions (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) id+ , testCase "HalfSipHash-2-4 Word32 Text" $ checkCollisions (halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key) T.pack+ ]+ ]++checkCollisions :: (Eq a, Show a) => (t -> a) -> (String -> t) -> IO ()+checkCollisions h mk =+ mapM_+ (\(label, x, y) -> assertBool label (h (mk x) /= h (mk y)))+ collisionPairs++collisionPairs :: [(String, String, String)]+collisionPairs =+ [ ("U+0100 and U+0001 U+0000 must not collide", "\x0100", "\x01\x00")+ , ("U+1234 and U+0012 U+0034 must not collide", "\x1234", "\x12\x34")+ , ("U+1F600 and U+0001 U+00F6 U+0000 must not collide", "\x1F600", "\x01\xF6\x00")+ ]
+ test/Test/Data/ByteFoldable.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE TypeApplications #-}++{- | Tests for the public 'ByteFoldable' extension point: an element type+defined outside the library must be hashable via its own instance, and must+produce exactly the hash of the bytes it emits.+-}+module Test.Data.ByteFoldable (tests) where++import qualified Data.ByteString as BS+import Data.Hash.Mono.FNV (fnv1a)+import Data.Hash.Mono.HalfSipHash (halfSipHash)+import Data.Hash.Mono.Internal.ByteFoldable (ByteFoldable (..))+import Data.Hash.Mono.SipHash (sipHash)+import Data.Word (Word32, Word64, Word8)+import qualified Test.Data.HalfSipHash+import qualified Test.Data.SipHash+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))++-- | A user-defined element with a two-byte encoding, high byte first.+data TwoBytes = TwoBytes !Word8 !Word8++instance ByteFoldable TwoBytes where+ foldlBytes f z (TwoBytes hi lo) = f (f z hi) lo++-- | The bytes the instance above emits.+sampleBytes :: BS.ByteString+sampleBytes = BS.pack [0x01, 0x02]++sample :: TwoBytes+sample = TwoBytes 0x01 0x02++samples :: [TwoBytes]+samples = [sample]++tests :: TestTree+tests =+ testGroup+ "ByteFoldable"+ [ testCase "custom instance matches raw bytes (FNV-1a)" $+ fnv1a @Word64 samples @?= fnv1a @Word64 sampleBytes+ , testCase "custom instance matches raw bytes (SipHash-2-4)" $+ sipHash @Word64 2 4 Test.Data.SipHash.key samples+ @?= sipHash @Word64 2 4 Test.Data.SipHash.key sampleBytes+ , testCase "custom instance matches raw bytes (HalfSipHash-2-4)" $+ halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key samples+ @?= halfSipHash @Word32 2 4 Test.Data.HalfSipHash.key sampleBytes+ ]
+ test/Test/Data/FNV.hs view
@@ -0,0 +1,1078 @@+{-# LANGUAGE OverloadedStrings #-}++module Test.Data.FNV where++import Data.String (IsString)+import Data.Word (Word32, Word64)++inputs :: (IsString a, Monoid a) => [a]+inputs =+ [ ""+ , "a"+ , "b"+ , "c"+ , "d"+ , "e"+ , "f"+ , "fo"+ , "foo"+ , "foob"+ , "fooba"+ , "foobar"+ , "\x00"+ , "a\x00"+ , "b\x00"+ , "c\x00"+ , "d\x00"+ , "e\x00"+ , "f\x00"+ , "fo\x00"+ , "foo\x00"+ , "foob\x00"+ , "fooba\x00"+ , "foobar\x00"+ , "ch"+ , "cho"+ , "chon"+ , "chong"+ , "chongo"+ , "chongo "+ , "chongo w"+ , "chongo wa"+ , "chongo was"+ , "chongo was "+ , "chongo was h"+ , "chongo was he"+ , "chongo was her"+ , "chongo was here"+ , "chongo was here!"+ , "chongo was here!\n"+ , "ch\x00"+ , "cho\x00"+ , "chon\x00"+ , "chong\x00"+ , "chongo\x00"+ , "chongo \x00"+ , "chongo w\x00"+ , "chongo wa\x00"+ , "chongo was\x00"+ , "chongo was \x00"+ , "chongo was h\x00"+ , "chongo was he\x00"+ , "chongo was her\x00"+ , "chongo was here\x00"+ , "chongo was here!\x00"+ , "chongo was here!\n\x00"+ , "cu"+ , "cur"+ , "curd"+ , "curds"+ , "curds "+ , "curds a"+ , "curds an"+ , "curds and"+ , "curds and "+ , "curds and w"+ , "curds and wh"+ , "curds and whe"+ , "curds and whey"+ , "curds and whey\n"+ , "cu\x00"+ , "cur\x00"+ , "curd\x00"+ , "curds\x00"+ , "curds \x00"+ , "curds a\x00"+ , "curds an\x00"+ , "curds and\x00"+ , "curds and \x00"+ , "curds and w\x00"+ , "curds and wh\x00"+ , "curds and whe\x00"+ , "curds and whey\x00"+ , "curds and whey\n\x00"+ , "hi"+ , "hi\x00"+ , "hello"+ , "hello\x00"+ , "\xff\x00\x00\x01"+ , "\x01\x00\x00\xff"+ , "\xff\x00\x00\x02"+ , "\x02\x00\x00\xff"+ , "\xff\x00\x00\x03"+ , "\x03\x00\x00\xff"+ , "\xff\x00\x00\x04"+ , "\x04\x00\x00\xff"+ , "\x40\x51\x4e\x44"+ , "\x44\x4e\x51\x40"+ , "\x40\x51\x4e\x4a"+ , "\x4a\x4e\x51\x40"+ , "\x40\x51\x4e\x54"+ , "\x54\x4e\x51\x40"+ , "127.0.0.1"+ , "127.0.0.1\x00"+ , "127.0.0.2"+ , "127.0.0.2\x00"+ , "127.0.0.3"+ , "127.0.0.3\x00"+ , "64.81.78.68"+ , "64.81.78.68\x00"+ , "64.81.78.74"+ , "64.81.78.74\x00"+ , "64.81.78.84"+ , "64.81.78.84\x00"+ , "feedface"+ , "feedface\x00"+ , "feedfacedaffdeed"+ , "feedfacedaffdeed\x00"+ , "feedfacedeadbeef"+ , "feedfacedeadbeef\x00"+ , "line 1\nline 2\nline 3"+ , "chongo <Landon Curt Noll> /\\../\\"+ , "chongo <Landon Curt Noll> /\\../\\\x00"+ , "chongo (Landon Curt Noll) /\\../\\"+ , "chongo (Landon Curt Noll) /\\../\\\x00"+ , "http://antwrp.gsfc.nasa.gov/apod/astropix.html"+ , "http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash"+ , "http://epod.usra.edu/"+ , "http://exoplanet.eu/"+ , "http://hvo.wr.usgs.gov/cam3/"+ , "http://hvo.wr.usgs.gov/cams/HMcam/"+ , "http://hvo.wr.usgs.gov/kilauea/update/deformation.html"+ , "http://hvo.wr.usgs.gov/kilauea/update/images.html"+ , "http://hvo.wr.usgs.gov/kilauea/update/maps.html"+ , "http://hvo.wr.usgs.gov/volcanowatch/current_issue.html"+ , "http://neo.jpl.nasa.gov/risk/"+ , "http://norvig.com/21-days.html"+ , "http://primes.utm.edu/curios/home.php"+ , "http://slashdot.org/"+ , "http://tux.wr.usgs.gov/Maps/155.25-19.5.html"+ , "http://volcano.wr.usgs.gov/kilaueastatus.php"+ , "http://www.avo.alaska.edu/activity/Redoubt.php"+ , "http://www.dilbert.com/fast/"+ , "http://www.fourmilab.ch/gravitation/orbits/"+ , "http://www.fpoa.net/"+ , "http://www.ioccc.org/index.html"+ , "http://www.isthe.com/cgi-bin/number.cgi"+ , "http://www.isthe.com/chongo/bio.html"+ , "http://www.isthe.com/chongo/index.html"+ , "http://www.isthe.com/chongo/src/calc/lucas-calc"+ , "http://www.isthe.com/chongo/tech/astro/venus2004.html"+ , "http://www.isthe.com/chongo/tech/astro/vita.html"+ , "http://www.isthe.com/chongo/tech/comp/c/expert.html"+ , "http://www.isthe.com/chongo/tech/comp/calc/index.html"+ , "http://www.isthe.com/chongo/tech/comp/fnv/index.html"+ , "http://www.isthe.com/chongo/tech/math/number/howhigh.html"+ , "http://www.isthe.com/chongo/tech/math/number/number.html"+ , "http://www.isthe.com/chongo/tech/math/prime/mersenne.html"+ , "http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest"+ , "http://www.lavarnd.org/cgi-bin/corpspeak.cgi"+ , "http://www.lavarnd.org/cgi-bin/haiku.cgi"+ , "http://www.lavarnd.org/cgi-bin/rand-none.cgi"+ , "http://www.lavarnd.org/cgi-bin/randdist.cgi"+ , "http://www.lavarnd.org/index.html"+ , "http://www.lavarnd.org/what/nist-test.html"+ , "http://www.macosxhints.com/"+ , "http://www.mellis.com/"+ , "http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm"+ , "http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm"+ , "http://www.paulnoll.com/"+ , "http://www.pepysdiary.com/"+ , "http://www.sciencenews.org/index/home/activity/view"+ , "http://www.skyandtelescope.com/"+ , "http://www.sput.nl/~rob/sirius.html"+ , "http://www.systemexperts.com/"+ , "http://www.tq-international.com/phpBB3/index.php"+ , "http://www.travelquesttours.com/index.htm"+ , "http://www.wunderground.com/global/stations/89606.html"+ , mconcat $ replicate 10 "21701"+ , mconcat $ replicate 10 "M21701"+ , mconcat $ replicate 10 "2^21701-1"+ , mconcat $ replicate 10 "\x54\xc5"+ , mconcat $ replicate 10 "\xc5\x54"+ , mconcat $ replicate 10 "23209"+ , mconcat $ replicate 10 "M23209"+ , mconcat $ replicate 10 "2^23209-1"+ , mconcat $ replicate 10 "\x5a\xa9"+ , mconcat $ replicate 10 "\xa9\x5a"+ , mconcat $ replicate 10 "391581216093"+ , mconcat $ replicate 10 "391581*2^216093-1"+ , mconcat $ replicate 10 "\x05\xf9\x9d\x03\x4c\x81"+ , mconcat $ replicate 10 "FEDCBA9876543210"+ , mconcat $ replicate 10 "\xfe\xdc\xba\x98\x76\x54\x32\x10"+ , mconcat $ replicate 10 "EFCDAB8967452301"+ , mconcat $ replicate 10 "\xef\xcd\xab\x89\x67\x45\x23\x01"+ , mconcat $ replicate 10 "0123456789ABCDEF"+ , mconcat $ replicate 10 "\x01\x23\x45\x67\x89\xab\xcd\xef"+ , mconcat $ replicate 10 "1032547698BADCFE"+ , mconcat $ replicate 10 "\x10\x32\x54\x76\x98\xba\xdc\xfe"+ , mconcat $ replicate 500 "\x00"+ , mconcat $ replicate 500 "\x07"+ , mconcat $ replicate 500 "~"+ , mconcat $ replicate 500 "\x7f"+ ]++{- | Non-ASCII inputs for the UTF-8 golden vectors: @é@, @café@, @naïve@,+@U+0100@, @U+1F600@, and @U+10FFFF@.+-}+utf8Inputs :: [String]+utf8Inputs =+ [ "\xe9"+ , "caf\xe9"+ , "na\xefve"+ , "\x0100"+ , "\x1F600"+ , "\x10FFFF"+ ]++{- | FNV-1a over the UTF-8 bytes of 'utf8Inputs'. With a 32-bit result the+values wrap modulo @2^32@.+-}+fnv1aVectorsForWord32Utf8 :: [Word32]+fnv1aVectorsForWord32Utf8 =+ [ 0x1e9de8c1+ , 0xa82b5049+ , 0x999a082b+ , 0x779015e9+ , 0x33a29608+ , 0x41c1bc3a+ ]++-- | FNV-1a over the UTF-8 bytes of 'utf8Inputs'.+fnv1aVectorsForWord64Utf8 :: [Word64]+fnv1aVectorsForWord64Utf8 =+ [ 0x0ac21707b7181e01+ , 0x48e8823acfa40d89+ , 0x1e858bc68a6332ab+ , 0x0ab1f007b70b1b89+ , 0xfeff073875020288+ , 0x6eb1861c2c1fff5a+ ]++fnv1VectorsForWord32 :: [Word32]+fnv1VectorsForWord32 =+ [ 0x811c9dc5+ , 0x050c5d7e+ , 0x050c5d7d+ , 0x050c5d7c+ , 0x050c5d7b+ , 0x050c5d7a+ , 0x050c5d79+ , 0x6b772514+ , 0x408f5e13+ , 0xb4b1178b+ , 0xfdc80fb0+ , 0x31f0b262+ , 0x050c5d1f+ , 0x70772d5a+ , 0x6f772bc7+ , 0x6e772a34+ , 0x6d7728a1+ , 0x6c77270e+ , 0x6b77257b+ , 0x408f5e7c+ , 0xb4b117e9+ , 0xfdc80fd1+ , 0x31f0b210+ , 0xffe8d046+ , 0x6e772a5c+ , 0x4197aebb+ , 0xfcc8100f+ , 0xfdf147fa+ , 0xbcd44ee1+ , 0x23382c13+ , 0x846d619e+ , 0x1630abdb+ , 0xc99e89b2+ , 0x1692c316+ , 0x9f091bca+ , 0x2556be9b+ , 0x628e0e73+ , 0x98a0bf6c+ , 0xb10d5725+ , 0xdd002f35+ , 0x4197aed4+ , 0xfcc81061+ , 0xfdf1479d+ , 0xbcd44e8e+ , 0x23382c33+ , 0x846d61e9+ , 0x1630abba+ , 0xc99e89c1+ , 0x1692c336+ , 0x9f091ba2+ , 0x2556befe+ , 0x628e0e01+ , 0x98a0bf09+ , 0xb10d5704+ , 0xdd002f3f+ , 0x1c4a506f+ , 0x6e772a41+ , 0x26978421+ , 0xe184ff97+ , 0x9b5e5ac6+ , 0x5b88e592+ , 0xaa8164b7+ , 0x20b18c7b+ , 0xf28025c5+ , 0x84bb753f+ , 0x3219925a+ , 0x384163c6+ , 0x54f010d7+ , 0x8cea820c+ , 0xe12ab8ee+ , 0x26978453+ , 0xe184fff3+ , 0x9b5e5ab5+ , 0x5b88e5b2+ , 0xaa8164d6+ , 0x20b18c15+ , 0xf28025a1+ , 0x84bb751f+ , 0x3219922d+ , 0x384163ae+ , 0x54f010b2+ , 0x8cea8275+ , 0xe12ab8e4+ , 0x64411eaa+ , 0x6977223c+ , 0x428ae474+ , 0xb6fa7167+ , 0x73408525+ , 0xb78320a1+ , 0x0caf4135+ , 0xb78320a2+ , 0xcdc88e80+ , 0xb78320a3+ , 0x8ee1dbcb+ , 0xb78320a4+ , 0x4ffb2716+ , 0x860632aa+ , 0xcc2c5c64+ , 0x860632a4+ , 0x2a7ec4a6+ , 0x860632ba+ , 0xfefe8e14+ , 0x0a3cffd8+ , 0xf606c108+ , 0x0a3cffdb+ , 0xf906c5c1+ , 0x0a3cffda+ , 0xf806c42e+ , 0xc07167d7+ , 0xc9867775+ , 0xbf716668+ , 0xc78435b8+ , 0xc6717155+ , 0xb99568cf+ , 0x7662e0d6+ , 0x33a7f0e2+ , 0xc2732f95+ , 0xb053e78f+ , 0x3a19c02a+ , 0xa089821e+ , 0x31ae8f83+ , 0x995fa9c4+ , 0x35983f8c+ , 0x5036a251+ , 0x97018583+ , 0xb4448d60+ , 0x025dfe59+ , 0xc5eab3af+ , 0x7d21ba1e+ , 0x7704cddb+ , 0xd0071bfe+ , 0x0ff3774c+ , 0xb0fea0ea+ , 0x58177303+ , 0x4f599cda+ , 0x3e590a47+ , 0x965595f8+ , 0xc37f178d+ , 0x9711dd26+ , 0x23c99b7f+ , 0x6e568b17+ , 0x43f0245b+ , 0xbcb7a001+ , 0x12e6dffe+ , 0x0792f2d6+ , 0xb966936b+ , 0x46439ac5+ , 0x728d49af+ , 0xd33745c9+ , 0xbc382a57+ , 0x4bda1d31+ , 0xce35ccae+ , 0x3b6eed94+ , 0x445c9c58+ , 0x3db8bf9d+ , 0x2dee116d+ , 0xc18738da+ , 0x5b156176+ , 0x2aa7d593+ , 0xb2409658+ , 0xe1489528+ , 0xfe1ee07e+ , 0xe8842315+ , 0x3a6a63a2+ , 0x06d2c18c+ , 0xf8ef7225+ , 0x843d3300+ , 0xbb24f7ae+ , 0x878c0ec9+ , 0xb557810f+ , 0x57423246+ , 0x87f7505e+ , 0xbb809f20+ , 0x8932abb5+ , 0x0a9b3aa0+ , 0xb8682a24+ , 0xa7ac1c56+ , 0x11409252+ , 0xa987f517+ , 0xf309e7ed+ , 0xc9e8f417+ , 0x7f447bdd+ , 0xb929adc5+ , 0x57022879+ , 0xdcfd2c49+ , 0x6edafff5+ , 0xf04fb1f1+ , 0xfb7de8b9+ , 0xc5f1d7e9+ , 0x32c1f439+ , 0x7fd3eb7d+ , 0x81597da5+ , 0x05eb7a25+ , 0x9c0fa1b5+ , 0x53ccb1c5+ , 0xfabece15+ , 0x4ad745a5+ , 0xe5bdc495+ , 0x23b3c0a5+ , 0xfa823dd5+ , 0x0c6c58b9+ , 0xe2dbccd5+ , 0xdb7f50f9+ ]++fnv1aVectorsForWord32 :: [Word32]+fnv1aVectorsForWord32 =+ [ 0x811c9dc5+ , 0xe40c292c+ , 0xe70c2de5+ , 0xe60c2c52+ , 0xe10c2473+ , 0xe00c22e0+ , 0xe30c2799+ , 0x6222e842+ , 0xa9f37ed7+ , 0x3f5076ef+ , 0x39aaa18a+ , 0xbf9cf968+ , 0x050c5d1f+ , 0x2b24d044+ , 0x9d2c3f7f+ , 0x7729c516+ , 0xb91d6109+ , 0x931ae6a0+ , 0x052255db+ , 0xbef39fe6+ , 0x6150ac75+ , 0x9aab3a3d+ , 0x519c4c3e+ , 0x0c1c9eb8+ , 0x5f299f4e+ , 0xef8580f3+ , 0xac297727+ , 0x4546b9c0+ , 0xbd564e7d+ , 0x6bdd5c67+ , 0xdd77ed30+ , 0xf4ca9683+ , 0x4aeb9bd0+ , 0xe0e67ad0+ , 0xc2d32fa8+ , 0x7f743fb7+ , 0x6900631f+ , 0xc59c990e+ , 0x448524fd+ , 0xd49930d5+ , 0x1c85c7ca+ , 0x0229fe89+ , 0x2c469265+ , 0xce566940+ , 0x8bdd8ec7+ , 0x34787625+ , 0xd3ca6290+ , 0xddeaf039+ , 0xc0e64870+ , 0xdad35570+ , 0x5a740578+ , 0x5b004d15+ , 0x6a9c09cd+ , 0x2384f10a+ , 0xda993a47+ , 0x8227df4f+ , 0x4c298165+ , 0xfc563735+ , 0x8cb91483+ , 0x775bf5d0+ , 0xd5c428d0+ , 0x34cc0ea3+ , 0xea3b4cb7+ , 0x8e59f029+ , 0x2094de2b+ , 0xa65a0ad4+ , 0x9bbee5f4+ , 0xbe836343+ , 0x22d5344e+ , 0x19a1470c+ , 0x4a56b1ff+ , 0x70b8e86f+ , 0x0a5b4a39+ , 0xb5c3f670+ , 0x53cc3f70+ , 0xc03b0a99+ , 0x7259c415+ , 0x4095108b+ , 0x7559bdb1+ , 0xb3bf0bbc+ , 0x2183ff1c+ , 0x2bd54279+ , 0x23a156ca+ , 0x64e2d7e4+ , 0x683af69a+ , 0xaed2346e+ , 0x4f9f2cab+ , 0x02935131+ , 0xc48fb86d+ , 0x2269f369+ , 0xc18fb3b4+ , 0x50ef1236+ , 0xc28fb547+ , 0x96c3bf47+ , 0xbf8fb08e+ , 0xf3e4d49c+ , 0x32179058+ , 0x280bfee6+ , 0x30178d32+ , 0x21addaf8+ , 0x4217a988+ , 0x772633d6+ , 0x08a3d11e+ , 0xb7e2323a+ , 0x07a3cf8b+ , 0x91dfb7d1+ , 0x06a3cdf8+ , 0x6bdd3d68+ , 0x1d5636a7+ , 0xd5b808e5+ , 0x1353e852+ , 0xbf16b916+ , 0xa55b89ed+ , 0x3c1a2017+ , 0x0588b13c+ , 0xf22f0174+ , 0xe83641e1+ , 0x6e69b533+ , 0xf1760448+ , 0x64c8bd58+ , 0x97b4ea23+ , 0x9a4e92e6+ , 0xcfb14012+ , 0xf01b2511+ , 0x0bbb59c3+ , 0xce524afa+ , 0xdd16ef45+ , 0x60648bb3+ , 0x7fa4bcfc+ , 0x5053ae17+ , 0xc9302890+ , 0x956ded32+ , 0x9136db84+ , 0xdf9d3323+ , 0x32bb6cd0+ , 0xc8f8385b+ , 0xeb08bfba+ , 0x62cc8e3d+ , 0xc3e20f5c+ , 0x39e97f17+ , 0x7837b203+ , 0x319e877b+ , 0xd3e63f89+ , 0x29b50b38+ , 0x5ed678b8+ , 0xb0d5b793+ , 0x52450be5+ , 0xfa72d767+ , 0x95066709+ , 0x7f52e123+ , 0x76966481+ , 0x063258b0+ , 0x2ded6e8a+ , 0xb07d7c52+ , 0xd0c71b71+ , 0xf684f1bd+ , 0x868ecfa8+ , 0xf794f684+ , 0xd19701c3+ , 0x346e171e+ , 0x91f8f676+ , 0x0bf58848+ , 0x6317b6d1+ , 0xafad4c54+ , 0x0f25681e+ , 0x91b18d49+ , 0x7d61c12e+ , 0x5147d25c+ , 0x9a8b6805+ , 0x4cd2a447+ , 0x1e549b14+ , 0x2fe1b574+ , 0xcf0cd31e+ , 0x6c471669+ , 0x0e5eef1e+ , 0x2bed3602+ , 0xb26249e0+ , 0x2c9b86a4+ , 0xe415e2bb+ , 0x18a98d1d+ , 0xb7df8b7b+ , 0x241e9075+ , 0x063f70dd+ , 0x0295aed9+ , 0x56a7f781+ , 0x253bc645+ , 0x46610921+ , 0x7c1577f9+ , 0x512b2851+ , 0x76823999+ , 0xc0586935+ , 0xf3415c85+ , 0x0ae4ff65+ , 0x58b79725+ , 0xdea43aa5+ , 0x2bb3be35+ , 0xea777a45+ , 0x8f21c305+ , 0x5c9d0865+ , 0xfa823dd5+ , 0x21a27271+ , 0x83c5c6d5+ , 0x813b0881+ ]++fnv1VectorsForWord64 :: [Word64]+fnv1VectorsForWord64 =+ [ 0xcbf29ce484222325+ , 0xaf63bd4c8601b7be+ , 0xaf63bd4c8601b7bd+ , 0xaf63bd4c8601b7bc+ , 0xaf63bd4c8601b7bb+ , 0xaf63bd4c8601b7ba+ , 0xaf63bd4c8601b7b9+ , 0x08326207b4eb2f34+ , 0xd8cbc7186ba13533+ , 0x0378817ee2ed65cb+ , 0xd329d59b9963f790+ , 0x340d8765a4dda9c2+ , 0xaf63bd4c8601b7df+ , 0x08326707b4eb37da+ , 0x08326607b4eb3627+ , 0x08326507b4eb3474+ , 0x08326407b4eb32c1+ , 0x08326307b4eb310e+ , 0x08326207b4eb2f5b+ , 0xd8cbc7186ba1355c+ , 0x0378817ee2ed65a9+ , 0xd329d59b9963f7f1+ , 0x340d8765a4dda9b0+ , 0x50a6d3b724a774a6+ , 0x08326507b4eb341c+ , 0xd8d5c8186ba98bfb+ , 0x1ccefc7ef118dbef+ , 0x0c92fab3ad3db77a+ , 0x9b77794f5fdec421+ , 0x0ac742dfe7874433+ , 0xd7dad5766ad8e2de+ , 0xa1bb96378e897f5b+ , 0x5b3f9b6733a367d2+ , 0xb07ce25cbea969f6+ , 0x8d9e9997f9df0d6a+ , 0x838c673d9603cb7b+ , 0x8b5ee8a5e872c273+ , 0x4507c4e9fb00690c+ , 0x4c9ca59581b27f45+ , 0xe0aca20b624e4235+ , 0xd8d5c8186ba98b94+ , 0x1ccefc7ef118db81+ , 0x0c92fab3ad3db71d+ , 0x9b77794f5fdec44e+ , 0x0ac742dfe7874413+ , 0xd7dad5766ad8e2a9+ , 0xa1bb96378e897f3a+ , 0x5b3f9b6733a367a1+ , 0xb07ce25cbea969d6+ , 0x8d9e9997f9df0d02+ , 0x838c673d9603cb1e+ , 0x8b5ee8a5e872c201+ , 0x4507c4e9fb006969+ , 0x4c9ca59581b27f64+ , 0xe0aca20b624e423f+ , 0x13998e580afa800f+ , 0x08326507b4eb3401+ , 0xd8d5ad186ba95dc1+ , 0x1c72e17ef0ca4e97+ , 0x2183c1b327c38ae6+ , 0xb66d096c914504f2+ , 0x404bf57ad8476757+ , 0x887976bd815498bb+ , 0x3afd7f02c2bf85a5+ , 0xfc4476b0eb70177f+ , 0x186d2da00f77ecba+ , 0xf97140fa48c74066+ , 0xa2b1cf49aa926d37+ , 0x0690712cd6cf940c+ , 0xf7045b3102b8906e+ , 0xd8d5ad186ba95db3+ , 0x1c72e17ef0ca4ef3+ , 0x2183c1b327c38a95+ , 0xb66d096c914504d2+ , 0x404bf57ad8476736+ , 0x887976bd815498d5+ , 0x3afd7f02c2bf85c1+ , 0xfc4476b0eb70175f+ , 0x186d2da00f77eccd+ , 0xf97140fa48c7400e+ , 0xa2b1cf49aa926d52+ , 0x0690712cd6cf9475+ , 0xf7045b3102b89064+ , 0x74f762479f9d6aea+ , 0x08326007b4eb2b9c+ , 0xd8c4c9186b9b1a14+ , 0x7b495389bdbdd4c7+ , 0x3b6dba0d69908e25+ , 0xd6b2b17bf4b71261+ , 0x447bfb7f98e615b5+ , 0xd6b2b17bf4b71262+ , 0x3bd2807f93fe1660+ , 0xd6b2b17bf4b71263+ , 0x3329057f8f16170b+ , 0xd6b2b17bf4b71264+ , 0x2a7f8a7f8a2e19b6+ , 0x23d3767e64b2f98a+ , 0xff768d7e4f9d86a4+ , 0x23d3767e64b2f984+ , 0xccd1837e334e4aa6+ , 0x23d3767e64b2f99a+ , 0x7691fd7e028f6754+ , 0x34ad3b1041204318+ , 0xa29e749ea9d201c8+ , 0x34ad3b104120431b+ , 0xa29e779ea9d206e1+ , 0x34ad3b104120431a+ , 0xa29e769ea9d2052e+ , 0x02a17ebca4aa3497+ , 0x229ef18bcd375c95+ , 0x02a17dbca4aa32c8+ , 0x229b6f8bcd3449d8+ , 0x02a184bca4aa3ed5+ , 0x22b3618bcd48c3ef+ , 0x5c2c346706186f36+ , 0xb78c410f5b84f8c2+ , 0xed9478212b267395+ , 0xd9bbb55c5256662f+ , 0x8c54f0203249438a+ , 0xbd9790b5727dc37e+ , 0xa64e5f36c9e2b0e3+ , 0x8fd0680da3088a04+ , 0x67aad32c078284cc+ , 0xb37d55d81c57b331+ , 0x55ac0f3829057c43+ , 0xcb27f4b8e1b6cc20+ , 0x26caf88bcbef2d19+ , 0x8e6e063b97e61b8f+ , 0xb42750f7f3b7c37e+ , 0xf3c6ba64cf7ca99b+ , 0xebfb69b427ea80fe+ , 0x39b50c3ed970f46c+ , 0x5b9b177aa3eb3e8a+ , 0x6510063ecf4ec903+ , 0x2b3bbd2c00797c7a+ , 0xf1d6204ff5cb4aa7+ , 0x4836e27ccf099f38+ , 0x82efbb0dd073b44d+ , 0x4a80c282ffd7d4c6+ , 0x305d1a9c9ee43bdf+ , 0x15c366948ffc6997+ , 0x80153ae218916e7b+ , 0xfa23e2bdf9e2a9e1+ , 0xd47e8d8a2333c6de+ , 0x7e128095f688b056+ , 0x2f5356890efcedab+ , 0x95c2b383014f55c5+ , 0x4727a5339ce6070f+ , 0xb0555ecd575108e9+ , 0x48d785770bb4af37+ , 0x09d4701c12af02b1+ , 0x79f031e78f3cf62e+ , 0x52a1ee85db1b5a94+ , 0x6bd95b2eb37fa6b8+ , 0x74971b7077aef85d+ , 0xb4e4fae2ffcc1aad+ , 0x2bd48bd898b8f63a+ , 0xe9966ac1556257f6+ , 0x92a3d1cd078ba293+ , 0xf81175a482e20ab8+ , 0x5bbb3de722e73048+ , 0x6b4f363492b9f2be+ , 0xc2d559df73d59875+ , 0xf75f62284bc7a8c2+ , 0xda8dd8e116a9f1cc+ , 0xbdc1e6ab76057885+ , 0xfec6a4238a1224a0+ , 0xc03f40f3223e290e+ , 0x1ed21673466ffda9+ , 0xdf70f906bb0dd2af+ , 0xf3dcda369f2af666+ , 0x9ebb11573cdcebde+ , 0x81c72d9077fedca0+ , 0x0ec074a31be5fb15+ , 0x2a8b3280b6c48f20+ , 0xfd31777513309344+ , 0x194534a86ad006b6+ , 0x3be6fdf46e0cfe12+ , 0x017cc137a07eb057+ , 0x9428fc6e7d26b54d+ , 0x9aaa2e3603ef8ad7+ , 0x82c6d3f3a0ccdf7d+ , 0xc86eeea00cf09b65+ , 0x705f8189dbb58299+ , 0x415a7f554391ca69+ , 0xcfe3d49fa2bdc555+ , 0xf0f9c56039b25191+ , 0x7075cb6abd1d32d9+ , 0x43c94e2c8b277509+ , 0x3cbfd4e4ea670359+ , 0xc05887810f4d019d+ , 0x14468ff93ac22dc5+ , 0xebed699589d99c05+ , 0x6d99f6df321ca5d5+ , 0x0cd410d08c36d625+ , 0xef1b2a2c86831d35+ , 0x3b349c4d69ee5f05+ , 0x55248ce88f45f035+ , 0xaa69ca6a18a4c885+ , 0x1fe3fce62bd816b5+ , 0x0289a488a8df69d9+ , 0x15e96e1613df98b5+ , 0xe6be57375ad89b99+ ]++fnv1aVectorsForWord64 :: [Word64]+fnv1aVectorsForWord64 =+ [ 0xcbf29ce484222325+ , 0xaf63dc4c8601ec8c+ , 0xaf63df4c8601f1a5+ , 0xaf63de4c8601eff2+ , 0xaf63d94c8601e773+ , 0xaf63d84c8601e5c0+ , 0xaf63db4c8601ead9+ , 0x08985907b541d342+ , 0xdcb27518fed9d577+ , 0xdd120e790c2512af+ , 0xcac165afa2fef40a+ , 0x85944171f73967e8+ , 0xaf63bd4c8601b7df+ , 0x089be207b544f1e4+ , 0x08a61407b54d9b5f+ , 0x08a2ae07b54ab836+ , 0x0891b007b53c4869+ , 0x088e4a07b5396540+ , 0x08987c07b5420ebb+ , 0xdcb28a18fed9f926+ , 0xdd1270790c25b935+ , 0xcac146afa2febf5d+ , 0x8593d371f738acfe+ , 0x34531ca7168b8f38+ , 0x08a25607b54a22ae+ , 0xf5faf0190cf90df3+ , 0xf27397910b3221c7+ , 0x2c8c2b76062f22e0+ , 0xe150688c8217b8fd+ , 0xf35a83c10e4f1f87+ , 0xd1edd10b507344d0+ , 0x2a5ee739b3ddb8c3+ , 0xdcfb970ca1c0d310+ , 0x4054da76daa6da90+ , 0xf70a2ff589861368+ , 0x4c628b38aed25f17+ , 0x9dd1f6510f78189f+ , 0xa3de85bd491270ce+ , 0x858e2fa32a55e61d+ , 0x46810940eff5f915+ , 0xf5fadd190cf8edaa+ , 0xf273ed910b32b3e9+ , 0x2c8c5276062f6525+ , 0xe150b98c821842a0+ , 0xf35aa3c10e4f55e7+ , 0xd1ed680b50729265+ , 0x2a5f0639b3dded70+ , 0xdcfbaa0ca1c0f359+ , 0x4054ba76daa6a430+ , 0xf709c7f5898562b0+ , 0x4c62e638aed2f9b8+ , 0x9dd1a8510f779415+ , 0xa3de2abd4911d62d+ , 0x858e0ea32a55ae0a+ , 0x46810f40eff60347+ , 0xc33bce57bef63eaf+ , 0x08a24307b54a0265+ , 0xf5b9fd190cc18d15+ , 0x4c968290ace35703+ , 0x07174bd5c64d9350+ , 0x5a294c3ff5d18750+ , 0x05b3c1aeb308b843+ , 0xb92a48da37d0f477+ , 0x73cdddccd80ebc49+ , 0xd58c4c13210a266b+ , 0xe78b6081243ec194+ , 0xb096f77096a39f34+ , 0xb425c54ff807b6a3+ , 0x23e520e2751bb46e+ , 0x1a0b44ccfe1385ec+ , 0xf5ba4b190cc2119f+ , 0x4c962690ace2baaf+ , 0x0716ded5c64cda19+ , 0x5a292c3ff5d150f0+ , 0x05b3e0aeb308ecf0+ , 0xb92a5eda37d119d9+ , 0x73ce41ccd80f6635+ , 0xd58c2c132109f00b+ , 0xe78baf81243f47d1+ , 0xb0968f7096a2ee7c+ , 0xb425a84ff807855c+ , 0x23e4e9e2751b56f9+ , 0x1a0b4eccfe1396ea+ , 0x54abd453bb2c9004+ , 0x08ba5f07b55ec3da+ , 0x337354193006cb6e+ , 0xa430d84680aabd0b+ , 0xa9bc8acca21f39b1+ , 0x6961196491cc682d+ , 0xad2bb1774799dfe9+ , 0x6961166491cc6314+ , 0x8d1bb3904a3b1236+ , 0x6961176491cc64c7+ , 0xed205d87f40434c7+ , 0x6961146491cc5fae+ , 0xcd3baf5e44f8ad9c+ , 0xe3b36596127cd6d8+ , 0xf77f1072c8e8a646+ , 0xe3b36396127cd372+ , 0x6067dce9932ad458+ , 0xe3b37596127cf208+ , 0x4b7b10fa9fe83936+ , 0xaabafe7104d914be+ , 0xf4d3180b3cde3eda+ , 0xaabafd7104d9130b+ , 0xf4cfb20b3cdb5bb1+ , 0xaabafc7104d91158+ , 0xf4cc4c0b3cd87888+ , 0xe729bac5d2a8d3a7+ , 0x74bc0524f4dfa4c5+ , 0xe72630c5d2a5b352+ , 0x6b983224ef8fb456+ , 0xe73042c5d2ae266d+ , 0x8527e324fdeb4b37+ , 0x0a83c86fee952abc+ , 0x7318523267779d74+ , 0x3e66d3d56b8caca1+ , 0x956694a5c0095593+ , 0xcac54572bb1a6fc8+ , 0xa7a4c9f3edebf0d8+ , 0x7829851fac17b143+ , 0x2c8f4c9af81bcf06+ , 0xd34e31539740c732+ , 0x3605a2ac253d2db1+ , 0x08c11b8346f4a3c3+ , 0x6be396289ce8a6da+ , 0xd9b957fb7fe794c5+ , 0x05be33da04560a93+ , 0x0957f1577ba9747c+ , 0xda2cc3acc24fba57+ , 0x74136f185b29e7f0+ , 0xb2f2b4590edb93b2+ , 0xb3608fce8b86ae04+ , 0x4a3a865079359063+ , 0x5b3a7ef496880a50+ , 0x48fae3163854c23b+ , 0x07aaa640476e0b9a+ , 0x2f653656383a687d+ , 0xa1031f8e7599d79c+ , 0xa31908178ff92477+ , 0x097edf3c14c3fb83+ , 0xb51ca83feaa0971b+ , 0xdd3c0d96d784f2e9+ , 0x86cd26a9ea767d78+ , 0xe6b215ff54a30c18+ , 0xec5b06a1c5531093+ , 0x45665a929f9ec5e5+ , 0x8c7609b4a9f10907+ , 0x89aac3a491f0d729+ , 0x32ce6b26e0f4a403+ , 0x614ab44e02b53e01+ , 0xfa6472eb6eef3290+ , 0x9e5d75eb1948eb6a+ , 0xb6d12ad4a8671852+ , 0x88826f56eba07af1+ , 0x44535bf2645bc0fd+ , 0x169388ffc21e3728+ , 0xf68aac9e396d8224+ , 0x8e87d7e7472b3883+ , 0x295c26caa8b423de+ , 0x322c814292e72176+ , 0x8a06550eb8af7268+ , 0xef86d60e661bcf71+ , 0x9e5426c87f30ee54+ , 0xf1ea8aa826fd047e+ , 0x0babaf9a642cb769+ , 0x4b3341d4068d012e+ , 0xd15605cbc30a335c+ , 0x5b21060aed8412e5+ , 0x45e2cda1ce6f4227+ , 0x50ae3745033ad7d4+ , 0xaa4588ced46bf414+ , 0xc1b0056c4a95467e+ , 0x56576a71de8b4089+ , 0xbf20965fa6dc927e+ , 0x569f8383c2040882+ , 0xe1e772fba08feca0+ , 0x4ced94af97138ac4+ , 0xc4112ffb337a82fb+ , 0xd64a4fd41de38b7d+ , 0x4cfc32329edebcbb+ , 0x0803564445050395+ , 0xaa1574ecf4642ffd+ , 0x694bc4e54cc315f9+ , 0xa3d7cb273b011721+ , 0x577c2f8b6115bfa5+ , 0xb7ec8c1a769fb4c1+ , 0x5d5cfce63359ab19+ , 0x33b96c3cd65b5f71+ , 0xd845097780602bb9+ , 0x84d47645d02da3d5+ , 0x83544f33b58773a5+ , 0x9175cbb2160836c5+ , 0xc71b3bc175e72bc5+ , 0x636806ac222ec985+ , 0xb6ef0e6950f52ed5+ , 0xead3d8a0f3dfdaa5+ , 0x922908fe9a861ba5+ , 0x6d4821de275fd5c5+ , 0x1fe3fce62bd816b5+ , 0xc23e9fccd6f70591+ , 0xc1af12bdfe16b5b5+ , 0x39e9f18f2f85e221+ ]
+ test/Test/Data/HalfSipHash.hs view
@@ -0,0 +1,182 @@+{- | Reference HalfSipHash-2-4 vectors.++The values are the reference implementation's output words, i.e. the+little-endian reading of the byte arrays in+<https://github.com/veorq/SipHash/blob/master/vectors.h>. The key bytes+are @00 01 .. 07@.+-}+module Test.Data.HalfSipHash where++import qualified Data.ByteString as BS+import Data.Char (chr)+import Data.String (IsString, fromString)+import Data.Word (Word32, Word64)++key :: Word64+key = 0x0001020304050607++inputs :: (IsString a, Monoid a) => [a]+inputs = fmap (\n -> fromString $ fmap chr [0 .. n - 1]) [0 .. 64 - 1]++-- | Inputs around the 256-byte length-byte wrap (254-513 bytes).+boundaryInputs :: [BS.ByteString]+boundaryInputs = [BS.replicate n 97 | n <- [254, 255, 256, 257, 258, 511, 512, 513]]++{- | HalfSipHash-2-4-32 reference output words for the empty input and+the prefixes of @00 01 ..@.+-}+halfSipHash24VectorsForWord32 :: [Word32]+halfSipHash24VectorsForWord32 =+ [ 0x5b9f35a9+ , 0xb85a4727+ , 0x03a662fa+ , 0x04e7fe8a+ , 0x89466e2a+ , 0x69b6fac5+ , 0x23fc6358+ , 0xc563cf8b+ , 0x8f84b8d0+ , 0x79e706f8+ , 0x3479b094+ , 0x50300808+ , 0x2f87f057+ , 0xff63e677+ , 0x7cf8ffd6+ , 0x972bfe74+ , 0x84acb5d9+ , 0x5b6474c4+ , 0x9b8d5b46+ , 0x87e3ef7b+ , 0x45104de3+ , 0xb3623f61+ , 0xfe67f370+ , 0xbdb8ade6+ , 0x630c4027+ , 0x75787826+ , 0x5f7b564f+ , 0x69e6b03a+ , 0x004064b0+ , 0xb40f67ff+ , 0x8b339e50+ , 0x1a9f585d+ , 0x1221e7fe+ , 0x59327533+ , 0x8c4f436a+ , 0x29b728fe+ , 0xecc65ce7+ , 0x548d7e69+ , 0x0f8b6863+ , 0xb4620b65+ , 0x4018bcb6+ , 0x0545075d+ , 0x2efd4224+ , 0x3a86b77b+ , 0x48d50577+ , 0xb10852d7+ , 0xc899d4b6+ , 0x2e209208+ , 0xe32ce169+ , 0xe580b58d+ , 0xc6649736+ , 0x04026e01+ , 0xd4f3853b+ , 0xbe66dbfe+ , 0x3a2a691e+ , 0xc08489c6+ , 0x40b9c5a5+ , 0x8ce8e99b+ , 0x4081bc7d+ , 0xc58e077c+ , 0x736ce7d4+ , 0xb9cb8f42+ , 0x7a9983bd+ , 0x744aea59+ ]++{- | HalfSipHash-2-4-64 reference output words. Each result is the+little-endian reading of an 8-byte @vectors_hsip64@ entry: the first+32-bit output word is the low half and the second is the high half.+-}+halfSipHash24VectorsForWord64 :: [Word64]+halfSipHash24VectorsForWord64 =+ [ 0xc83cb8b9591f8d21+ , 0x157338f8122455be+ , 0x57eb507cef394f06+ , 0x790606f7451a0fce+ , 0xa12ee55b178ae7d5+ , 0x80b53d2f3f7c9dcb+ , 0x25bca28a35913ece+ , 0x84c67bb0282720ff+ , 0x8c85e4bc20e8feed+ , 0x07838813cccc515b+ , 0xeef2a6069f46b095+ , 0x48cddd94393326ae+ , 0x99c7f5ae9f1fc77b+ , 0x44370c5ad752235a+ , 0x58e6e8ea70a8b13b+ , 0x02c9814ecb0b7d21+ , 0xb5f37b5fd2aa3673+ , 0x6a4f4c1c64c0ad37+ , 0xf9423e9a2bdbb2c9+ , 0x3c36ab2080e410f9+ , 0xdba7ee6f0a2bf51b+ , 0xefb3e869c21d7400+ , 0xef76a71bfa0301e2+ , 0x731d684be510224c+ , 0xf1a63fae45107470+ , 0x384071393740860c+ , 0xf0232911d89e890d+ , 0xb8e11eb8faf56b22+ , 0xb516001efb5f922d+ , 0xf110ee2cd5581936+ , 0x9d17984886af1a29+ , 0x7c11345c157f3c86+ , 0x6c6211d8469d7028+ , 0x9cf8281d68778424+ , 0x30988f52d7e42483+ , 0xd86bea3ae1d4eff9+ , 0xdc7642ec407ad686+ , 0x357ea9ccec92623f+ , 0x0921d424e72ed9cb+ , 0x793d408d80f68d36+ , 0x4caec8671cc8385b+ , 0xb3ac39d48971ab95+ , 0x24703225c0521aa9+ , 0xeaac2895c687005b+ , 0x5ab1dc27adf3301e+ , 0xd44e32909a5c7f69+ , 0x38dc5755990f5c49+ , 0x4df9293c2a202794+ , 0x3e3ea94bc0a8eaa9+ , 0x1812017d73c1a4ee+ , 0x495af6d88f562d91+ , 0x975cffb096959156+ , 0xe150f598795a4402+ , 0xb21f1de76c46ec86+ , 0xbce389d2e7699535+ , 0x967cbb62ca051b87+ , 0x1d5ff142f992a4a1+ , 0x6e5b09f67f26ec12+ , 0x9dd831b2a15e1b5d+ , 0x54ee923f45b4cfd8+ , 0x60e426bf902876d6+ , 0xf35cedb7a4633531+ , 0x9366d472b53a0bf9+ , 0x876032bf713ca62e+ ]++{- | Reference HalfSipHash-2-4-32 output words for 'boundaryInputs'.+The values use the same byte order as+'halfSipHash24VectorsForWord32'.+-}+boundaryVectorsForWord32 :: [Word32]+boundaryVectorsForWord32 =+ [ 0x8bafb24d+ , 0x80debc4f+ , 0xccc21763+ , 0x74aae63c+ , 0xc110387a+ , 0x8d238996+ , 0xea25986f+ , 0x79711faa+ ]
+ test/Test/Data/SipHash.hs view
@@ -0,0 +1,182 @@+{- | Reference SipHash-2-4 vectors.++The values are the reference implementation's output words, i.e. the+little-endian reading of the byte arrays in+<https://github.com/veorq/SipHash/blob/master/vectors.h>. The key bytes+are @00 01 .. 0f@.+-}+module Test.Data.SipHash where++import qualified Data.ByteString as BS+import Data.Char (chr)+import Data.String (IsString, fromString)+import Data.WideWord.Word128 (Word128)+import Data.Word (Word64)++key :: Word128+key = 0x000102030405060708090a0b0c0d0e0f++inputs :: (IsString a, Monoid a) => [a]+inputs = fmap (\n -> fromString $ fmap chr [0 .. n - 1]) [0 .. 64 - 1]++-- | Inputs around the 256-byte length-byte wrap (254-513 bytes).+boundaryInputs :: [BS.ByteString]+boundaryInputs = [BS.replicate n 97 | n <- [254, 255, 256, 257, 258, 511, 512, 513]]++{- | SipHash-2-4-64 reference output words for the empty input and the+prefixes of @00 01 ..@.+-}+sipHash24VectorsForWord64 :: [Word64]+sipHash24VectorsForWord64 =+ [ 0x726fdb47dd0e0e31+ , 0x74f839c593dc67fd+ , 0x0d6c8009d9a94f5a+ , 0x85676696d7fb7e2d+ , 0xcf2794e0277187b7+ , 0x18765564cd99a68d+ , 0xcbc9466e58fee3ce+ , 0xab0200f58b01d137+ , 0x93f5f5799a932462+ , 0x9e0082df0ba9e4b0+ , 0x7a5dbbc594ddb9f3+ , 0xf4b32f46226bada7+ , 0x751e8fbc860ee5fb+ , 0x14ea5627c0843d90+ , 0xf723ca908e7af2ee+ , 0xa129ca6149be45e5+ , 0x3f2acc7f57c29bdb+ , 0x699ae9f52cbe4794+ , 0x4bc1b3f0968dd39c+ , 0xbb6dc91da77961bd+ , 0xbed65cf21aa2ee98+ , 0xd0f2cbb02e3b67c7+ , 0x93536795e3a33e88+ , 0xa80c038ccd5ccec8+ , 0xb8ad50c6f649af94+ , 0xbce192de8a85b8ea+ , 0x17d835b85bbb15f3+ , 0x2f2e6163076bcfad+ , 0xde4daaaca71dc9a5+ , 0xa6a2506687956571+ , 0xad87a3535c49ef28+ , 0x32d892fad841c342+ , 0x7127512f72f27cce+ , 0xa7f32346f95978e3+ , 0x12e0b01abb051238+ , 0x15e034d40fa197ae+ , 0x314dffbe0815a3b4+ , 0x027990f029623981+ , 0xcadcd4e59ef40c4d+ , 0x9abfd8766a33735c+ , 0x0e3ea96b5304a7d0+ , 0xad0c42d6fc585992+ , 0x187306c89bc215a9+ , 0xd4a60abcf3792b95+ , 0xf935451de4f21df2+ , 0xa9538f0419755787+ , 0xdb9acddff56ca510+ , 0xd06c98cd5c0975eb+ , 0xe612a3cb9ecba951+ , 0xc766e62cfcadaf96+ , 0xee64435a9752fe72+ , 0xa192d576b245165a+ , 0x0a8787bf8ecb74b2+ , 0x81b3e73d20b49b6f+ , 0x7fa8220ba3b2ecea+ , 0x245731c13ca42499+ , 0xb78dbfaf3a8d83bd+ , 0xea1ad565322a1a0b+ , 0x60e61c23a3795013+ , 0x6606d7e446282b93+ , 0x6ca4ecb15c5f91e1+ , 0x9f626da15c9625f3+ , 0xe51b38608ef25f57+ , 0x958a324ceb064572+ ]++{- | SipHash-2-4-128 reference output words. Each result is the+little-endian reading of a 16-byte @vectors_sip128@ entry: the first+64-bit output word is the low half and the second is the high half.+-}+sipHash24VectorsForWord128 :: [Word128]+sipHash24VectorsForWord128 =+ [ 0x930255c71472f66de6a825ba047f81a3+ , 0x45fc229b1159763444af996bd8c187da+ , 0xe4ff0af6de8ba3fcc75da4a48d227781+ , 0x51ed8529b0b6335f4ea967520cb6709c+ , 0x7955cd7b7c6e0f7daf8f9c2dc16481f8+ , 0x27960e69077a5254886f778059876813+ , 0x5ea1d78f30a05e481386208b33caee14+ , 0x3982f01fa64ab8c053c1dbd8beebf1a1+ , 0xb49714f364e2830f61f55862baa9623b+ , 0xed716dbb028b7fc4abbad90a06994426+ , 0xbafbd0f3d34754c956691478c30d1100+ , 0x18dce5816fdcb4a277666b3868c55101+ , 0x25c13285f64d638258f35e9066b226d6+ , 0xf752b9c44f9329d0108bc0e947e26998+ , 0x024949e45f48c77e9cded766aceffc31+ , 0xd9c3cf970fec087e11a8b03399e99354+ , 0x77052385bf1533fdbb54b067caa4e26e+ , 0x4077e47ac466c05498b88d73e8063d47+ , 0x23f7aefe81a44d298548bf23e4e526a4+ , 0xb12e51528920d574b0fa65cf31770178+ , 0xeb3938e8a544933e7390223f83fc259e+ , 0x121d073ecd14228a215a52be5a498e56+ , 0xae0aff8e52109c469a6bd15245b5294a+ , 0x1c69bf9a9ae28ccfe0f5a9d5dd84d1c9+ , 0xad32618a178a2a88d850bd78ae79b42d+ , 0x6f8f8dcbeab951507b445e2d045fce8e+ , 0x661f147886e0ae7ee807c3b3b4530b9c+ , 0x94eb9e122febd3bfe4eaa669af48f2ab+ , 0xf4ae587302f335b9884b576816da6406+ , 0xb76a7c463cfdd40ce97d33bfc49d4baa+ , 0x87226d68d4d71a2bde6baf1f477f5cea+ , 0x353dc4524fde2317fcfa233218b03929+ , 0x68eb4665559d3e363efcea5eca56397c+ , 0xcfffa94e5f9db6b6321cf0467107c677+ , 0xde549b30f1f02509df7e84b86c98a637+ , 0xc88c3c922e1a2407f9a8a99de6f005a7+ , 0x11674f90ed769e1e4648c4291f7dc43d+ , 0x2b69d3c551473c0d1a0efce601bf620d+ , 0xb5e7be4b085efde49e667cca8b46038c+ , 0xd92bd2d0e5cc73449c2caf3bb95b8a52+ , 0xd83b91c6c80cae97ad5dc9951e306adf+ , 0xdbb6705e289135e7397f852c90891180+ , 0x5b0ccacc34ae5036bb31c2c96a3417e6+ , 0x89df5aecdc211840aa21b7ef3734d927+ , 0x4273cc66b1c9b1d8785e9ced9d7d2389+ , 0x4cb150a294fa8911657d5ebf91806d4a+ , 0x022949cf3d0efc3f89aee75560f9330e+ , 0x1b1563dc4bd8c88ed1190b722b431ce6+ , 0x169b2608a6559037cf82f749f5aee5f7+ , 0x03641a20adf237a84fa5b7d00f038d43+ , 0x3f4286f2270d7e24e304bf4feed390a5+ , 0x38f5f9ae7cd35cb1c493fe72a1c1e25f+ , 0x7c013a8bd03d13b26eb306bd5c32972c+ , 0x9ed32a009f65f09f94ca6b7a2214c892+ , 0x871d91d64108d5fb8c32d80b1150e8dc+ , 0xda832592b52be3481279dac78449f167+ , 0x362a1da96f16947ee94ed572cff23819+ , 0x8e6904163024620ffe49ed46961e4874+ , 0x1d8a3d58d0386400d8d6a998dea5fc57+ , 0x595357d9743676d4be1cdcef1cdeec9f+ , 0x40e772d8cb73ca6653f128eb000c04e3+ , 0x7a0f6793591ca9ccfe1d836a9a009776+ , 0xbd5947f0a447d505a067f52123545358+ , 0x7cbd3f979a063e504a83502f77d15051+ ]++{- | Reference SipHash-2-4-64 output words for 'boundaryInputs'. The+values use the same byte order as 'sipHash24VectorsForWord64'.+-}+boundaryVectorsForWord64 :: [Word64]+boundaryVectorsForWord64 =+ [ 0x0028c1ded1b851e5+ , 0xe987ca4ff9f8404d+ , 0x03413138de48340e+ , 0xa5d0d8d2d9378001+ , 0xde306f78d586b010+ , 0xb2b283a137aa8552+ , 0x9cb7322fb06c14a2+ , 0xbad61d3a1333d25b+ ]