packages feed

galois-field-0.2.1: tests/GaloisFieldTests.hs

module GaloisFieldTests where

import Protolude

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

ringAxioms :: forall r . (Arbitrary r, Eq r, Num r, Show r)
  => TestName -> r -> TestTree
ringAxioms s _ = testGroup ("Ring axioms of " <> s)
  [ testProperty "commutativity of addition"
    $ commutativity ((+) :: r -> r -> r)
  , testProperty "commutativity of multiplication"
    $ commutativity ((*) :: r -> r -> r)
  , testProperty "associativity of addition"
    $ associativity ((+) :: r -> r -> r)
  , testProperty "associativity of multiplication"
    $ associativity ((*) :: r -> r -> r)
  , testProperty "distributivity of multiplication over addition"
    $ distributivity ((*) :: r -> r -> r) (+)
  , testProperty "additive identity"
    $ identities ((+) :: r -> r -> r) 0
  , testProperty "multiplicative identity"
    $ identities ((*) :: r -> r -> r) 1
  , testProperty "additive inverses"
    $ inverses ((+) :: r -> r -> r) negate 0
  ]

fieldAxioms :: forall k . (Arbitrary k, Eq k, Fractional k, Show k)
  => TestName -> k -> TestTree
fieldAxioms s k = testGroup ("Field axioms of " <> s)
  [ ringAxioms s k
  , testProperty "multiplicative inverses"
    $ \n -> n /= 0 ==> inverses ((*) :: k -> k -> k) recip 1 n
  ]