module Data.Curve
(
Curve(..)
, mul
, mul'
, Form(..)
, Coordinates(..)
) where
import Protolude
import Control.Monad.Random (MonadRandom, Random(..), getRandom)
import Data.Field.Galois (GaloisField, PrimeField, fromP)
import Data.Group (Group(..))
import GHC.Natural (Natural)
import Test.Tasty.QuickCheck (Arbitrary(..))
import Text.PrettyPrint.Leijen.Text (Pretty)
class (GaloisField q, PrimeField r, Arbitrary (Point f c e q r),
Eq (Point f c e q r), Generic (Point f c e q r), Group (Point f c e q r),
NFData (Point f c e q r), Pretty (Point f c e q r), Random (Point f c e q r),
Show (Point f c e q r)) => Curve (f :: Form) (c :: Coordinates) e q r where
{-# MINIMAL add, char, cof, dbl, def, disc, frob, fromA, gen,
id, inv, order, point, pointX, toA, yX #-}
data family Point f c e q r :: *
char :: Point f c e q r -> Natural
cof :: Point f c e q r -> Natural
def :: Point f c e q r -> Bool
disc :: Point f c e q r -> q
order :: Point f c e q r -> Natural
add :: Point f c e q r -> Point f c e q r -> Point f c e q r
dbl :: Point f c e q r -> Point f c e q r
id :: Point f c e q r
inv :: Point f c e q r -> Point f c e q r
frob :: Point f c e q r -> Point f c e q r
fromA :: Curve f 'Affine e q r => Point f 'Affine e q r -> Point f c e q r
gen :: Point f c e q r
point :: q -> q -> Maybe (Point f c e q r)
pointX :: q -> Maybe (Point f c e q r)
rnd :: MonadRandom m => m (Point f c e q r)
rnd = getRandom
toA :: Curve f 'Affine e q r => Point f c e q r -> Point f 'Affine e q r
yX :: Point f c e q r -> q -> Maybe q
mul :: Curve f c e q r => Point f c e q r -> r -> Point f c e q r
mul = (. fromP) . mul'
{-# INLINABLE mul #-}
mul' :: (Curve f c e q r, Integral n) => Point f c e q r -> n -> Point f c e q r
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' #-}
{-# SPECIALISE mul' ::
Curve f c e q r => Point f c e q r -> Int -> Point f c e q r,
Curve f c e q r => Point f c e q r -> Integer -> Point f c e q r,
Curve f c e q r => Point f c e q r -> Natural -> Point f c e q r,
Curve f c e q r => Point f c e q r -> Word -> Point f c e q r
#-}
data Form = Binary
| Edwards
| Montgomery
| Weierstrass
data Coordinates = Affine
| Jacobian
| Projective
instance Curve f c e q r => Arbitrary (Point f c e q r) where
arbitrary = mul gen <$> arbitrary
{-# INLINABLE arbitrary #-}
instance Curve f c e q r => Group (Point f c e q r) where
invert = inv
{-# INLINABLE invert #-}
pow = mul'
{-# INLINABLE pow #-}
instance Curve f c e q r => Monoid (Point f c e q r) where
mempty = id
{-# INLINABLE mempty #-}
instance Curve f c e q r => Random (Point f c e q r) where
random = first (mul gen) . random
{-# INLINABLE random #-}
randomR = panic "Curve.randomR: not implemented."
instance Curve f c e q r => Semigroup (Point f c e q r) where
p <> q = if p == q then dbl p else add p q
{-# INLINABLE (<>) #-}