module ZkFold.Symbolic.GroebnerBasis.Types (
    Variable,
    Monomial,
    Polynomial,
    variable,
    monomial,
    polynomial
    ) where

import           Data.List                                    (sortBy)
import           Data.Map                                     (Map)
import           Numeric.Natural                              (Natural)
import           Prelude                                      hiding (Num (..), length, replicate, (!!))

import           ZkFold.Base.Algebra.Basic.Class              (PrimeField)
import           ZkFold.Base.Algebra.Basic.Field              (Zp)
import           ZkFold.Symbolic.GroebnerBasis.Internal.Types

type Variable p = Var Integer (Zp p)

variable :: Integer -> Variable p
variable :: forall (p :: Natural). Integer -> Variable p
variable = Integer -> Var Integer (Zp p)
forall {k} a (c :: k). a -> Var a c
Free

type Monomial p = Monom Integer (Zp p)

monomial :: Zp p -> Map Natural (Variable p) -> Monomial p
monomial :: forall (p :: Natural).
Zp p -> Map Natural (Variable p) -> Monomial p
monomial = Zp p -> Map Natural (Var Integer (Zp p)) -> Monom Integer (Zp p)
forall a c. c -> Map Natural (Var a c) -> Monom a c
M

type Polynomial p = Polynom Integer (Zp p)

polynomial :: PrimeField (Zp p) => [Monomial p] -> Polynomial p
polynomial :: forall (p :: Natural).
PrimeField (Zp p) =>
[Monomial p] -> Polynomial p
polynomial = [Monom Integer (Zp p)] -> Polynom Integer (Zp p)
forall a c. [Monom a c] -> Polynom a c
P ([Monom Integer (Zp p)] -> Polynom Integer (Zp p))
-> ([Monom Integer (Zp p)] -> [Monom Integer (Zp p)])
-> [Monom Integer (Zp p)]
-> Polynom Integer (Zp p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Monom Integer (Zp p) -> Monom Integer (Zp p) -> Ordering)
-> [Monom Integer (Zp p)] -> [Monom Integer (Zp p)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((Monom Integer (Zp p) -> Monom Integer (Zp p) -> Ordering)
-> Monom Integer (Zp p) -> Monom Integer (Zp p) -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip Monom Integer (Zp p) -> Monom Integer (Zp p) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare) ([Monom Integer (Zp p)] -> [Monom Integer (Zp p)])
-> ([Monom Integer (Zp p)] -> [Monom Integer (Zp p)])
-> [Monom Integer (Zp p)]
-> [Monom Integer (Zp p)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Monom Integer (Zp p) -> Bool)
-> [Monom Integer (Zp p)] -> [Monom Integer (Zp p)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (Monom Integer (Zp p) -> Bool) -> Monom Integer (Zp p) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Monom Integer (Zp p) -> Bool
forall c a. (Eq c, FiniteField c) => Monom a c -> Bool
zeroM)