module Group
( Group(..)
) where
import Protolude
import Control.Monad.Random (MonadRandom, Random, getRandom)
import Test.Tasty.QuickCheck (Arbitrary)
import Text.PrettyPrint.Leijen.Text (Pretty)
-------------------------------------------------------------------------------
-- Types
-------------------------------------------------------------------------------
-- | Groups.
class (Arbitrary g, Eq g, Generic g,
Monoid g, Pretty g, Random g, Show g) => Group g where
{-# MINIMAL add, dbl, def, gen, id, inv, order #-}
-- | Element addition.
add :: g -> g -> g
-- | Element doubling.
dbl :: g -> g
-- | Check well-defined.
def :: g -> Bool
-- | Group generator.
gen :: g
-- | Identity element.
id :: g
-- | Element inversion.
inv :: g -> g
-- | Element multiplication.
mul' :: g -> Integer -> g
mul' p n
| n < 0 = inv (mul' p (-n))
| n == 0 = id
| n == 1 = p
| even n = p'
| otherwise = add p p'
where
p' = mul' (dbl p) (div n 2)
{-# INLINABLE mul' #-}
-- | Curve order.
order :: g -> Integer
-- | Random element.
rnd :: MonadRandom m => m g
rnd = getRandom
{-# INLINABLE rnd #-}