{-# LANGUAGE BangPatterns, DataKinds, KindSignatures, GeneralizedNewtypeDeriving, TypeFamilies #-}
module Math.Algebra.Polynomial.Univariate
(
Univariate(..) , U(..) , unUni , uniVar , renameUniVar
, ZUni , QUni , fromZUni , fromQUni
, differentiateUni , integrateUni , integrateUni'
)
where
import Data.Array ( Array , (!) , listArray , assocs )
import Data.List
import GHC.TypeLits
import Data.Proxy
import Unsafe.Coerce as Unsafe
import Math.Algebra.Polynomial.Class
import Math.Algebra.Polynomial.Misc
import Math.Algebra.Polynomial.Pretty
import qualified Math.Algebra.Polynomial.FreeModule as ZMod
import Math.Algebra.Polynomial.FreeModule ( FreeMod , FreeModule(..) , ZMod , QMod )
import Math.Algebra.Polynomial.Monomial.Univariate
newtype Univariate (coeff :: *) (var :: Symbol) = Uni (FreeMod coeff (U var))
deriving (Eq,Ord,Show)
unUni :: Univariate c v -> FreeMod c (U v)
unUni (Uni a) = a
instance FreeModule (Univariate c v) where
type BaseF (Univariate c v) = U v
type CoeffF (Univariate c v) = c
toFreeModule = unUni
fromFreeModule = Uni
uniVar :: KnownSymbol var => Univariate c var -> String
uniVar = symbolVal . varProxy where
varProxy :: Univariate c var -> Proxy var
varProxy _ = Proxy
renameUniVar :: Univariate c var1 -> Univariate c var2
renameUniVar = Unsafe.unsafeCoerce
type ZUni var = Univariate Integer var
type QUni var = Univariate Rational var
fromZUni :: (Ring c, KnownSymbol v) => Univariate Integer v -> Univariate c v
fromZUni = Uni . ZMod.fromZMod . unUni
fromQUni :: (Field c, KnownSymbol v) => Univariate Rational v -> Univariate c v
fromQUni = Uni . ZMod.fromQMod . unUni
differentiateUni :: (Ring c, KnownSymbol var) => Univariate c var -> Univariate c var
differentiateUni = Uni . ZMod.mapMaybeBaseCoeff f . unUni where
f (U k) = case k of
0 -> Nothing
_ -> Just ( U (k-1) , fromIntegral k )
integrateUni :: (Field c, KnownSymbol var) => Univariate c var -> Univariate c var
integrateUni = Uni . ZMod.mapMaybeBaseCoeff f . unUni where
f (U k) = Just ( U (k+1) , 1 / fromIntegral (k+1) )
integrateUni' :: (Field c, KnownSymbol var) => c -> Univariate c var -> Univariate c var
integrateUni' c0 p = integrateUni p + scalarP c0
instance (Ring coeff, KnownSymbol var) => AlmostPolynomial (Univariate coeff var) where
type CoeffP (Univariate coeff var) = coeff
type MonomP (Univariate coeff var) = U var
type VarP (Univariate coeff var) = ()
fromListP = Uni . ZMod.fromList
toListP = ZMod.toList . unUni
zeroP = Uni ZMod.zero
isZeroP = ZMod.isZero . unUni
oneP = Uni (ZMod.generator emptyM)
variableP = Uni . ZMod.generator . variableM
singletonP = \v e -> Uni (ZMod.generator (singletonM v e))
monomP = \m -> Uni $ ZMod.generator m
monomP' = \m c -> Uni $ ZMod.singleton m c
scalarP = \s -> Uni $ ZMod.singleton emptyM s
addP = \p1 p2 -> Uni $ ZMod.add (unUni p1) (unUni p2)
subP = \p1 p2 -> Uni $ ZMod.sub (unUni p1) (unUni p2)
negP = Uni . ZMod.neg . unUni
mulP = \p1 p2 -> Uni $ ZMod.mulWith mulM (unUni p1) (unUni p2)
productP = \ps -> Uni $ ZMod.productWith emptyM mulM $ map unUni ps
coeffOfP = \m p -> ZMod.coeffOf m (unUni p)
mulByMonomP = \m p -> Uni $ ZMod.mulByMonom m (unUni p)
scaleP = \s p -> Uni $ ZMod.scale s (unUni p)
instance (Ring coeff, KnownSymbol var) => Polynomial (Univariate coeff var) where
evalP = \g f p -> let { !z = evalM f ; h (!m,!c) = g c * z m } in sum' $ map h $ ZMod.toList $ unUni p
varSubsP = \f p -> Uni $ ZMod.mapBase (varSubsM f) (unUni p)
coeffSubsP = \f p -> Uni $ ZMod.fromList $ map (termSubsM f) $ ZMod.toList $ unUni p
subsP = \f p -> Uni $ ZMod.flatMap (evalM (unUni . f)) (unUni p)
instance (Ring c, KnownSymbol v) => Num (Univariate c v) where
fromInteger = scalarP . fromInteger
(+) = addP
(-) = subP
negate = negP
(*) = mulP
abs = id
signum = \_ -> scalarP 1
instance (Ring c, KnownSymbol v) => Pretty (Univariate c v) where
pretty poly@(Uni fm) = if isSignedR (proxyCoeffP poly)
then prettyFreeMod' True pretty fm
else prettyFreeMod'' pretty pretty fm
instance IsSigned (Univariate c v) where
signOf = const (Just Plus)
instance (Ring c, KnownSymbol v) => Ring (Univariate c v) where
isZeroR = ZMod.isZero . unUni
isAtomicR = const False
isSignedR = const False
absR = id
signumR = const (Just Plus)