-- | Multivariate compact polynomials where the variable set 
-- looks like @{x_1, x_2, ... , x_N}@.
--
-- This is very similar to the \"Indexed\" version, but should have much more
-- compact in-memory representation (which is useful in case of large or many 
-- polynomials; and should be in theory also faster, because of cache-friendlyness)
--
--

{-# LANGUAGE BangPatterns, TypeFamilies, DataKinds, KindSignatures, ScopedTypeVariables, FlexibleContexts #-}
module Math.Algebra.Polynomial.Multivariate.Compact 
  ( Poly(..) , unPoly , polyVar , nOfPoly , renamePolyVar
  , ZPoly , QPoly , fromZPoly, fromQPoly
  , Compact
  )
  where

--------------------------------------------------------------------------------

import Data.List
import Data.Word

import Data.Typeable
import GHC.TypeLits
import Data.Proxy
import Unsafe.Coerce as Unsafe

import Data.Foldable as F 

import qualified Math.Algebra.Polynomial.FreeModule as ZMod
import Math.Algebra.Polynomial.FreeModule ( FreeMod , FreeModule(..) ) -- , ZMod , QMod )

import Math.Algebra.Polynomial.Monomial.Compact

import Math.Algebra.Polynomial.Class
import Math.Algebra.Polynomial.Pretty
import Math.Algebra.Polynomial.Misc

--------------------------------------------------------------------------------

-- | A multivariate polynomial in with a given coefficient ring. 
--
-- It is also indexed by the (shared) /name/ of the variables and the /number of/
-- variable. For example @Polyn Rational "x" 3@ the type of polynomials in the
-- variables @x1, x2, x3@ with rational coefficients.
newtype Poly (coeff :: *) (var :: Symbol) (n :: Nat) = Poly (FreeMod coeff (Compact var n))
  deriving (Poly coeff var n -> Poly coeff var n -> Bool
(Poly coeff var n -> Poly coeff var n -> Bool)
-> (Poly coeff var n -> Poly coeff var n -> Bool)
-> Eq (Poly coeff var n)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall coeff (var :: Symbol) (n :: Nat).
Eq coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
/= :: Poly coeff var n -> Poly coeff var n -> Bool
$c/= :: forall coeff (var :: Symbol) (n :: Nat).
Eq coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
== :: Poly coeff var n -> Poly coeff var n -> Bool
$c== :: forall coeff (var :: Symbol) (n :: Nat).
Eq coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
Eq,Eq (Poly coeff var n)
Eq (Poly coeff var n)
-> (Poly coeff var n -> Poly coeff var n -> Ordering)
-> (Poly coeff var n -> Poly coeff var n -> Bool)
-> (Poly coeff var n -> Poly coeff var n -> Bool)
-> (Poly coeff var n -> Poly coeff var n -> Bool)
-> (Poly coeff var n -> Poly coeff var n -> Bool)
-> (Poly coeff var n -> Poly coeff var n -> Poly coeff var n)
-> (Poly coeff var n -> Poly coeff var n -> Poly coeff var n)
-> Ord (Poly coeff var n)
Poly coeff var n -> Poly coeff var n -> Bool
Poly coeff var n -> Poly coeff var n -> Ordering
Poly coeff var n -> Poly coeff var n -> Poly coeff var n
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Eq (Poly coeff var n)
forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Ordering
forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Poly coeff var n
min :: Poly coeff var n -> Poly coeff var n -> Poly coeff var n
$cmin :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Poly coeff var n
max :: Poly coeff var n -> Poly coeff var n -> Poly coeff var n
$cmax :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Poly coeff var n
>= :: Poly coeff var n -> Poly coeff var n -> Bool
$c>= :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
> :: Poly coeff var n -> Poly coeff var n -> Bool
$c> :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
<= :: Poly coeff var n -> Poly coeff var n -> Bool
$c<= :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
< :: Poly coeff var n -> Poly coeff var n -> Bool
$c< :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Bool
compare :: Poly coeff var n -> Poly coeff var n -> Ordering
$ccompare :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Poly coeff var n -> Poly coeff var n -> Ordering
$cp1Ord :: forall coeff (var :: Symbol) (n :: Nat).
Ord coeff =>
Eq (Poly coeff var n)
Ord,Int -> Poly coeff var n -> ShowS
[Poly coeff var n] -> ShowS
Poly coeff var n -> String
(Int -> Poly coeff var n -> ShowS)
-> (Poly coeff var n -> String)
-> ([Poly coeff var n] -> ShowS)
-> Show (Poly coeff var n)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall coeff (var :: Symbol) (n :: Nat).
Show coeff =>
Int -> Poly coeff var n -> ShowS
forall coeff (var :: Symbol) (n :: Nat).
Show coeff =>
[Poly coeff var n] -> ShowS
forall coeff (var :: Symbol) (n :: Nat).
Show coeff =>
Poly coeff var n -> String
showList :: [Poly coeff var n] -> ShowS
$cshowList :: forall coeff (var :: Symbol) (n :: Nat).
Show coeff =>
[Poly coeff var n] -> ShowS
show :: Poly coeff var n -> String
$cshow :: forall coeff (var :: Symbol) (n :: Nat).
Show coeff =>
Poly coeff var n -> String
showsPrec :: Int -> Poly coeff var n -> ShowS
$cshowsPrec :: forall coeff (var :: Symbol) (n :: Nat).
Show coeff =>
Int -> Poly coeff var n -> ShowS
Show,Typeable)

