{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module WideWord where
import Data.Word
import Data.Bits
import Data.WideWord.Int128
import Data.WideWord.Word128
import Criterion.Main
import Data.Vector.Unboxed ( Vector, Unbox )
import Data.Vector.Unboxed.Deriving
import qualified Data.Vector.Unboxed as U
-- This is the easiest to implement, but not entirely correct; we should keep
-- the structure packed in memory so that the hi and lo words are adjacent. I'll
-- leave @erikd to implement that though...
derivingUnbox "Word128"
[t| Word128 -> (Word64, Word64) |]
[| \(Word128 hi lo) -> (hi,lo) |]
[| \(hi,lo) -> Word128 hi lo |]
derivingUnbox "Int128"
[t| Int128 -> (Word64, Word64) |]
[| \(Int128 hi lo) -> (hi,lo) |]
[| \(hi,lo) -> Int128 hi lo |]
benchmark
:: Vector Word64
-> Vector Word64
-> Vector Word64
-> Vector Word64
-> Vector Int
-> Benchmark
benchmark !xhi !xlo !yhi !ylo !ss =
bgroup "WideWord"
[ mkBench "Word128" Word128 xhi xlo yhi ylo ss
, mkBench "Int128" Int128 xhi xlo yhi ylo ss
]
mkBench
:: (Unbox t, Eq t, Ord t, Num t, Integral t, Bits t, FiniteBits t)
=> String
-> (Word64 -> Word64 -> t)
-> Vector Word64
-> Vector Word64
-> Vector Word64
-> Vector Word64
-> Vector Int
-> Benchmark
mkBench ty con xhi xlo yhi ylo ss =
let
xs = U.zipWith con xhi xlo
ys = U.zipWith con yhi ylo
ss' = U.map abs ss
in
bgroup ty
[ bgroup "Eq"
[ bench "(==)" $ nf (U.zipWith (==) xs) ys
, bench "(/=)" $ nf (U.zipWith (/=) xs) ys
]
, bgroup "Ord"
[ bench "(>=)" $ nf (U.zipWith (>=) xs) ys
, bench "(<=)" $ nf (U.zipWith (<=) xs) ys
, bench "(>)" $ nf (U.zipWith (>) xs) ys
, bench "(<)" $ nf (U.zipWith (<) xs) ys
]
, bgroup "Num"
[ bench "(+)" $ nf (U.zipWith (+) xs) ys
, bench "(-)" $ nf (U.zipWith (-) xs) ys
, bench "(*)" $ nf (U.zipWith (*) xs) ys
, bench "negate" $ nf (U.map negate) xs
, bench "abs" $ nf (U.map abs) ys
, bench "signum" $ nf (U.map signum) xs
]
, bgroup "Integral"
[ bench "quot" $ nf (U.zipWith quot xs) ys
, bench "rem" $ nf (U.zipWith rem xs) ys
, bench "quotRem" $ nf (U.zipWith quotRem xs) ys
, bench "div" $ nf (U.zipWith div xs) ys
, bench "mod" $ nf (U.zipWith mod xs) ys
, bench "divMod" $ nf (U.zipWith divMod xs) ys
]
, bgroup "Bits"
[ bench "(.&.)" $ nf (U.zipWith (.&.) xs) ys
, bench "(.|.)" $ nf (U.zipWith (.|.) xs) ys
, bench "xor" $ nf (U.zipWith xor xs) ys
, bench "complement" $ nf (U.map complement) xs
, bench "shift" $ nf (U.zipWith shift xs) ss
, bench "rotate" $ nf (U.zipWith rotate ys) ss
, bench "setBit" $ nf (U.zipWith setBit xs) ss'
, bench "clearBit" $ nf (U.zipWith clearBit ys) ss'
, bench "complementBit" $ nf (U.zipWith complementBit xs) ss'
, bench "testBit" $ nf (U.zipWith testBit ys) ss'
, bench "popCount" $ nf (U.map popCount) xs
]
, bgroup "FiniteBits"
[ bench "countLeadingZeros" $ nf (U.map countLeadingZeros) xs
, bench "countTrailingZeros" $ nf (U.map countTrailingZeros) ys
]
]