{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module TestUtils ( ShortPoly(..) , tenTimesLess , mySemiringLaws , myRingLaws , myNumLaws , myGcdDomainLaws , myEuclideanLaws , myIsListLaws , myShowLaws ) where import Prelude hiding (lcm, rem) import Control.Arrow import Data.Euclidean import Data.Finite import Data.Mod.Word import Data.Proxy import Data.Semiring (Semiring(..), Ring) import qualified Data.Vector.Generic as G import qualified Data.Vector.Generic.Sized as SG import qualified Data.Vector.Unboxed.Sized as SU import GHC.Exts import GHC.TypeNats (KnownNat) import Test.QuickCheck.Classes import Test.Tasty import Test.Tasty.QuickCheck import qualified Data.Poly.Semiring as Dense import qualified Data.Poly.Laurent as DenseLaurent import Data.Poly.Multi.Semiring import qualified Data.Poly.Multi.Laurent as MultiLaurent newtype ShortPoly a = ShortPoly { unShortPoly :: a } deriving (Eq, Show, Semiring, GcdDomain, Euclidean, Num) instance KnownNat m => Arbitrary (Mod m) where arbitrary = oneof [arbitraryBoundedEnum, fromInteger <$> arbitrary] shrink = map fromInteger . shrink . toInteger . unMod instance KnownNat n => Arbitrary (Finite n) where arbitrary = elements finites instance (Arbitrary a, KnownNat n, G.Vector v a) => Arbitrary (SG.Vector v n a) where arbitrary = SG.replicateM arbitrary shrink vs = [ vs SG.// [(i, x)] | i <- finites, x <- shrink (SG.index vs i) ] instance (Eq a, Semiring a, Arbitrary a, G.Vector v a) => Arbitrary (Dense.Poly v a) where arbitrary = Dense.toPoly . G.fromList <$> arbitrary shrink = fmap (Dense.toPoly . G.fromList) . shrink . G.toList . Dense.unPoly instance (Eq a, Semiring a, Arbitrary a, G.Vector v a) => Arbitrary (ShortPoly (Dense.Poly v a)) where arbitrary = ShortPoly . Dense.toPoly . G.fromList . (\xs -> take (length xs `mod` 10) xs) <$> arbitrary shrink = fmap (ShortPoly . Dense.toPoly . G.fromList) . shrink . G.toList . Dense.unPoly . unShortPoly instance (Eq a, Semiring a, Arbitrary a, G.Vector v a) => Arbitrary (DenseLaurent.Laurent v a) where arbitrary = DenseLaurent.toLaurent <$> ((`rem` 10) <$> arbitrary) <*> arbitrary shrink = fmap (uncurry DenseLaurent.toLaurent) . shrink . DenseLaurent.unLaurent instance (Eq a, Semiring a, Arbitrary a, G.Vector v a) => Arbitrary (ShortPoly (DenseLaurent.Laurent v a)) where arbitrary = (ShortPoly .) . DenseLaurent.toLaurent <$> ((`rem` 10) <$> arbitrary) <*> (unShortPoly <$> arbitrary) shrink = fmap (ShortPoly . uncurry DenseLaurent.toLaurent . fmap unShortPoly) . shrink . fmap ShortPoly . DenseLaurent.unLaurent . unShortPoly instance (Eq a, Semiring a, Arbitrary a, KnownNat n, G.Vector v (SU.Vector n Word, a)) => Arbitrary (MultiPoly v n a) where arbitrary = toMultiPoly . G.fromList <$> arbitrary shrink = fmap (toMultiPoly . G.fromList) . shrink . G.toList . unMultiPoly instance (Eq a, Semiring a, Arbitrary a, KnownNat n, G.Vector v (SU.Vector n Word, a)) => Arbitrary (ShortPoly (MultiPoly v n a)) where arbitrary = ShortPoly . toMultiPoly . G.fromList . (\xs -> take (length xs `mod` 4) (map (first (SU.map (`mod` 3))) xs)) <$> arbitrary shrink = fmap (ShortPoly . toMultiPoly . G.fromList) . shrink . G.toList . unMultiPoly . unShortPoly instance (Eq a, Semiring a, Arbitrary a, KnownNat n, G.Vector v (Word, a), G.Vector v (SU.Vector n Word, a)) => Arbitrary (MultiLaurent.MultiLaurent v n a) where arbitrary = MultiLaurent.toMultiLaurent <$> (SU.map (`rem` 10) <$> arbitrary) <*> arbitrary shrink = fmap (uncurry MultiLaurent.toMultiLaurent) . shrink . MultiLaurent.unMultiLaurent instance (Eq a, Semiring a, Arbitrary a, KnownNat n, G.Vector v (Word, a), G.Vector v (SU.Vector n Word, a)) => Arbitrary (ShortPoly (MultiLaurent.MultiLaurent v n a)) where arbitrary = (ShortPoly .) . MultiLaurent.toMultiLaurent <$> (SU.map (`rem` 10) <$> arbitrary) <*> (unShortPoly <$> arbitrary) shrink = fmap (ShortPoly . uncurry MultiLaurent.toMultiLaurent . fmap unShortPoly) . shrink . fmap ShortPoly . MultiLaurent.unMultiLaurent . unShortPoly ------------------------------------------------------------------------------- tenTimesLess :: TestTree -> TestTree tenTimesLess = adjustOption $ \(QuickCheckTests n) -> QuickCheckTests (max 100 (n `div` 10)) mySemiringLaws :: (Eq a, Semiring a, Arbitrary a, Show a) => Proxy a -> TestTree mySemiringLaws proxy = testGroup tpclss $ map tune props where Laws tpclss props = semiringLaws proxy tune pair = case fst pair of "Multiplicative Associativity" -> tenTimesLess test "Multiplication Left Distributes Over Addition" -> tenTimesLess test "Multiplication Right Distributes Over Addition" -> tenTimesLess test _ -> test where test = uncurry testProperty pair myRingLaws :: (Eq a, Ring a, Arbitrary a, Show a) => Proxy a -> TestTree myRingLaws proxy = testGroup tpclss $ map (uncurry testProperty) props where Laws tpclss props = ringLaws proxy myNumLaws :: (Eq a, Num a, Arbitrary a, Show a) => Proxy a -> TestTree myNumLaws proxy = testGroup tpclss $ map tune props where Laws tpclss props = numLaws proxy tune pair = case fst pair of "Multiplicative Associativity" -> tenTimesLess test "Multiplication Left Distributes Over Addition" -> tenTimesLess test "Multiplication Right Distributes Over Addition" -> tenTimesLess test "Subtraction" -> tenTimesLess test _ -> test where test = uncurry testProperty pair myGcdDomainLaws :: forall a. (Eq a, GcdDomain a, Arbitrary a, Show a) => Proxy a -> TestTree myGcdDomainLaws proxy = testGroup tpclss $ map tune $ lcm0 : props where Laws tpclss props = gcdDomainLaws proxy tune pair = case fst pair of "gcd1" -> tenTimesLess $ tenTimesLess test "gcd2" -> tenTimesLess $ tenTimesLess test "lcm1" -> tenTimesLess $ tenTimesLess $ tenTimesLess test "lcm2" -> tenTimesLess test "coprime" -> tenTimesLess $ tenTimesLess test _ -> test where test = uncurry testProperty pair lcm0 = ("lcm0", property $ \(x :: a) -> lcm x zero === zero .&&. lcm zero x === zero) myEuclideanLaws :: (Eq a, Euclidean a, Arbitrary a, Show a) => Proxy a -> TestTree myEuclideanLaws proxy = testGroup tpclss $ map (uncurry testProperty) props where Laws tpclss props = euclideanLaws proxy myIsListLaws :: (Eq a, IsList a, Arbitrary a, Show a, Show (Item a), Arbitrary (Item a)) => Proxy a -> TestTree myIsListLaws proxy = testGroup tpclss $ map (uncurry testProperty) props where Laws tpclss props = isListLaws proxy myShowLaws :: (Eq a, Arbitrary a, Show a) => Proxy a -> TestTree myShowLaws proxy = testGroup tpclss $ map tune props where Laws tpclss props = showLaws proxy tune pair = case fst pair of "Equivariance: showList" -> tenTimesLess $ tenTimesLess test _ -> test where test = uncurry testProperty pair