finite-field-0.10.0: test/TestPrimeField.hs
{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, GADTs, DataKinds, CPP, TypeOperators #-}
{-# OPTIONS_GHC -fcontext-stack=32 #-}
import Prelude hiding (toInteger)
import Test.Tasty
import Test.Tasty.QuickCheck
import Test.Tasty.HUnit
import Test.Tasty.TH
import qualified Test.QuickCheck.Monadic as QM
import Control.DeepSeq
import Control.Exception
import Control.Monad
import Data.Either
import Data.Hashable
import Data.List (genericLength)
import Data.Numbers.Primes (primes)
import Data.Proxy
import Data.Ratio
import Data.FiniteField
#ifdef UseGHCTypeLits
import Data.Maybe
import GHC.TypeLits
#else
import TypeLevel.Number.Nat
#endif
-- ----------------------------------------------------------------------
-- addition
prop_add_comm =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
forAll arbitrary $ \b ->
a + b == b + a
prop_add_assoc =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
forAll arbitrary $ \b ->
forAll arbitrary $ \c ->
(a + b) + c == a + (b + c)
prop_add_unitl =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
0 + a == a
prop_add_unitr =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
a + 0 == a
prop_negate =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
a + negate a == 0
prop_sub_negate =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
forAll arbitrary $ \(b :: PrimeField p) ->
a - b == a + negate b
-- ----------------------------------------------------------------------
-- multiplication
prop_mult_comm =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
forAll arbitrary $ \b ->
a * b == b * a
prop_mult_assoc =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
forAll arbitrary $ \b ->
forAll arbitrary $ \c ->
(a * b) * c == a * (b * c)
prop_mult_unitl =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
1 * a == a
prop_mult_unitr =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
a * 1 == a
prop_mult_zero_l =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
0*a == 0
prop_mult_zero_r =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
a*0 == 0
-- ----------------------------------------------------------------------
-- distributivity
prop_distl =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
forAll arbitrary $ \b ->
forAll arbitrary $ \c ->
a * (b + c) == a*b + a*c
prop_distr =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
forAll arbitrary $ \b ->
forAll arbitrary $ \c ->
(b + c) * a == b*a + c*a
-- ----------------------------------------------------------------------
-- misc Num methods
prop_abs =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
abs a == a
prop_signum =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
signum a == 1
-- ----------------------------------------------------------------------
-- Fractional
prop_fromRational =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(r :: Rational) ->
(fromRational r :: PrimeField p) == fromInteger (numerator r) / fromInteger (denominator r)
prop_recip =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
a /= 0 ==> a * (recip a) == 1
-- ----------------------------------------------------------------------
-- FiniteField
prop_pthRoot =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
pthRoot a ^ char a == a
prop_allValues = do
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
genericLength (allValues :: [PrimeField p]) == order (undefined :: PrimeField p)
-- ----------------------------------------------------------------------
-- Show / Read
prop_read_show =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
read (show a) == a
-- ----------------------------------------------------------------------
-- Ord
prop_zero_minimum =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
0 <= a
-- ----------------------------------------------------------------------
-- NFData
prop_rnf =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
rnf a == ()
-- ----------------------------------------------------------------------
-- Enum
prop_toEnum_fromEnum =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
toEnum (fromEnum a) == a
prop_toEnum_negative = QM.monadicIO $ do
SomeNat' (_ :: Proxy p) <- QM.pick smallPrimes
let a :: PrimeField p
a = toEnum (-1)
(ret :: Either SomeException (PrimeField p)) <- QM.run $ try $ evaluate $ a
QM.assert $ isLeft ret
-- https://github.com/msakai/finite-field/issues/2
case_toEnum_big_integer =
(toEnum 7 :: $(primeField (2^127 - 1))) @?= 7
-- ----------------------------------------------------------------------
prop_hash =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
hash a `seq` () == ()
-- ----------------------------------------------------------------------
-- misc
prop_fromInteger_toInteger =
forAll smallPrimes $ \(SomeNat' (_ :: Proxy p)) ->
forAll arbitrary $ \(a :: PrimeField p) ->
fromInteger (toInteger a) == a
case_primeFieldT = a @?= 1
where
a :: $(primeField 15485867)
a = 15485867 + 1
------------------------------------------------------------------------
#ifdef UseGHCTypeLits
data SomeNat' where
SomeNat' :: KnownNat p => Proxy p -> SomeNat'
instance Show SomeNat' where
showsPrec p (SomeNat' x) = showsPrec p (natVal x)
#else
data SomeNat' where
SomeNat' :: Nat p => Proxy p -> SomeNat'
instance Show SomeNat' where
showsPrec p (SomeNat' (x :: Proxy p)) = showsPrec p (toInt (undefined :: p))
#endif
smallPrimes :: Gen SomeNat'
smallPrimes = do
i <- choose (0, 2^(16::Int))
#ifdef UseGHCTypeLits
case fromJust $ someNatVal $ primes !! i of
SomeNat proxy -> return $ SomeNat' proxy
#else
let f :: forall p. Nat p => p -> SomeNat'
f _ = SomeNat' (Proxy :: Proxy p)
return $ withNat f (primes !! i)
#endif
#ifdef UseGHCTypeLits
instance KnownNat p => Arbitrary (PrimeField p) where
#else
instance Nat p => Arbitrary (PrimeField p) where
#endif
arbitrary = liftM fromInteger arbitrary
------------------------------------------------------------------------
-- Test harness
main :: IO ()
main = $(defaultMainGenerator)
#if !MIN_VERSION_base(4,7,0)
isLeft :: Either a b -> Bool
isLeft (Left _) = True
isLeft (Right _) = False
isRight :: Either a b -> Bool
isRight (Left _) = False
isRight (Right _) = True
#endif