abcBridge-0.15: tests/Tests/Operations.hs
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE CPP #-}
module Tests.Operations
( op_tests
) where
import qualified Data.AIG as AIG
import Test.Tasty
import Test.QuickCheck
import Test.Tasty.QuickCheck
#if MIN_VERSION_base(4,8,0)
import qualified Data.Bits as Bits
#endif
bv :: AIG.IsAIG l g => g s -> Int -> Integer -> AIG.BV (l s)
bv = AIG.bvFromInteger
bin_test :: String
-> AIG.Proxy l g
-- ^ Proxy
-> (forall s . g s -> AIG.BV (l s) -> AIG.BV (l s) -> IO (AIG.BV (l s)))
-- ^ Bitvector operation
-> (Integer -> Integer -> Integer)
-- ^ Concrete op
-> TestTree
bin_test nm proxy@(AIG.Proxy f) bv_op c_op = f $
testProperty nm $ \u v -> ioProperty $ do
let w = 10
AIG.SomeGraph g <- AIG.newGraph proxy
z <- bv_op g (bv g w u) (bv g w v)
let expected = (c_op (u `mod` (2^w)) (v `mod` (2^w))) `mod` (2^w)
return $ Just expected == AIG.asUnsigned g z
unary_test :: String
-> AIG.Proxy l g
-- ^ Proxy
-> (forall s . g s -> AIG.BV (l s) -> IO (AIG.BV (l s)))
-- ^ Bitvector operation
-> (Integer -> Integer)
-- ^ Concrete op
-> TestTree
unary_test nm proxy@(AIG.Proxy f) bv_op c_op = f $
testProperty nm $ \u -> ioProperty $ do
let w = 10
AIG.SomeGraph g <- AIG.newGraph proxy
z <- bv_op g (bv g w u)
let expected = (c_op (u `mod` (2^w))) `mod` (2^w)
return $ Just expected == AIG.asUnsigned g z
-- reference implementations of lg2 and lg2_up
lg2 :: Integer -> Integer
lg2 = go 0
where go i x
| x <= 0 = -1
| x == 1 = i
| otherwise = go (i+1) (x `div` 2)
lg2_up :: Int -> Integer -> Integer
lg2_up w 0 = toInteger w
lg2_up _ x = lg2 (x-1) + 1
test_lg2_down :: AIG.Proxy l g
-- ^ Proxy
-> TestTree
test_lg2_down proxy@(AIG.Proxy f) = f $
testProperty "test_lg2_down" $ \(w0::Int) u0 -> ioProperty $ do
let w = ((abs w0) + 1)
let u' = (abs u0)
AIG.SomeGraph g <- AIG.newGraph proxy
z <- AIG.logBase2_down g (bv g w u')
let expected = (lg2 (u' `mod` (2^w))) `mod` (2^w)
return $ Just expected == AIG.asUnsigned g z
test_lg2_up :: AIG.Proxy l g
-- ^ Proxy
-> TestTree
test_lg2_up proxy@(AIG.Proxy f) = f $
testProperty "test_lg2_up" $ \(w0::Int) u0 -> ioProperty $ do
let w = ((abs w0) + 1)
let u' = (abs u0)
AIG.SomeGraph g <- AIG.newGraph proxy
z <- AIG.logBase2_up g (bv g w u')
let expected = (lg2_up w (u' `mod` (2^w))) `mod` (2^w)
return $ Just expected == AIG.asUnsigned g z
#if MIN_VERSION_base(4,8,0)
test_clz :: AIG.Proxy l g
-- ^ Proxy
-> TestTree
test_clz proxy@(AIG.Proxy f) = f $
testProperty "test_clz" $ \(u::Int) -> ioProperty $ do
let w = Bits.finiteBitSize u
AIG.SomeGraph g <- AIG.newGraph proxy
z <- AIG.countLeadingZeros g (bv g w (toInteger u))
let expected = toInteger $ Bits.countLeadingZeros u
return $ Just expected == AIG.asUnsigned g z
test_ctz :: AIG.Proxy l g
-- ^ Proxy
-> TestTree
test_ctz proxy@(AIG.Proxy f) = f $
testProperty "test_ctz" $ \(u::Int) -> ioProperty $ do
let w = Bits.finiteBitSize u
AIG.SomeGraph g <- AIG.newGraph proxy
z <- AIG.countTrailingZeros g (bv g w (toInteger u))
let expected = toInteger $ Bits.countTrailingZeros u
return $ Just expected == AIG.asUnsigned g z
#endif
op_tests :: AIG.Proxy l g -> [TestTree]
op_tests proxy@(AIG.Proxy f) = f $
[ testProperty "test_bv" $ \u -> ioProperty $ do
AIG.SomeGraph g <- AIG.newGraph proxy
let w = 10
let z = (bv g w u)
let expected = u `mod` (2^w)
return $ Just expected == AIG.asUnsigned g z
, bin_test "test_add" proxy AIG.add (+)
, bin_test "test_sub" proxy AIG.sub (-)
, bin_test "test_mul" proxy AIG.mul (*)
, unary_test "test_neg" proxy AIG.neg negate
, test_lg2_down proxy
, test_lg2_up proxy
#if MIN_VERSION_base(4,8,0)
, test_clz proxy
, test_ctz proxy
#endif
]