module GaloisFieldTests where import Protolude import GaloisField import Test.Tasty import Test.Tasty.QuickCheck associativity :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool associativity op x y z = op x (op y z) == op (op x y) z commutativity :: Eq a => (a -> a -> a) -> a -> a -> Bool commutativity op x y = op x y == op y x distributivity :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool distributivity op op' x y z = op (op' x y) z == op' (op x z) (op y z) && op x (op' y z) == op' (op x y) (op x z) identities :: Eq a => (a -> a -> a) -> a -> a -> Bool identities op e x = op x e == x && op e x == x inverses :: Eq a => (a -> a -> a) -> (a -> a) -> a -> a -> Bool inverses op inv e x = op x (inv x) == e && op (inv x) x == e fieldAxioms :: forall k . GaloisField k => k -> TestTree fieldAxioms _ = testGroup ("Field axioms") [ testProperty "commutativity of addition" $ commutativity ((+) :: k -> k -> k) , testProperty "commutativity of multiplication" $ commutativity ((*) :: k -> k -> k) , testProperty "associativity of addition" $ associativity ((+) :: k -> k -> k) , testProperty "associativity of multiplication" $ associativity ((*) :: k -> k -> k) , testProperty "distributivity of multiplication over addition" $ distributivity ((*) :: k -> k -> k) (+) , testProperty "additive identity" $ identities ((+) :: k -> k -> k) 0 , testProperty "multiplicative identity" $ identities ((*) :: k -> k -> k) 1 , testProperty "additive inverses" $ inverses ((+) :: k -> k -> k) negate 0 , testProperty "multiplicative inverses" $ \x -> x /= 0 ==> inverses ((*) :: k -> k -> k) recip 1 x ] squareRoots :: forall k . GaloisField k => k -> TestTree squareRoots _ = testGroup "Square roots" [ testProperty "squares of square roots" $ \(x :: k) -> isJust (sr x) ==> (((^ (2 :: Int)) <$> sr x) == Just x) ] quadraticEquations :: forall k . GaloisField k => k -> TestTree quadraticEquations _ = testGroup "Quadratic equations" [ testProperty "solutions of quadratic equations" $ \(a :: k) (b :: k) (c :: k) -> a /= 0 && b /= 0 && isJust (quad a b c) ==> (((\x -> a * x * x + b * x + c) <$> quad a b c) == Just 0) ] test :: forall k . GaloisField k => TestName -> k -> TestTree test s x = testGroup s [fieldAxioms x, squareRoots x, quadraticEquations x] testEF :: forall k . GaloisField k => TestName -> k -> TestTree testEF s x = testGroup s [fieldAxioms x] testBF :: forall k . GaloisField k => TestName -> k -> TestTree testBF s x = testGroup s [fieldAxioms x]