packages feed

galois-field-0.4.0: tests/GaloisFieldTests.hs

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 _ = localOption (QuickCheckTests 10) $ testGroup "Square roots"
  [ testProperty "squares of square roots"
    $ \(x :: k) -> isJust (sr x)
      ==> (((^ (2 :: Int)) <$> sr x) == Just x)
  , 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]

test' :: forall k . GaloisField k => TestName -> k -> TestTree
test' s x = testGroup s [fieldAxioms x]