poly-0.5.1.0: src/Data/Poly/Multi/Semiring.hs
-- |
-- Module: Data.Poly.Multi.Semiring
-- Copyright: (c) 2020 Andrew Lelechenko
-- Licence: BSD3
-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>
--
-- Sparse multivariate polynomials with a 'Semiring' instance.
--
-- @since 0.5.0.0
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Poly.Multi.Semiring
( MultiPoly
, VMultiPoly
, UMultiPoly
, unMultiPoly
, toMultiPoly
, monomial
, scale
, pattern X
, pattern Y
, pattern Z
, eval
, subst
, deriv
, integral
, segregate
, unsegregate
) where
import Data.Finite
import Data.Euclidean (Field)
import Data.Semiring (Semiring(..))
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Sized as SG
import qualified Data.Vector.Sized as SV
import qualified Data.Vector.Unboxed.Sized as SU
import GHC.TypeNats (KnownNat, type (<=))
import Data.Poly.Internal.Multi (MultiPoly, VMultiPoly, UMultiPoly, unMultiPoly, segregate, unsegregate)
import qualified Data.Poly.Internal.Multi as Multi
import Data.Poly.Internal.Multi.Field ()
import Data.Poly.Internal.Multi.GcdDomain ()
-- | Make a 'MultiPoly' from a list of (powers, coefficient) pairs.
--
-- >>> :set -XOverloadedLists -XDataKinds
-- >>> import Data.Vector.Generic.Sized (fromTuple)
-- >>> toMultiPoly [(fromTuple (0,0),1),(fromTuple (0,1),2),(fromTuple (1,0),3)] :: VMultiPoly 2 Integer
-- 3 * X + 2 * Y + 1
-- >>> toMultiPoly [(fromTuple (0,0),0),(fromTuple (0,1),0),(fromTuple (1,0),0)] :: UMultiPoly 2 Int
-- 0
--
-- @since 0.5.0.0
toMultiPoly
:: (Eq a, Semiring a, G.Vector v (SU.Vector n Word, a))
=> v (SU.Vector n Word, a)
-> MultiPoly v n a
toMultiPoly = Multi.toMultiPoly'
-- | Create a monomial from powers and a coefficient.
--
-- @since 0.5.0.0
monomial
:: (Eq a, Semiring a, G.Vector v (SU.Vector n Word, a))
=> SU.Vector n Word
-> a
-> MultiPoly v n a
monomial = Multi.monomial'
-- | Multiply a polynomial by a monomial, expressed as powers and a coefficient.
--
-- >>> :set -XDataKinds
-- >>> import Data.Vector.Generic.Sized (fromTuple)
-- >>> scale (fromTuple (1, 1)) 3 (X^2 + Y) :: UMultiPoly 2 Int
-- 3 * X^3 * Y + 3 * X * Y^2
--
-- @since 0.5.0.0
scale
:: (Eq a, Semiring a, KnownNat n, G.Vector v (SU.Vector n Word, a))
=> SU.Vector n Word
-> a
-> MultiPoly v n a
-> MultiPoly v n a
scale = Multi.scale'
-- | Create a polynomial equal to the first variable.
--
-- @since 0.5.0.0
pattern X
:: (Eq a, Semiring a, KnownNat n, 1 <= n, G.Vector v (SU.Vector n Word, a))
=> MultiPoly v n a
pattern X = Multi.X'
-- | Create a polynomial equal to the second variable.
--
-- @since 0.5.0.0
pattern Y
:: (Eq a, Semiring a, KnownNat n, 2 <= n, G.Vector v (SU.Vector n Word, a))
=> MultiPoly v n a
pattern Y = Multi.Y'
-- | Create a polynomial equal to the third variable.
--
-- @since 0.5.0.0
pattern Z
:: (Eq a, Semiring a, KnownNat n, 3 <= n, G.Vector v (SU.Vector n Word, a))
=> MultiPoly v n a
pattern Z = Multi.Z'
-- | Evaluate the polynomial at a given point.
--
-- >>> :set -XDataKinds
-- >>> import Data.Vector.Generic.Sized (fromTuple)
-- >>> eval (X^2 + Y^2 :: UMultiPoly 2 Int) (fromTuple (3, 4) :: Data.Vector.Sized.Vector 2 Int)
-- 25
--
-- @since 0.5.0.0
eval
:: (Semiring a, G.Vector v (SU.Vector n Word, a), G.Vector u a)
=> MultiPoly v n a
-> SG.Vector u n a
-> a
eval = Multi.eval'
-- | Substitute other polynomials instead of the variables.
--
-- >>> :set -XDataKinds
-- >>> import Data.Vector.Generic.Sized (fromTuple)
-- >>> subst (X^2 + Y^2 + Z^2 :: UMultiPoly 3 Int) (fromTuple (X + 1, Y + 1, X + Y :: UMultiPoly 2 Int))
-- 2 * X^2 + 2 * X * Y + 2 * X + 2 * Y^2 + 2 * Y + 2
--
-- @since 0.5.0.0
subst
:: (Eq a, Semiring a, KnownNat m, G.Vector v (SU.Vector n Word, a), G.Vector w (SU.Vector m Word, a))
=> MultiPoly v n a
-> SV.Vector n (MultiPoly w m a)
-> MultiPoly w m a
subst = Multi.subst'
-- | Take the derivative of the polynomial with respect to the /i/-th variable.
--
-- >>> :set -XDataKinds
-- >>> deriv 0 (X^3 + 3 * Y) :: UMultiPoly 2 Int
-- 3 * X^2
-- >>> deriv 1 (X^3 + 3 * Y) :: UMultiPoly 2 Int
-- 3
--
-- @since 0.5.0.0
deriv
:: (Eq a, Semiring a, G.Vector v (SU.Vector n Word, a))
=> Finite n
-> MultiPoly v n a
-> MultiPoly v n a
deriv = Multi.deriv'
-- | Compute an indefinite integral of the polynomial
-- with respect to the /i/-th variable,
-- setting the constant term to zero.
--
-- >>> :set -XDataKinds
-- >>> integral 0 (3 * X^2 + 2 * Y) :: UMultiPoly 2 Double
-- 1.0 * X^3 + 2.0 * X * Y
-- >>> integral 1 (3 * X^2 + 2 * Y) :: UMultiPoly 2 Double
-- 3.0 * X^2 * Y + 1.0 * Y^2
--
-- @since 0.5.0.0
integral
:: (Field a, G.Vector v (SU.Vector n Word, a))
=> Finite n
-> MultiPoly v n a
-> MultiPoly v n a
integral = Multi.integral'