module Group.Field
( module Group
, module Group.Field
) where
import Protolude
import Control.Monad.Random (Random(..))
import GaloisField (GaloisField(..))
import Test.Tasty.QuickCheck (Arbitrary(..))
import Text.PrettyPrint.Leijen.Text (Pretty(..))
import Curve (PrimeField')
import Group (Group(..))
-------------------------------------------------------------------------------
-- Types
-------------------------------------------------------------------------------
-- | Field groups.
class (GaloisField q, PrimeField' r) => FGroup r q where
{-# MINIMAL g_, h_, q_, r_ #-}
g_ :: Element r q -- ^ Group generator.
h_ :: Element r q -> Integer -- ^ Group cofactor.
q_ :: Element r q -> Integer -- ^ Group characteristic.
r_ :: Element r q -> Integer -- ^ Group order.
-- | Field elements.
newtype Element r q = F q
deriving (Eq, Functor, Generic, NFData, Read, Show)
-------------------------------------------------------------------------------
-- Operations
-------------------------------------------------------------------------------
-- Field elements are groups.
instance FGroup r q => Group (Element r q) where
add = (<>)
{-# INLINABLE add #-}
dbl = join (<>)
{-# INLINABLE dbl #-}
def (F x) = x /= 0
{-# INLINABLE def #-}
gen = g_
{-# INLINABLE gen #-}
id = mempty
{-# INLINABLE id #-}
inv = (<$>) recip
{-# INLINABLE inv #-}
mul' = (. flip pow) . flip (<$>)
{-# INLINABLE mul' #-}
order = r_
{-# INLINABLE order #-}
-- Field elements are monoids.
instance FGroup r q => Monoid (Element r q) where
mempty = F 1
{-# INLINABLE mempty #-}
-- Field elements are semigroups.
instance FGroup r q => Semigroup (Element r q) where
F x <> F y = F (x * y)
{-# INLINABLE (<>) #-}
-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------
-- Field elements are arbitrary.
instance FGroup r q => Arbitrary (Element r q) where
-- Arbitrary group element.
arbitrary = mul' gen <$> arbitrary
{- Arbitrary field element.
arbitrary = suchThatMap arbitrary defX
where
defX 0 = Nothing
defX x = Just (F x)
-}
{-# INLINABLE arbitrary #-}
-- Field elements are pretty.
instance FGroup r q => Pretty (Element r q) where
pretty (F x) = pretty x
-- Field elements are random.
instance FGroup r q => Random (Element r q) where
-- Random group element.
random = first (mul' gen) . random
{- Random field element.
random g = case random g of
(0, g') -> random g'
(x, g') -> (F x, g')
-}
{-# INLINABLE random #-}
randomR = panic "not implemented."