unPoly :: Poly c v n -> FreeMod c (Compact v n)
unPoly :: Poly c v n -> FreeMod c (Compact v n)
unPoly (Poly FreeMod c (Compact v n)
x) = FreeMod c (Compact v n)
x

-- | Name of the variables
polyVar :: KnownSymbol var => Poly c var n -> String
polyVar :: Poly c var n -> String
polyVar = Proxy var -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy var -> String)
-> (Poly c var n -> Proxy var) -> Poly c var n -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly c var n -> Proxy var
forall c (var :: Symbol) (n :: Nat). Poly c var n -> Proxy var
varProxy where
  varProxy :: Poly c var n -> Proxy var
  varProxy :: Poly c var n -> Proxy var
varProxy Poly c var n
_ = Proxy var
forall k (t :: k). Proxy t
Proxy

-- | Number of variables
nOfPoly :: KnownNat n => Poly c var n -> Int
nOfPoly :: Poly c var n -> Int
nOfPoly = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int)
-> (Poly c var n -> Integer) -> Poly c var n -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Integer)
-> (Poly c var n -> Proxy n) -> Poly c var n -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly c var n -> Proxy n
forall c (var :: Symbol) (n :: Nat). Poly c var n -> Proxy n
natProxy where
  natProxy :: Poly c var n -> Proxy n
  natProxy :: Poly c var n -> Proxy n
natProxy Poly c var n
_ = Proxy n
forall k (t :: k). Proxy t
Proxy

instance FreeModule (Poly c v n) where
  type BaseF  (Poly c v n) = Compact v n
  type CoeffF (Poly c v n) = c
  toFreeModule :: Poly c v n -> FreeMod (CoeffF (Poly c v n)) (BaseF (Poly c v n))
toFreeModule   = Poly c v n -> FreeMod (CoeffF (Poly c v n)) (BaseF (Poly c v n))
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly
  fromFreeModule :: FreeMod (CoeffF (Poly c v n)) (BaseF (Poly c v n)) -> Poly c v n
fromFreeModule = FreeMod (CoeffF (Poly c v n)) (BaseF (Poly c v n)) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly

-- | Rename the variables (zero cost)
renamePolyVar :: Poly c var1 n -> Poly c var2 n
renamePolyVar :: Poly c var1 n -> Poly c var2 n
renamePolyVar = Poly c var1 n -> Poly c var2 n
forall a b. a -> b
Unsafe.unsafeCoerce

--------------------------------------------------------------------------------

type ZPoly = Poly Integer
type QPoly = Poly Rational

