{-# LANGUAGE
BangPatterns, PatternSynonyms, KindSignatures, DataKinds,
FlexibleInstances, TypeSynonymInstances, ScopedTypeVariables,
EmptyDataDecls
#-}
module Math.Singular.Factory.Polynomial where
import GHC.TypeLits
import Data.Proxy
import Data.Text.Lazy ( Text , pack )
import System.IO.Unsafe as Unsafe
import Math.Singular.Factory.Internal.CanonicalForm
import Math.Singular.Factory.Internal.Factory
import Math.Singular.Factory.Variables
import Math.Singular.Factory.Domains
import Math.Singular.Factory.Expr
import Math.Singular.Factory.Parser
newtype Polynomial varset domain
= Poly { unPoly :: CF }
instance Eq (Polynomial vars domain) where
(==) (Poly cf1) (Poly cf2) = safeEqCF cf1 cf2
instance forall vars domain. VariableSet vars => Show (Polynomial vars domain) where
show (Poly cf) = showCF_with (varIdxName (Proxy :: Proxy vars)) cf
polyIsZero :: Polynomial vars domain -> Bool
polyIsZero (Poly cf) = isZeroCF cf
polyIsOne :: Polynomial vars domain -> Bool
polyIsOne (Poly cf) = isOneCF cf
inBaseDomain :: Polynomial vars domain -> Bool
inBaseDomain (Poly cf) = isInBaseDomainCF cf
mbConstant :: BaseDomain domain => Polynomial vars domain -> Maybe domain
mbConstant (Poly cf) = if isInBaseDomainCF cf
then Just (unsafeCfToBase cf)
else Nothing
konst :: BaseDomain domain => domain -> Polynomial vars domain
konst = Poly . baseToCF
var :: VarIdx -> Polynomial vars domain
var idx = Poly $ varCF (theNthVar idx)
varPow :: VarIdx -> Int -> Polynomial vars domain
varPow idx expo = Poly $ varPowCF (theNthVar idx) expo
mapIntoDomain
:: forall domain1 domain2 vars. (BaseDomain domain1, BaseDomain domain2)
=> Polynomial vars domain1 -> Polynomial vars domain2
mapIntoDomain (Poly cf) = result where
result = Poly (mapIntoCF (factoryChar pxy) cf)
pxy = Proxy :: Proxy domain2
instance forall vars domain. BaseDomain domain => Num (Polynomial vars domain) where
fromInteger = Poly . (baseToCF :: domain -> CF) . fromInteger
negate (Poly cf) = Poly (negate cf)
(Poly cf1) + (Poly cf2) = Poly (cf1 + cf2)
(Poly cf1) - (Poly cf2) = Poly (cf1 - cf2)
(Poly cf1) * (Poly cf2) = Poly (cf1 * cf2)
abs = id
signum = const 1
pow :: BaseDomain domain => Polynomial vars domain -> Int -> Polynomial vars domain
pow (Poly cf) expo = Poly $ powCF cf expo
polyGCD :: BaseDomain domain => Polynomial vars domain -> Polynomial vars domain -> Polynomial vars domain
polyGCD (Poly cf1) (Poly cf2) = Poly $ gcdPolyCF cf1 cf2
polyReduce :: BaseDomain domain => Polynomial vars domain -> Polynomial vars domain -> Polynomial vars domain
polyReduce (Poly cf1) (Poly cf2) = Poly $ reduceCF cf1 cf2
factorize :: BaseDomain domain => Polynomial vars domain -> [(Polynomial vars domain, Int)]
factorize (Poly cf) = map f (factorizeCF cf) where
f (p, expo) = (Poly p, expo)
substitute1 :: BaseDomain domain => VarIdx -> Polynomial vars domain -> Polynomial vars domain -> Polynomial vars domain
substitute1 idx (Poly what) (Poly cf) = Poly (substituteCF (theNthVar idx) what cf)
evaluate :: BaseDomain domain => (VarIdx -> domain) -> Polynomial vars domain -> domain
evaluate fun (Poly cf0) = unsafeCfToBase (go 1 cf0) where
go :: Int -> CF -> CF
go !idx !cf = if isInBaseDomainCF cf
then cf
else go (idx+1) (substituteCF (theNthVar idx) (baseToCF $ fun idx) cf)
parsePolynomial :: forall vars. VariableSet vars => Text -> Maybe (Polynomial vars Integer)
parsePolynomial text = evalGenPoly konst var <$> parseGenPoly (Proxy :: Proxy vars) text
parsePolyExpr :: forall vars. VariableSet vars => Text -> Maybe (Polynomial vars Integer)
parsePolyExpr text = evalExpr var <$> parseExpr (Proxy :: Proxy vars) text
parsePolynomialStr :: forall vars. VariableSet vars => String -> Maybe (Polynomial vars Integer)
parsePolynomialStr = parsePolynomial . pack
parsePolyExprStr :: forall vars. VariableSet vars => String -> Maybe (Polynomial vars Integer)
parsePolyExprStr = parsePolyExpr . pack