Polynomial
Polynomial types using the standard basis.
Polynomial
Polynomials.Polynomial
— TypePolynomial{T, X}(coeffs::AbstractVector{T}, [var = :x])
Construct a polynomial from its coefficients coeffs
, lowest order first, optionally in terms of the given variable var
which may be a character, symbol, or a string.
If $p = a_n x^n + \ldots + a_2 x^2 + a_1 x + a_0$, we construct this through Polynomial([a_0, a_1, ..., a_n])
.
The usual arithmetic operators are overloaded to work with polynomials as well as with combinations of polynomials and scalars. However, operations involving two polynomials of different variables causes an error except those involving a constant polynomial.
Polynomial
is not axis-aware, and it treats coeffs
simply as a list of coefficients with the first index always corresponding to the constant term. In order to use the axis of coeffs
as exponents, consider using a LaurentPolynomial
or possibly a SparsePolynomial
.
Examples
julia> using Polynomials
julia> Polynomial([1, 0, 3, 4])
Polynomial(1 + 3*x^2 + 4*x^3)
julia> Polynomial([1, 2, 3], :s)
Polynomial(1 + 2*s + 3*s^2)
julia> one(Polynomial)
Polynomial(1.0)
Immutable Polynomial
Polynomials.ImmutablePolynomial
— TypeImmutablePolynomial{T, X, N}(coeffs)
Construct an immutable (static) polynomial from its coefficients a₀, a₁, …, aₙ
, lowest order first, optionally in terms of the given variable x
where x
can be a character, symbol, or string.
If $p = a_n x^n + \ldots + a_2 x^2 + a_1 x + a_0$, we construct this through ImmutablePolynomial((a_0, a_1, ..., a_n))
(assuming a_n ≠ 0
). As well, a vector or number can be used for construction.
The usual arithmetic operators are overloaded to work with polynomials as well as with combinations of polynomials and scalars. However, operations involving two non-constant polynomials of different variables causes an error. Unlike other polynomials, setindex!
is not defined for ImmutablePolynomials
.
As the degree of the polynomial (+1
) is a compile-time constant, several performance improvements are possible. For example, immutable polynomials can take advantage of faster polynomial evaluation provided by evalpoly
from Julia 1.4; similar methods are also used for addition and multiplication.
However, as the degree is included in the type, promotion between immutable polynomials can not promote to a common type. As such, they are precluded from use in rational functions.
ImmutablePolynomial
is not axis-aware, and it treats coeffs
simply as a list of coefficients with the first index always corresponding to the constant term.
Examples
julia> ImmutablePolynomial((1, 0, 3, 4))
ImmutablePolynomial(1 + 3*x^2 + 4*x^3)
julia> ImmutablePolynomial((1, 2, 3), :s)
ImmutablePolynomial(1 + 2*s + 3*s^2)
julia> one(ImmutablePolynomial)
ImmutablePolynomial(1.0)
This was modeled after StaticUnivariatePolynomials by @tkoolen
.
Sparse Polynomial
Polynomials.SparsePolynomial
— TypeSparsePolynomial{T, X}(coeffs::Dict{Int,T})
Polynomials in the standard basis backed by a dictionary holding the non-zero coefficients. For polynomials of high degree, this might be advantageous.
Examples:
julia> P = SparsePolynomial;
julia> p, q = P([1,2,3]), P([4,3,2,1])
(SparsePolynomial(1 + 2*x + 3*x^2), SparsePolynomial(4 + 3*x + 2*x^2 + x^3))
julia> p + q
SparsePolynomial(5 + 5*x + 5*x^2 + x^3)
julia> p * q
SparsePolynomial(4 + 11*x + 20*x^2 + 14*x^3 + 8*x^4 + 3*x^5)
julia> p + 1
SparsePolynomial(2 + 2*x + 3*x^2)
julia> q * 2
SparsePolynomial(8 + 6*x + 4*x^2 + 2*x^3)
julia> p = Polynomials.basis(P, 10^9) - Polynomials.basis(P,0) # also P(Dict(0=>-1, 10^9=>1))
SparsePolynomial(-1.0 + 1.0*x^1000000000)
julia> p(1)
0.0
SparsePolynomial
is an alias for MutableSparsePolynomial{StandardBasis}
.
Laurent Polynomial
Polynomials.LaurentPolynomial
— TypeLaurentPolynomial{T,X}(coeffs::AbstractVector, [m::Integer = 0], [var = :x])
A Laurent polynomial is of the form a_{m}x^m + ... + a_{n}x^n
where m,n
are integers (not necessarily positive) with m <= n
.
The coeffs
specify a_{m}, a_{m-1}, ..., a_{n}
. The argument m
represents the lowest exponent of the variable in the series, and is taken to be zero by default.
Laurent polynomials and standard basis polynomials promote to Laurent polynomials. Laurent polynomials may be converted to a standard basis polynomial when m >= 0
,
Integration will fail if there is a x⁻¹
term in the polynomial.
LaurentPolynomial
is axis-aware, unlike the other polynomial types in this package.
Examples:
julia> P = LaurentPolynomial;
julia> p = P([1,1,1], -1)
LaurentPolynomial(x⁻¹ + 1 + x)
julia> q = P([1,1,1])
LaurentPolynomial(1 + x + x²)
julia> pp = Polynomial([1,1,1])
Polynomial(1 + x + x^2)
julia> p + q
LaurentPolynomial(x⁻¹ + 2 + 2*x + x²)
julia> p * q
LaurentPolynomial(x⁻¹ + 2 + 3*x + 2*x² + x³)
julia> p * pp
LaurentPolynomial(x⁻¹ + 2 + 3*x + 2*x² + x³)
julia> pp - q
LaurentPolynomial(0)
julia> derivative(p)
LaurentPolynomial(-x⁻² + 1)
julia> integrate(q)
LaurentPolynomial(1.0*x + 0.5*x² + 0.3333333333333333*x³)
julia> integrate(p) # x⁻¹ term is an issue
ERROR: ArgumentError: Can't integrate Laurent polynomial with `x⁻¹` term
julia> integrate(P([1,1,1], -5))
LaurentPolynomial(-0.25*x⁻⁴ - 0.3333333333333333*x⁻³ - 0.5*x⁻²)
julia> x⁻¹ = inv(variable(LaurentPolynomial)) # `inv` defined on monomials
LaurentPolynomial(1.0*x⁻¹)
julia> p = Polynomial([1,2,3])
Polynomial(1 + 2*x + 3*x^2)
julia> x = variable()
Polynomial(x)
julia> x^degree(p) * p(x⁻¹) # reverses coefficients
LaurentPolynomial(3.0 + 2.0*x + 1.0*x²)
Factored Polynomial
Polynomials.FactoredPolynomial
— TypeFactoredPolynomial{T,X}
A polynomial type that stores its data in a dictionary whose keys are the roots and whose values are the respective multiplicities along with a leading coefficient.
The structure is utilized for scalar multiplication, polynomial multiplication and powers, the finding of roots, and the identification of a greatest common divisor. For other operations, say addition, the operation is done after converting to the Polynomial
type then converting back. (This requires the identification of the roots, so is subject to numeric issues.)
Examples
julia> using Polynomials
julia> p = FactoredPolynomial(Dict([0=>1, 1=>2, 3=>4]))
FactoredPolynomial(x * (x - 3)⁴ * (x - 1)²)
julia> q = fromroots(FactoredPolynomial, [0,1,2,3])
FactoredPolynomial(x * (x - 2) * (x - 3) * (x - 1))
julia> p*q
FactoredPolynomial(x² * (x - 2) * (x - 3)⁵ * (x - 1)³)
julia> p^1000
FactoredPolynomial(x¹⁰⁰⁰ * (x - 3)⁴⁰⁰⁰ * (x - 1)²⁰⁰⁰)
julia> gcd(p,q)
FactoredPolynomial(x * (x - 3) * (x - 1))
julia> p = Polynomial([24, -50, 35, -10, 1])
Polynomial(24 - 50*x + 35*x^2 - 10*x^3 + x^4)
julia> q = convert(FactoredPolynomial, p) # noisy form of `factor`:
FactoredPolynomial((x - 4.0000000000000036) * (x - 2.9999999999999942) * (x - 1.0000000000000002) * (x - 2.0000000000000018))
julia> map(x->round(x, digits=12), q) # map works over factors and leading coefficient -- not coefficients in the standard basis
FactoredPolynomial((x - 4.0) * (x - 2.0) * (x - 3.0) * (x - 1.0))
Rational Function
Polynomials.RationalFunction
— TypeRationalFunction(p::AbstractPolynomial, q::AbstractPolynomial)
p // q
Create a rational expression (p//q
) from the two polynomials.
Common factors are not cancelled by the constructor, as they are for the base Rational
type. The lowest_terms
function attempts that operation.
For purposes of iteration, a rational function is treated like a two-element container.
Examples
julia> using Polynomials
julia> p,q = fromroots(Polynomial, [1,2,3]), fromroots(Polynomial, [2,3,4])
(Polynomial(-6 + 11*x - 6*x^2 + x^3), Polynomial(-24 + 26*x - 9*x^2 + x^3))
julia> pq = p // q
(-6 + 11*x - 6*x^2 + x^3) // (-24 + 26*x - 9*x^2 + x^3)
julia> lowest_terms(pq)
(-0.333333 + 0.333333*x) // (-1.33333 + 0.333333*x)
julia> pq(2.5)
-1.0
julia> pq(2) # uses first non-`0/0` ratio of `p⁽ᵏ⁾/q⁽ᵏ⁾`
-0.5
julia> pq^2
(36 - 132*x + 193*x^2 - 144*x^3 + 58*x^4 - 12*x^5 + x^6) // (576 - 1248*x + 1108*x^2 - 516*x^3 + 133*x^4 - 18*x^5 + x^6)
julia> derivative(pq)
(-108 + 180*x - 111*x^2 + 30*x^3 - 3*x^4) // (576 - 1248*x + 1108*x^2 - 516*x^3 + 133*x^4 - 18*x^5 + x^6)
The RationalFunctions.jl package was a helpful source of ideas.
The ImmutablePolynomial
type can not be used for rational functions, as the type requires the numerator and denominator to have the exact same type.
Polynomials.lowest_terms
— Functionlowest_terms(pq::AbstractRationalFunction, method=:numerical)
Find GCD of (p,q)
, u
, and return (p÷u)//(q÷u)
. Commonly referred to as lowest terms.
method
: passed togcd(p,q)
kwargs
: passed togcd(p,q)
By default, AbstractRationalFunction
types do not cancel common factors. This method will numerically cancel common factors, returning the normal form, canonicalized here by q[end]=1
. The result and original may be considered equivalent as rational expressions, but different when seen as functions of the indeterminate.