-- | Change the coefficient ring (from integers)
fromZPoly :: (Ring c, KnownSymbol v, KnownNat n) => Poly Integer v n -> Poly c v n
fromZPoly :: Poly Integer v n -> Poly c v n
fromZPoly= FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> (Poly Integer v n -> FreeMod c (Compact v n))
-> Poly Integer v n
-> Poly c v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ZMod (Compact v n) -> FreeMod c (Compact v n)
forall c b.
(Num c, Typeable c, Eq c, Num c, Ord b, Typeable b) =>
ZMod b -> FreeMod c b
ZMod.fromZMod (ZMod (Compact v n) -> FreeMod c (Compact v n))
-> (Poly Integer v n -> ZMod (Compact v n))
-> Poly Integer v n
-> FreeMod c (Compact v n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly Integer v n -> ZMod (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly

-- | Change the coefficient field (from rationals)
fromQPoly :: (Field c, KnownSymbol v, KnownNat n) => Poly Rational v n -> Poly c v n
fromQPoly :: Poly Rational v n -> Poly c v n
fromQPoly = FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> (Poly Rational v n -> FreeMod c (Compact v n))
-> Poly Rational v n
-> Poly c v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QMod (Compact v n) -> FreeMod c (Compact v n)
forall c b.
(Fractional c, Typeable c, Eq c, Num c, Ord b, Typeable b) =>
QMod b -> FreeMod c b
ZMod.fromQMod (QMod (Compact v n) -> FreeMod c (Compact v n))
-> (Poly Rational v n -> QMod (Compact v n))
-> Poly Rational v n
-> FreeMod c (Compact v n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly Rational v n -> QMod (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly

--------------------------------------------------------------------------------

instance (Ring c, KnownSymbol v, KnownNat n) => AlmostPolynomial (Poly c v n) where
  type CoeffP (Poly c v n) = c
  type MonomP (Poly c v n) = Compact v n
  type VarP   (Poly c v n) = Index

  zeroP :: Poly c v n
zeroP         = FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly FreeMod c (Compact v n)
forall c b. FreeMod c b
ZMod.zero
  isZeroP :: Poly c v n -> Bool
isZeroP       = FreeMod c (Compact v n) -> Bool
forall b c. Ord b => FreeMod c b -> Bool
ZMod.isZero (FreeMod c (Compact v n) -> Bool)
-> (Poly c v n -> FreeMod c (Compact v n)) -> Poly c v n -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly
  oneP :: Poly c v n
oneP          = FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (Compact v n -> FreeMod c (Compact v n)
forall c b. Num c => b -> FreeMod c b
ZMod.generator Compact v n
forall (n :: Nat) (v :: Symbol). KnownNat n => Compact v n
emptyCompact)

  fromListP :: [(MonomP (Poly c v n), CoeffP (Poly c v n))] -> Poly c v n
fromListP     = FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> ([(Compact v n, c)] -> FreeMod c (Compact v n))
-> [(Compact v n, c)]
-> Poly c v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Compact v n, c)] -> FreeMod c (Compact v n)
forall c b. (Eq c, Num c, Ord b) => [(b, c)] -> FreeMod c b
ZMod.fromList
  toListP :: Poly c v n -> [(MonomP (Poly c v n), CoeffP (Poly c v n))]
toListP       = FreeMod c (Compact v n) -> [(Compact v n, c)]
forall c b. FreeMod c b -> [(b, c)]
ZMod.toList (FreeMod c (Compact v n) -> [(Compact v n, c)])
-> (Poly c v n -> FreeMod c (Compact v n))
-> Poly c v n
-> [(Compact v n, c)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly

  variableP :: VarP (Poly c v n) -> Poly c v n
variableP     = FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> (Index -> FreeMod c (Compact v n)) -> Index -> Poly c v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Compact v n -> FreeMod c (Compact v n)
forall c b. Num c => b -> FreeMod c b
ZMod.generator (Compact v n -> FreeMod c (Compact v n))
-> (Index -> Compact v n) -> Index -> FreeMod c (Compact v n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index -> Compact v n
forall (n :: Nat) (v :: Symbol). KnownNat n => Index -> Compact v n
variableCompact
  singletonP :: VarP (Poly c v n) -> Int -> Poly c v n
singletonP    = \VarP (Poly c v n)
v Int
e -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (Compact v n -> FreeMod c (Compact v n)
forall c b. Num c => b -> FreeMod c b
ZMod.generator (Index -> Int -> Compact v n
forall (n :: Nat) (v :: Symbol).
KnownNat n =>
Index -> Int -> Compact v n
singletonCompact VarP (Poly c v n)
Index
v Int
e))
  monomP :: MonomP (Poly c v n) -> Poly c v n
monomP        = \MonomP (Poly c v n)
m     -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ Compact v n -> FreeMod c (Compact v n)
forall c b. Num c => b -> FreeMod c b
ZMod.generator MonomP (Poly c v n)
Compact v n
m
  monomP' :: MonomP (Poly c v n) -> CoeffP (Poly c v n) -> Poly c v n
monomP'       = \MonomP (Poly c v n)
m CoeffP (Poly c v n)
c   -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ Compact v n -> c -> FreeMod c (Compact v n)
forall b c. (Ord b, Num c, Eq c) => b -> c -> FreeMod c b
ZMod.singleton MonomP (Poly c v n)
Compact v n
m c
CoeffP (Poly c v n)
c
  scalarP :: CoeffP (Poly c v n) -> Poly c v n
scalarP       = \CoeffP (Poly c v n)
s     -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ Compact v n -> c -> FreeMod c (Compact v n)
forall b c. (Ord b, Num c, Eq c) => b -> c -> FreeMod c b
ZMod.singleton Compact v n
forall (n :: Nat) (v :: Symbol). KnownNat n => Compact v n
emptyCompact c
CoeffP (Poly c v n)
s

  addP :: Poly c v n -> Poly c v n -> Poly c v n
addP          = \Poly c v n
p1 Poly c v n
p2 -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ FreeMod c (Compact v n)
-> FreeMod c (Compact v n) -> FreeMod c (Compact v n)
forall b c.
(Ord b, Eq c, Num c) =>
FreeMod c b -> FreeMod c b -> FreeMod c b
ZMod.add (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p1) (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p2)
  subP :: Poly c v n -> Poly c v n -> Poly c v n
subP          = \Poly c v n
p1 Poly c v n
p2 -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ FreeMod c (Compact v n)
-> FreeMod c (Compact v n) -> FreeMod c (Compact v n)
forall b c.
(Ord b, Eq c, Num c) =>
FreeMod c b -> FreeMod c b -> FreeMod c b
ZMod.sub (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p1) (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p2)
  negP :: Poly c v n -> Poly c v n
negP          = FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> (Poly c v n -> FreeMod c (Compact v n))
-> Poly c v n
-> Poly c v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FreeMod c (Compact v n) -> FreeMod c (Compact v n)
forall c b. Num c => FreeMod c b -> FreeMod c b
ZMod.neg (FreeMod c (Compact v n) -> FreeMod c (Compact v n))
-> (Poly c v n -> FreeMod c (Compact v n))
-> Poly c v n
-> FreeMod c (Compact v n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly
  mulP :: Poly c v n -> Poly c v n -> Poly c v n
mulP          = \Poly c v n
p1 Poly c v n
p2 -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ (Compact v n -> Compact v n -> Compact v n)
-> FreeMod c (Compact v n)
-> FreeMod c (Compact v n)
-> FreeMod c (Compact v n)
forall b c.
(Ord b, Eq c, Num c) =>
(b -> b -> b) -> FreeMod c b -> FreeMod c b -> FreeMod c b
ZMod.mulWith     Compact v n -> Compact v n -> Compact v n
forall (n :: Nat) (v :: Symbol).
KnownNat n =>
Compact v n -> Compact v n -> Compact v n
mulCompact (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p1) (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p2)

  coeffOfP :: MonomP (Poly c v n) -> Poly c v n -> CoeffP (Poly c v n)
coeffOfP      = \MonomP (Poly c v n)
m Poly c v n
p   -> Compact v n -> FreeMod c (Compact v n) -> c
forall b c. (Ord b, Num c) => b -> FreeMod c b -> c
ZMod.coeffOf MonomP (Poly c v n)
Compact v n
m (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p)
  productP :: [Poly c v n] -> Poly c v n
productP      = \[Poly c v n]
ps    -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ Compact v n
-> (Compact v n -> Compact v n -> Compact v n)
-> [FreeMod c (Compact v n)]
-> FreeMod c (Compact v n)
forall b c.
(Ord b, Eq c, Num c) =>
b -> (b -> b -> b) -> [FreeMod c b] -> FreeMod c b
ZMod.productWith Compact v n
forall (n :: Nat) (v :: Symbol). KnownNat n => Compact v n
emptyCompact Compact v n -> Compact v n -> Compact v n
forall (n :: Nat) (v :: Symbol).
KnownNat n =>
Compact v n -> Compact v n -> Compact v n
mulCompact ([FreeMod c (Compact v n)] -> FreeMod c (Compact v n))
-> [FreeMod c (Compact v n)] -> FreeMod c (Compact v n)
forall a b. (a -> b) -> a -> b
$ (Poly c v n -> FreeMod c (Compact v n))
-> [Poly c v n] -> [FreeMod c (Compact v n)]
forall a b. (a -> b) -> [a] -> [b]
map Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly [Poly c v n]
ps
  mulByMonomP :: MonomP (Poly c v n) -> Poly c v n -> Poly c v n
mulByMonomP   = \MonomP (Poly c v n)
m Poly c v n
p   -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ Compact v n -> FreeMod c (Compact v n) -> FreeMod c (Compact v n)
forall c b.
(Eq c, Num c, Ord b, Monoid b) =>
b -> FreeMod c b -> FreeMod c b
ZMod.mulByMonom  MonomP (Poly c v n)
Compact v n
m (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p)
  scaleP :: CoeffP (Poly c v n) -> Poly c v n -> Poly c v n
scaleP        = \CoeffP (Poly c v n)
s Poly c v n
p   -> FreeMod c (Compact v n) -> Poly c v n
forall coeff (var :: Symbol) (n :: Nat).
FreeMod coeff (Compact var n) -> Poly coeff var n
Poly (FreeMod c (Compact v n) -> Poly c v n)
-> FreeMod c (Compact v n) -> Poly c v n
forall a b. (a -> b) -> a -> b
$ c -> FreeMod c (Compact v n) -> FreeMod c (Compact v n)
forall b c. (Ord b, Eq c, Num c) => c -> FreeMod c b -> FreeMod c b
ZMod.scale c
CoeffP (Poly c v n)
s (Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p) 

instance (Ring c, KnownSymbol v, KnownNat n) => Polynomial (Poly c v n) where
  evalP :: (CoeffP (Poly c v n) -> d)
-> (VarP (Poly c v n) -> d) -> Poly c v n -> d
evalP         = \CoeffP (Poly c v n) -> d
g VarP (Poly c v n) -> d
f Poly c v n
p -> let { !z :: Compact v n -> d
z = (VarM (Compact v n) -> d) -> Compact v n -> d
forall m c. (Monomial m, Num c) => (VarM m -> c) -> m -> c
evalM VarP (Poly c v n) -> d
VarM (Compact v n) -> d
f ; h :: (Compact v n, c) -> d
h (!Compact v n
m,!c
c) = CoeffP (Poly c v n) -> d
g c
CoeffP (Poly c v n)
c d -> d -> d
forall a. Num a => a -> a -> a
* Compact v n -> d
z Compact v n
m } in [d] -> d
forall a. Num a => [a] -> a
sum' ([d] -> d) -> [d] -> d
forall a b. (a -> b) -> a -> b
$ ((Compact v n, c) -> d) -> [(Compact v n, c)] -> [d]
forall a b. (a -> b) -> [a] -> [b]
map (Compact v n, c) -> d
h ([(Compact v n, c)] -> [d]) -> [(Compact v n, c)] -> [d]
forall a b. (a -> b) -> a -> b
$ FreeMod c (Compact v n) -> [(Compact v n, c)]
forall c b. FreeMod c b -> [(b, c)]
ZMod.toList (FreeMod c (Compact v n) -> [(Compact v n, c)])
-> FreeMod c (Compact v n) -> [(Compact v n, c)]
forall a b. (a -> b) -> a -> b
$ Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly Poly c v n
p
  --varSubsP      = \f p   -> Poly $ ZMod.mapBase (varSubsCompact f) (unPoly p)
  --coeffSubsP    = \f p   -> Poly $ ZMod.fromList $ map (termSubsCompact f) $ ZMod.toList $ unPoly p 
  --subsP         = \f p   -> Poly $ ZMod.flatMap (evalCompact (unPoly . f)) (unPoly p)
  varSubsP :: (VarP (Poly c v n) -> VarP (Poly c v n))
-> Poly c v n -> Poly c v n
varSubsP   = String -> (Index -> Index) -> Poly c v n -> Poly c v n
forall a. HasCallStack => String -> a
error String
"Compact/varSubsP: not yet implemented"
  coeffSubsP :: (VarP (Poly c v n) -> Maybe (CoeffP (Poly c v n)))
-> Poly c v n -> Poly c v n
coeffSubsP = String -> (Index -> Maybe c) -> Poly c v n -> Poly c v n
forall a. HasCallStack => String -> a
error String
"Compact/coeffSubsP: not yet implemented"
  subsP :: (VarP (Poly c v n) -> Poly c v n) -> Poly c v n -> Poly c v n
subsP      = String -> (Index -> Poly c v n) -> Poly c v n -> Poly c v n
forall a. HasCallStack => String -> a
error String
"Compact/subsP: not yet implemented"
  

instance (Ring c, KnownSymbol v, KnownNat n) => Num (Poly c v n) where
  fromInteger :: Integer -> Poly c v n
fromInteger = c -> Poly c v n
forall p. AlmostPolynomial p => CoeffP p -> p
scalarP (c -> Poly c v n) -> (Integer -> c) -> Integer -> Poly c v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> c
forall a. Num a => Integer -> a
fromInteger
  + :: Poly c v n -> Poly c v n -> Poly c v n
(+)    = Poly c v n -> Poly c v n -> Poly c v n
forall p. AlmostPolynomial p => p -> p -> p
addP
  (-)    = Poly c v n -> Poly c v n -> Poly c v n
forall p. AlmostPolynomial p => p -> p -> p
subP
  negate :: Poly c v n -> Poly c v n
negate = Poly c v n -> Poly c v n
forall p. AlmostPolynomial p => p -> p
negP
  * :: Poly c v n -> Poly c v n -> Poly c v n
(*)    = Poly c v n -> Poly c v n -> Poly c v n
forall p. AlmostPolynomial p => p -> p -> p
mulP
  abs :: Poly c v n -> Poly c v n
abs    = Poly c v n -> Poly c v n
forall a. a -> a
id
  signum :: Poly c v n -> Poly c v n
signum = \Poly c v n
_ -> CoeffP (Poly c v n) -> Poly c v n
forall p. AlmostPolynomial p => CoeffP p -> p
scalarP CoeffP (Poly c v n)
1

instance (Ring c, KnownSymbol v, KnownNat n, Pretty (Compact v n)) => Pretty (Poly c v n) where
  pretty :: Poly c v n -> String
pretty poly :: Poly c v n
poly@(Poly FreeMod c (Compact v n)
fm) = if Proxy c -> Bool
forall c. Ring c => Proxy c -> Bool
isSignedR (Poly c v n -> Proxy (CoeffP (Poly c v n))
forall p. AlmostPolynomial p => p -> Proxy (CoeffP p)
proxyCoeffP Poly c v n
poly)
    then Bool
-> (Compact v n -> String) -> FreeMod c (Compact v n) -> String
forall c b.
(Num c, Eq c, IsSigned c, Pretty c) =>
Bool -> (b -> String) -> FreeMod c b -> String
prettyFreeMod'  Bool
True   Compact v n -> String
forall a. Pretty a => a -> String
pretty FreeMod c (Compact v n)
fm
    else (c -> String)
-> (Compact v n -> String) -> FreeMod c (Compact v n) -> String
forall c b. (c -> String) -> (b -> String) -> FreeMod c b -> String
prettyFreeMod'' c -> String
forall a. Pretty a => a -> String
pretty Compact v n -> String
forall a. Pretty a => a -> String
pretty FreeMod c (Compact v n)
fm

-- hackety hack hack...
instance IsSigned (Poly c v n) where
  signOf :: Poly c v n -> Maybe Sign
signOf = Maybe Sign -> Poly c v n -> Maybe Sign
forall a b. a -> b -> a
const (Sign -> Maybe Sign
forall a. a -> Maybe a
Just Sign
Plus)

-- So that we can use it again as a coefficient ring
instance (Ring c, KnownSymbol v, KnownNat n) => Ring (Poly c v n) where
  isZeroR :: Poly c v n -> Bool
isZeroR   = FreeMod c (Compact v n) -> Bool
forall b c. Ord b => FreeMod c b -> Bool
ZMod.isZero (FreeMod c (Compact v n) -> Bool)
-> (Poly c v n -> FreeMod c (Compact v n)) -> Poly c v n -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Poly c v n -> FreeMod c (Compact v n)
forall c (v :: Symbol) (n :: Nat).
Poly c v n -> FreeMod c (Compact v n)
unPoly
  isAtomicR :: Proxy (Poly c v n) -> Bool
isAtomicR = Bool -> Proxy (Poly c v n) -> Bool
forall a b. a -> b -> a
const Bool
False
  isSignedR :: Proxy (Poly c v n) -> Bool
isSignedR = Bool -> Proxy (Poly c v n) -> Bool
forall a b. a -> b -> a
const Bool
False
  absR :: Poly c v n -> Poly c v n
absR      = Poly c v n -> Poly c v n
forall a. a -> a
id
  signumR :: Poly c v n -> Maybe Sign
signumR   = Maybe Sign -> Poly c v n -> Maybe Sign
forall a b. a -> b -> a
const (Sign -> Maybe Sign
forall a. a -> Maybe a
Just Sign
Plus)

--------------------------------------------------------------------------------