Sparse distributed multivariate Laurent polynomials
Every element of the multivariate Laurent polynomial ring $R[x_1, x_1^{-1}, \dots, x_n, x_n^{-1}]$ can be presented as a sum of products of powers of the $x_i$ where the power can be any integer. Therefore, the interface for sparse multivarate polynomials carries over with the additional feature that exponents can be negative.
Generic multivariate Laurent polynomial types
AbstractAlgebra.jl provides a generic implementation of multivariate Laurent polynomials, built in terms of regular multivariate polynomials, in the file src/generic/LaurentMPoly.jl.
The type LaurentMPolyWrap{T, ...} <: LaurentMPolyRingElem{T} implements generic multivariate Laurent polynomials by wrapping regular polynomials: a Laurent polynomial l wraps a polynomial p and a vector of integers $n_i$ such that $l = \prod_i x_i^{n_i} * p$. The representation is said to be normalized when each $n_i$ is as large as possible (or zero when l is zero), but the representation of a given element is not required to be normalized internally.
The corresponding parent type is LaurentMPolyWrapRing{T, ...} <: LaurentMPolyRing{T}.
Abstract types
Two abstract types LaurentMPolyRingElem{T} and LaurentMPolyRing{T} are defined to represent Laurent polynomials and rings thereof, parameterized on a base ring T.
Multivate Laurent polynomial operations
Since, from the point of view of the interface, Laurent polynomials are simply regular polynomials with possibly negative exponents, the following functions from the polynomial interface are completely analogous. As with regular polynomials, an implementation must provide access to the elements as a sum of individual terms in some order. This order currently cannot be specified in the constructor.
AbstractAlgebra.laurent_polynomial_ring — Method
laurent_polynomial_ring(R::Ring, varnames...; cached::Bool = true)Given a base ring R and variable names varnames..., say :x, :y, :z, return a tuple S, x, y, z representing the new ring $S = R[x, 1/x, y, 1/y, z, 1/z]$ and the generators $x, y, z$ of the ring.
By default (cached=true), the output S will be cached, i.e. if laurent_polynomial_ring is invoked again with the same arguments, the same (identical) ring is returned. Setting cached to false ensures a distinct new ring is returned, and will also prevent it from being cached.
For information about the many ways to specify varnames... refer to polynomial_ring or the specification in AbstractAlgebra.@varnames_interface.
Examples
julia> S, (x, y) = laurent_polynomial_ring(ZZ, [:x, :y])
(Multivariate Laurent polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.LaurentMPolyWrap{BigInt, AbstractAlgebra.Generic.MPoly{BigInt}, AbstractAlgebra.Generic.LaurentMPolyWrapRing{BigInt, AbstractAlgebra.Generic.MPolyRing{BigInt}}}[x, y])
julia> (x + y)*x^-1
1 + x^-1*yAbstractAlgebra.@laurent_polynomial_ring — Macro
@laurent_polynomial_ring(R::Ring, varnames...; cached=true)Return the ring from laurent_polynomial_ring and introduce the generators into the current scope.
Examples
julia> S = @laurent_polynomial_ring(ZZ, [:u, :v])
Multivariate Laurent polynomial ring in 2 variables u, v
over integers
julia> u*v^-1
u*v^-1(S::LaurentMPolyRing{T})(A::Vector{T}, m::Vector{Vector{Int}})MPolyBuildCtx(R::LaurentMPolyRing)
push_term!(M::LaurentMPolyBuildCtx, c::RingElem, v::Vector{Int})
finish(M::LaurentMPolyBuildCtx)symbols(S::LaurentMPolyRing)
number_of_variables(f::LaurentMPolyRing)
gens(S::LaurentMPolyRing)
gen(S::LaurentMPolyRing, i::Int)
is_gen(x::LaurentMPolyRingElem)
var_index(p::LaurentMPolyRingElem)
length(f::LaurentMPolyRingElem)coefficients(p::LaurentMPolyRingElem)
monomials(p::LaurentMPolyRingElem)
terms(p::LaurentMPolyRingElem)
exponent_vectors(p::LaurentMPolyRingElem)
leading_coefficient(p::LaurentMPolyRingElem)
leading_monomial(p::LaurentMPolyRingElem)
leading_term(p::LaurentMPolyRingElem)
leading_exponent_vector(p::LaurentMPolyRingElem)change_base_ring(::Ring, p::LaurentMPolyRingElem)
change_coefficient_ring(::Ring, p::LaurentMPolyRingElem)
map_coefficients(::Any, p::LaurentMPolyRingElem)evaluate(p::LaurentMPolyRingElem, ::Vector)derivative(p::LaurentMPolyRingElem, x::LaurentMPolyRingElem)
derivative(p::LaurentMPolyRingElem, i::Int)rand(R::LaurentMPolyRingElem, length_range::AbstractUnitRange{Int}, exp_range::AbstractUnitRange{Int}, v...)The choice of canonical unit for Laurent polynomials includes the product $\prod_i x_i^{n_i}$ from the normalized representation. In particular, this means that the output of gcd will not have any negative exponents.
julia> R, (x, y) = laurent_polynomial_ring(ZZ, [:x, :y]);
julia> canonical_unit(2*x^-5 - 3*x + 4*y^-4 + 5*y^2)
-x^-5*y^-4
julia> gcd(x^-3 - y^3, x^-2 - y^2)
x*y - 1