{-# LANGUAGE NegativeLiterals #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-} {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-} {-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-} module Clash.Tests.FixedExhaustive (tests) where import Data.Proxy (Proxy(..)) import Data.Typeable (typeRep) import Test.Tasty import Test.Tasty.HUnit import Clash.Sized.Fixed (Fixed(..), FracFixedC, SFixed, UFixed) listsEqual :: forall f rep int frac . ( FracFixedC rep int frac , f ~ Fixed rep int frac ) => String -> [f] -> [Rational] -> Assertion listsEqual prefix fs0 rs0 = do let limit = 1000 minVal = toRational $ minBound @f maxVal = toRational $ maxBound @f fs = take limit (map toRational fs0) rs = take limit $ takeWhile (\r -> r >= minVal && r <= maxVal) rs0 assertBool (prefix ++ "length rs > maxLength") (length rs < limit) assertBool (prefix ++ show fs ++ "\n/=\n" ++ show rs) (fs == rs) forAllEnumFrom :: forall f rep int frac . ( FracFixedC rep int frac , f ~ Fixed rep int frac ) => Proxy f -> Assertion forAllEnumFrom Proxy = sequence_ [ listsEqual ("x1 = Fixed " ++ show (toInteger $ unFixed x1)) (enumFrom x1) (enumFrom (toRational x1)) | x1 :: f <- map Fixed [minBound..]] forAllEnumFromThen :: forall f rep int frac . ( FracFixedC rep int frac , f ~ Fixed rep int frac ) => Proxy f -> Assertion forAllEnumFromThen Proxy = sequence_ [ let fs = enumFromThen x1 x2 rs = enumFromThen (toRational x1) (toRational x2) prefix = unlines [ "x1 = Fixed " ++ show (toInteger $ unFixed x1) , "x2 = Fixed " ++ show (toInteger $ unFixed x2)] in if (x1 == x2) then listsEqual prefix (take 10 fs) (take 10 rs) else listsEqual prefix fs rs | x1 :: f <- map Fixed [minBound..] , x2 <- map Fixed [minBound..]] forAllEnumFromTo :: forall f rep int frac . ( FracFixedC rep int frac , f ~ Fixed rep int frac ) => Proxy f -> Assertion forAllEnumFromTo Proxy = sequence_ [ listsEqual (unlines [ "x1 = Fixed " ++ show (toInteger $ unFixed x1) , "y = Fixed " ++ show (toInteger $ unFixed y)]) (enumFromTo x1 y) (enumFromTo (toRational x1) (toRational y)) | x1 :: f <- map Fixed [minBound..] , y <- map Fixed [minBound..]] forAllEnumFromThenTo :: forall f rep int frac . ( FracFixedC rep int frac , f ~ Fixed rep int frac ) => Proxy f -> Assertion forAllEnumFromThenTo Proxy = sequence_ [ let fs = enumFromThenTo x1 x2 y rs = enumFromThenTo (toRational x1) (toRational x2) (toRational y) prefix = unlines [ "x1 = Fixed " ++ show (toInteger $ unFixed x1) , "x2 = Fixed " ++ show (toInteger $ unFixed x2) , "y = Fixed " ++ show (toInteger $ unFixed y)] in if (x1 == x2) then listsEqual prefix (take 10 fs) (take 10 rs) else listsEqual prefix fs rs | x1 :: f <- map Fixed [minBound..] , x2 <- map Fixed [minBound..] , y <- map Fixed [minBound..]] enumTests :: forall f rep int frac . ( FracFixedC rep int frac , f ~ Fixed rep int frac ) => Proxy f -> TestTree enumTests pf = testGroup (show $ typeRep pf) [ testCase "enumFrom" $ forAllEnumFrom pf , testCase "enumFromThen" $ forAllEnumFromThen pf , testCase "enumFromTo" $ forAllEnumFromTo pf , testCase "enumFromThenTo" $ forAllEnumFromThenTo pf ] tests :: TestTree tests = testGroup "FixedExhaustive" [ enumTests (Proxy @(SFixed 0 0)) , enumTests (Proxy @(SFixed 0 1)) , enumTests (Proxy @(SFixed 1 0)) , enumTests (Proxy @(SFixed 0 2)) , enumTests (Proxy @(SFixed 1 1)) , enumTests (Proxy @(SFixed 2 0)) , enumTests (Proxy @(SFixed 0 3)) , enumTests (Proxy @(SFixed 1 2)) , enumTests (Proxy @(SFixed 2 1)) , enumTests (Proxy @(SFixed 3 0)) , enumTests (Proxy @(SFixed 0 4)) , enumTests (Proxy @(SFixed 1 3)) , enumTests (Proxy @(SFixed 2 2)) , enumTests (Proxy @(SFixed 3 1)) , enumTests (Proxy @(SFixed 4 0)) , enumTests (Proxy @(UFixed 0 0)) , enumTests (Proxy @(UFixed 0 1)) , enumTests (Proxy @(UFixed 1 0)) , enumTests (Proxy @(UFixed 0 2)) , enumTests (Proxy @(UFixed 1 1)) , enumTests (Proxy @(UFixed 2 0)) , enumTests (Proxy @(UFixed 0 3)) , enumTests (Proxy @(UFixed 1 2)) , enumTests (Proxy @(UFixed 2 1)) , enumTests (Proxy @(UFixed 3 0)) , enumTests (Proxy @(UFixed 0 4)) , enumTests (Proxy @(UFixed 1 3)) , enumTests (Proxy @(UFixed 2 2)) , enumTests (Proxy @(UFixed 3 1)) , enumTests (Proxy @(UFixed 4 0)) ]