From 6f63963b0218ef4637557ea90d28cb6923b279c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 17 Apr 2026 13:16:18 +0200 Subject: [PATCH 1/3] Remove Polynomials --- src/DynamicPolynomials.jl | 91 +++++++------ src/comp.jl | 56 -------- src/diff.jl | 18 --- src/mult.jl | 138 +------------------- src/operators.jl | 267 +------------------------------------- src/promote.jl | 64 +-------- src/subs.jl | 103 +-------------- 7 files changed, 63 insertions(+), 674 deletions(-) diff --git a/src/DynamicPolynomials.jl b/src/DynamicPolynomials.jl index 889877b..3334a38 100644 --- a/src/DynamicPolynomials.jl +++ b/src/DynamicPolynomials.jl @@ -8,82 +8,97 @@ import MutableArithmetics as MA import StarAlgebras as SA include("var.jl") -#const CommutativeVariable{O,M} = Variable{Commutative{O},M} -#const NonCommutativeVariable{O,M} = Variable{NonCommutative{O},M} include("mono.jl") const DMonomialLike{V,M} = Union{Monomial{V,M},Variable{V,M}} MA.mutability(::Type{<:Monomial{<:Commutative}}) = MA.IsMutable() MA.mutability(::Type{<:Monomial{<:NonCommutative}}) = MA.IsNotMutable() + +# Term type comes from MP (SA.Term) const _Term{V,M,T} = MP.Term{T,Monomial{V,M}} -function __add_variables!(t::_Term, allvars, map) - return __add_variables!(MP.monomial(t), allvars, map) -end + include("monomial_vector.jl") -include("poly.jl") -MA.mutability(::Type{<:Polynomial}) = MA.IsMutable() -const TermPoly{V,M,T} = Union{_Term{V,M,T},Polynomial{V,M,T}} -const PolyType{V,M} = - Union{Polynomial{V,M},_Term{V,M},Monomial{V,M},Variable{V,M}} + function MP.variable_union_type( - ::Union{PolyType{V,M},Type{<:PolyType{V,M}}}, + ::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, ) where {V,M} return Variable{V,M} end -MP.constant_monomial(::Type{<:PolyType{V,M}}) where {V,M} = Monomial{V,M}() -function MP.constant_monomial(p::PolyType) - return Monomial(copy(MP.variables(p)), zeros(Int, nvariables(p))) +function MP.variable_union_type( + ::Union{_Term{V,M},Type{<:_Term{V,M}}}, +) where {V,M} + return Variable{V,M} end -MP.monomial_type(::Type{<:PolyType{V,M}}) where {V,M} = Monomial{V,M} -MP.monomial_type(::PolyType{V,M}) where {V,M} = Monomial{V,M} -MP.ordering(p::PolyType) = MP.ordering(MP.variable_union_type(p)) -#function MP.constant_monomial(::Type{Monomial{V,M}}, vars=Variable{V,M}[]) where {V,M} -# return Monomial{V,M}(vars, zeros(Int, length(vars))) -#end -function MP.term_type( - ::Union{TermPoly{V,M,T},Type{<:TermPoly{V,M,T}}}, -) where {V,M,T} - return _Term{V,M,T} +MP.constant_monomial(::Type{<:DMonomialLike{V,M}}) where {V,M} = Monomial{V,M}() +function MP.constant_monomial(p::DMonomialLike) + return Monomial(copy(MP.variables(p)), zeros(Int, nvariables(p))) end +MP.monomial_type(::Type{<:DMonomialLike{V,M}}) where {V,M} = Monomial{V,M} +MP.monomial_type(::DMonomialLike{V,M}) where {V,M} = Monomial{V,M} +MP.monomial_type(::Type{<:_Term{V,M}}) where {V,M} = Monomial{V,M} +MP.monomial_type(::_Term{V,M}) where {V,M} = Monomial{V,M} +MP.ordering(p::DMonomialLike) = MP.ordering(MP.variable_union_type(p)) + function MP.term_type( - ::Union{PolyType{V,M},Type{<:PolyType{V,M}}}, + ::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, ::Type{T}, ) where {V,M,T} return _Term{V,M,T} end -MP.term_type(::Type{Polynomial{V,M}}) where {V,M} = _Term{V,M} -MP.polynomial_type(::Type{_Term{V,M}}) where {V,M} = Polynomial{V,M} -MP.polynomial_type(::Type{_Term{V,M,T}}) where {T,V,M} = Polynomial{V,M,T} + +# polynomial_type returns AlgebraElement type +# We compute the FullBasis type directly to avoid recursion through _polynomial_type +function _dp_full_basis_type(::Type{Monomial{V,M}}) where {V,M} + Vars = Vector{Variable{V,M}} + E = Vector{Int} + P = MP.Polynomial{MP.Monomial,Vars,E} + O = MP.ordering(Variable{V,M}) + return SA.MappedBasis{ + P, E, + MP.ExponentsIterator{O,Nothing,E}, + MP.Variables{MP.Monomial,Vars}, + typeof(MP.exponents), + } +end + function MP.polynomial_type( - ::Union{PolyType{V,M},Type{<:PolyType{V,M}}}, + ::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, ::Type{T}, ) where {V,M,T} - return Polynomial{V,M,T} + return MP.algebra_element_type(Vector{T}, _dp_full_basis_type(Monomial{V,M})) +end +function MP.polynomial_type(::Type{_Term{V,M,T}}) where {V,M,T} + return MP.algebra_element_type(Vector{T}, _dp_full_basis_type(Monomial{V,M})) +end +function MP.polynomial_type(::Type{_Term{V,M}}) where {V,M} + return MP.algebra_element_type(Vector{Any}, _dp_full_basis_type(Monomial{V,M})) end -MP.variables(p::AbstractArray{<:PolyType}) = mergevars(MP.variables.(p))[1] + +MP.variables(p::AbstractArray{<:DMonomialLike}) = mergevars(MP.variables.(p))[1] function MP.nvariables( - p::Union{PolyType,MonomialVector,AbstractArray{<:PolyType}}, + p::Union{DMonomialLike,MonomialVector,AbstractArray{<:DMonomialLike}}, ) return length(MP.variables(p)) end function MP.similar_variable( - P::Union{PolyType{V,M},Type{<:PolyType{V,M}}}, + P::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, ::Type{Val{S}}, ) where {V,M,S} return MP.similar_variable(P, S) end -function MP.similar_variable(p::PolyType{V,M}, s::Symbol) where {V,M} +function MP.similar_variable(p::DMonomialLike{V,M}, s::Symbol) where {V,M} return Variable(string(s), V, M, isreal(p) ? REAL : COMPLEX) end -function MP.similar_variable(::Type{<:PolyType{V,M}}, s::Symbol) where {V,M} - return Variable(string(s), V, M, REAL) # we cannot infer this from the type +function MP.similar_variable(::Type{<:DMonomialLike{V,M}}, s::Symbol) where {V,M} + return Variable(string(s), V, M, REAL) end include("promote.jl") -include("operators.jl") +# Monomial multiplication (cmult.jl and ncmult.jl) +include("mult.jl") + include("comp.jl") -include("anti_diff.jl") include("diff.jl") include("subs.jl") diff --git a/src/comp.jl b/src/comp.jl index 16f8697..87d019e 100644 --- a/src/comp.jl +++ b/src/comp.jl @@ -6,7 +6,6 @@ function Base.:(==)(x::Vector{Variable{V,M}}, y::Vector{Variable{V,M}}) where {V if length(x) != length(y) false else - #for (xi, yi) in zip(x, y) for i in 1:length(x) if x[i] != y[i] return false @@ -41,8 +40,6 @@ function (==)(x::MonomialVector{V,M}, y::MonomialVector{V,M}) where {V,M} return false end allvars, maps = mergevars([MP.variables(x), MP.variables(y)]) - # Should be sorted in the same order since the non-common - # polyvar should have exponent 0 for (a, b) in zip(x.Z, y.Z) A = zeros(Int, length(allvars)) B = zeros(Int, length(allvars)) @@ -56,56 +53,3 @@ function (==)(x::MonomialVector{V,M}, y::MonomialVector{V,M}) where {V,M} end (==)(mv::AbstractVector, x::MonomialVector) = monomial_vector(mv) == x (==)(x::MonomialVector, mv::AbstractVector) = x == monomial_vector(mv) - -# Comparison of Term -function _compare(p::Polynomial{V,M}, q::Polynomial{V,M}, comparator) where {V,M} - # terms should be sorted and without zeros - if MP.nterms(p) != MP.nterms(q) - return false - end - for i in eachindex(p.a) - if !comparator(p.x[i], q.x[i]) - # There should not be zero terms - @assert p.a[i] != 0 - @assert q.a[i] != 0 - return false - end - if !comparator(p.a[i], q.a[i]) - return false - end - end - return true -end - -(==)(p::Polynomial{V, M}, q::Polynomial{V, M}) where {V, M} = _compare(p, q, (==)) -Base.isequal(p::Polynomial{V, M}, q::Polynomial{V, M}) where {V, M} = _compare(p, q, isequal) - -function Base.isapprox( - p::Polynomial{V,M,S}, - q::Polynomial{V,M,T}; - rtol::Real = Base.rtoldefault(S, T, 0), - atol::Real = 0, - ztol::Real = iszero(atol) ? Base.rtoldefault(S, T, 0) : atol, -) where {V,M,S,T} - i = j = 1 - while i <= length(p.x) || j <= length(q.x) - if i > length(p.x) || (j <= length(q.x) && q.x[j] < p.x[i]) - if !isapproxzero(q.a[j], ztol = ztol) - return false - end - j += 1 - elseif j > length(q.x) || p.x[i] < q.x[j] - if !isapproxzero(p.a[i], ztol = ztol) - return false - end - i += 1 - else - if !isapprox(p.a[i], q.a[j], rtol = rtol, atol = atol) - return false - end - i += 1 - j += 1 - end - end - return true -end diff --git a/src/diff.jl b/src/diff.jl index 591d1fb..c7200cf 100644 --- a/src/diff.jl +++ b/src/diff.jl @@ -8,21 +8,3 @@ function MP.differentiate(m::Monomial{V,M}, x::Variable{V,M}) where {V,M} m.z[i] * Monomial(MP.variables(m), z) end end - -function MP.differentiate(p::Polynomial{V,M,T}, x::Variable{V,M}) where {V,M,T} - # grlex order preserved - i = something(findfirst(isequal(x), MP.variables(p)), 0) - S = typeof(zero(T) * 0) - if iszero(i) - zero(Polynomial{V,M,S}) - else - keep = findall(z -> z[i] > 0, p.x.Z) - Z = copy.(p.x.Z[keep]) - a = Vector{S}(undef, length(keep)) - for j in 1:length(Z) - a[j] = p.a[keep[j]] * Z[j][i] - Z[j][i] -= 1 - end - Polynomial(a, MonomialVector(MP.variables(p), Z)) - end -end diff --git a/src/mult.jl b/src/mult.jl index e422a4f..042bcd3 100644 --- a/src/mult.jl +++ b/src/mult.jl @@ -1,3 +1,4 @@ +# Monomial multiplication helper functions function multiplyexistingvar(i::Int, z::Vector{Int}) newz = copy(z) newz[i] += 1 @@ -36,143 +37,8 @@ function insertvar(Z::Vector{Vector{Int}}, x::Variable, i::Int) return Vector{Int}[insertvar(z, x, i) for z in Z] end +# Commutative and noncommutative monomial multiplication include("cmult.jl") include("ncmult.jl") MP.left_constant_mult(α, x::Monomial) = MP.term(α, MA.mutable_copy(x)) - -function zero_with_variables( - ::Type{Polynomial{V,M,T}}, - vars::Vector{Variable{V,M}}, -) where {V,M,T} - return Polynomial(T[], empty_monomial_vector(vars)) -end - -# I do not want to cast x to TermContainer because that would force the promotion of eltype(q) with Int -function Base.:(*)(x::DMonomialLike, p::Polynomial) - return Polynomial(MA.mutable_copy(p.a), x * p.x) -end -function Base.:(*)(x::DMonomialLike{<:NonCommutative}, p::Polynomial) - # Order may change, e.g. y * (x + y) = y^2 + yx - return Polynomial( - monomial_vector(MA.mutable_copy(p.a), [x * m for m in p.x])..., - ) -end - -function _term_poly_mult( - t::_Term{V,M,S}, - p::Polynomial{V,M,T}, - op::Function, -) where {V,M,S,T} - U = MA.promote_operation(op, S, T) - if iszero(t) - zero(Polynomial{V,M,U}) - else - n = nterms(p) - allvars, maps = mergevars([MP.monomial(t).vars, p.x.vars]) - nv = length(allvars) - # Necessary to annotate the type in case it is empty - Z = Vector{Int}[zeros(Int, nv) for i in 1:n] - for i in 1:n - Z[i][maps[1]] = MP.monomial(t).z - Z[i][maps[2]] += p.x.Z[i] - end - Polynomial(op.(MP.coefficient(t), p.a), MonomialVector(allvars, Z)) - end -end -Base.:(*)(p::Polynomial, t::_Term) = _term_poly_mult(t, p, (α, β) -> β * α) -Base.:(*)(t::_Term, p::Polynomial) = _term_poly_mult(t, p, *) -_sumprod(a, b) = a * b + a * b -function _mul( - ::Type{T}, - p::AbstractPolynomialLike, - q::AbstractPolynomialLike, -) where {T} - return _mul(T, polynomial(p), polynomial(q)) -end -function _mul( - ::Type{T}, - p::Polynomial{<:Commutative}, - q::Polynomial{<:Commutative}, -) where {T} - samevars = MP.variables(p) == MP.variables(q) - if samevars - allvars = copy(MP.variables(p)) - else - allvars, maps = mergevars([MP.variables(p), MP.variables(q)]) - end - N = MP.nterms(p) * MP.nterms(q) - Z = Vector{Vector{Int}}(undef, N) - a = Vector{T}(undef, N) - i = 0 - for u in MP.terms(p) - for v in MP.terms(q) - if samevars - z = MP.monomial(u).z + MP.monomial(v).z - else - z = zeros(Int, length(allvars)) - z[maps[1]] += MP.monomial(u).z - z[maps[2]] += MP.monomial(v).z - end - i += 1 - Z[i] = z - a[i] = MP.coefficient(u) * MP.coefficient(v) - end - end - return allvars, a, Z -end -function Base.:(*)( - p::Polynomial{V,M,S}, - q::Polynomial{V,M,T}, -) where {V<:Commutative,M,S,T} - PT = MA.promote_operation(*, typeof(p), typeof(q)) - if iszero(p) || iszero(q) - zero(PT) - else - polynomialclean(_mul(MP.coefficient_type(PT), p, q)...) - end -end -function MA.operate_to!( - p::Polynomial{V,M,T}, - ::typeof(*), - q1::MP.AbstractPolynomialLike, - q2::MP.AbstractPolynomialLike, -) where {V<:NonCommutative,M,T} - if iszero(q1) || iszero(q2) - MA.operate!(zero, p) - else - ts = _Term{V,M,T}[] - MP.mul_to_terms!(ts, q1, q2) - # TODO do better than create tmp - tmp = polynomial!(ts) - copy!(p.a, tmp.a) - copy!(p.x.vars, tmp.x.vars) - copy!(p.x.Z, tmp.x.Z) - return p - end -end -function MA.operate_to!( - p::Polynomial{<:Commutative,M,T}, - ::typeof(*), - q1::MP.AbstractPolynomialLike, - q2::MP.AbstractPolynomialLike, -) where {M,T} - if iszero(q1) || iszero(q2) - MA.operate!(zero, p) - else - polynomialclean_to!(p, _mul(T, q1, q2)...) - end -end -function MA.operate!( - ::typeof(*), - p::Polynomial{V,M}, - q::Polynomial{V,M}, -) where {V,M} - if iszero(q) - return MA.operate!(zero, p) - elseif nterms(q) == 1 - return MA.operate!(*, p, MP.leading_term(q)) - else - return MA.operate_to!(p, *, p, q) - end -end diff --git a/src/operators.jl b/src/operators.jl index 607fb65..9d318e8 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -1,270 +1,7 @@ -# In Base/intfuncs.jl, x^p returns zero(x) when p == 0 -# Since one(Variable) and one(Monomial) do not return -# a Variable and a Monomial, this results in type instability -# Defining the specific methods solve this problem and also make -# them a lot faster +# Monomial power Base.:(^)(x::Variable{V,M}, i::Int) where {V,M} = Monomial{V,M}([x], [i]) Base.:(^)(x::Monomial{<:Commutative}, i::Int) = Monomial(copy(x.vars), i * x.z) +# Monomial arithmetic (delegates to MP term arithmetic) Base.:(+)(x::DMonomialLike, y::DMonomialLike) = MP.term(x) + MP.term(y) Base.:(-)(x::DMonomialLike, y::DMonomialLike) = MP.term(x) - MP.term(y) - -_getindex(p::Polynomial, i::Int) = MP.terms(p)[i] -_getindex(t::_Term, ::Int) = t -function _plusorminus_to!( - a::Vector{U}, - Z::Vector{Vector{Int}}, - op::Function, - p::TermPoly{V,M}, - q::TermPoly{V,M}, - maps, - nvars, -) where {V,M,U} - i = j = 1 - while i <= nterms(p) || j <= nterms(q) - z = zeros(Int, nvars) - if j > nterms(q) || ( - i <= nterms(p) && - MP.monomial(_getindex(p, i)) < MP.monomial(_getindex(q, j)) - ) - t = _getindex(p, i) - z[maps[1]] = MP.monomial(t).z - α = MA.scaling_convert(U, MA.copy_if_mutable(MP.coefficient(t))) - i += 1 - elseif i > nterms(p) || - MP.monomial(_getindex(q, j)) < MP.monomial(_getindex(p, i)) - t = _getindex(q, j) - z[maps[2]] = MP.monomial(t).z - α = MA.scaling_convert(U, MA.operate(op, MP.coefficient(t))) - j += 1 - else - t = _getindex(p, i) - z[maps[1]] = MP.monomial(t).z - s = _getindex(q, j) - α = op(MP.coefficient(t), MP.coefficient(s)) - i += 1 - j += 1 - end - push!(a, α) - push!(Z, z) - end -end -function plusorminus( - p::TermPoly{V,M,S}, - q::TermPoly{V,M,T}, - op::Function, -) where {V,M,S,T} - varsvec = [MP.variables(p), MP.variables(q)] - allvars, maps = mergevars(varsvec) - U = MA.promote_operation(op, S, T) - a = U[] - Z = Vector{Int}[] - _plusorminus_to!(a, Z, op, p, q, maps, length(allvars)) - return Polynomial(a, MonomialVector{V,M}(allvars, Z)) -end - -function MA.operate!(::typeof(*), p::Polynomial, t::_Term) - # In case `coefficient(t)` is a polynomial (e.g. in `gcd` algorithm) - # We cannot do `MA.operate!(*, ...)`, we need `MP.right_constant_mult` - MA.operate!(MP.right_constant_mult, p, coefficient(t)) - MA.operate!(*, p, monomial(t)) - return p -end - -function MA.operate_to!( - output::Polynomial{V,M}, - op::Union{typeof(+),typeof(-)}, - p::TermPoly{V,M}, - q::TermPoly{V,M}, -) where {V,M} - if output === p || output === q - # Otherwise, `_plusorminus_to!` never finishes - error( - "Cannot call `operate_to!(output, $op, p, q)` with `output` equal to `p` or `q`, call `operate!` instead.", - ) - end - varsvec = [MP.variables(p), MP.variables(q)] - allvars, maps = mergevars(varsvec) - copy!(output.x.vars, allvars) - empty!(output.a) - empty!(output.x.Z) - _plusorminus_to!(output.a, output.x.Z, op, p, q, maps, length(allvars)) - return output -end - -""" - _lowest_term_idx(p::Polynomial) - -Return the index of the lowest term in `p` according to its monomial ordering. -""" -_lowest_term_idx(p::Polynomial{V, M, T}) where {V, M <: Reverse, T} = lastindex(p.x) -_lowest_term_idx(p::Polynomial) = firstindex(p.x) - -""" - _insert_constant_term!(p::Polynomial) - -Insert a constant (degree 0) term into polynomial `p` at the appropriate position for the -monomial ordering of `p`. Assume that a constant term does not already exists. -""" -function _insert_constant_term!(p::Polynomial{V, M, T}) where {V, M <: Reverse, T} - push!(MP.coefficients(p), zero(T)) - push!(MP.monomials(p).Z, zeros(Int, length(MP.variables(p)))) - return p -end - -function _insert_constant_term!(p::Polynomial{V, M, T}) where {V, M, T} - insert!(MP.coefficients(p), 1, zero(T)) - insert!(MP.monomials(p).Z, 1, zeros(Int, length(MP.variables(p)))) - return p -end - -function MA.operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial{V, M, T}, x::T) where {V, M, T} - c_idx = _lowest_term_idx(p) - if MP.nterms(p) == 0 || !MP.isconstant(MP.terms(p)[c_idx]) - _insert_constant_term!(p) - c_idx = _lowest_term_idx(p) - end - coeffs = MP.coefficients(p) - coeffs[c_idx] = op(coeffs[c_idx], x) - if iszero(coeffs[c_idx]) - deleteat!(coeffs, c_idx) - deleteat!(MP.monomials(p), c_idx) - end - return p -end - -function MA.operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial{V, M, T}, x::Variable{V, M}) where {V, M, T} - vars = MP.variables(p) - idx = searchsortedfirst(vars, x; rev = true) - monos = MP.monomials(p) - if idx > length(vars) || !isequal(vars[idx], x) - for mono in monos - insert!(MP.exponents(mono), idx, 0) - end - insert!(vars, idx, x) - end - mono = Monomial{V, M}(vars, zeros(Int, length(vars))) - mono.z[idx] = 1 - idx = searchsortedfirst(monos, mono) - coeffs = MP.coefficients(p) - N = MP.nterms(p) - if idx > N || !isequal(monos[idx], mono) - insert!(monos.Z, idx, MP.exponents(mono)) - insert!(coeffs, idx, zero(T)) - end - coeffs[idx] = op(coeffs[idx], one(T)) - if iszero(coeffs[idx]) - deleteat!(coeffs, idx) - deleteat!(monos, idx) - end - return p -end - -function MA.operate!( - op::Union{typeof(+),typeof(-)}, - p::Polynomial, - q::Union{Variable,Monomial,_Term}, -) - return MA.operate!(op, p, polynomial(q)) -end -const _NoVarTerm{T} = Tuple{T,Vector{Int}} -function MA.operate!( - op::Union{typeof(+),typeof(-)}, - p::Polynomial{<:NonCommutative}, - q::Polynomial{<:NonCommutative}, -) - return MA.operate_to!(p, op, MA.copy(p), q) -end - -function _exponents_compare(q::Polynomial{V,M}, j, e) where {V,M} - return cmp(M(), q.x.Z[j], e) -end - -# TODO need to check that this also works for non-commutative -function MA.operate!( - op::Union{typeof(+),typeof(-)}, - p::Polynomial{V, M1, T1}, - q::Polynomial{V, M2, T2}, -) where {V<:Commutative, M1, M2, T1, T2} - if MP.variables(p) != MP.variables(q) - allvars, maps = ___add_variables!(p, q) - if length(allvars) == length(MP.variables(q)) - rhs = q - else - # We could avoid promoting `q` to the same variables - # like in `plusorminus` to avoid extra allocation but it then - # gives slower comparison. There is a tradeoff and the approach used here - # should be better of `q` has less terms and then the same term is compared - # many times. - rhs = Polynomial(q.a, copy(q.x)) - __add_variables!(rhs, allvars, maps[2]) - end - return MA.operate!(op, p, rhs) - end - get1(i) = (p.a[i], p.x.Z[i]) - function get2(i) - return ( - MA.scaling_convert(eltype(p.a), MA.operate(op, q.a[i])), - copy(q.x.Z[i]), - ) - end - function set(i, t::_NoVarTerm) - p.a[i] = t[1] - return p.x.Z[i] = t[2] - end - function push(t::_NoVarTerm) - push!(p.a, t[1]) - return push!(p.x.Z, t[2]) - end - compare_monomials_impl(t, j) = _exponents_compare(q, j, t[2]) - compare_monomials(t::_NoVarTerm, j::Int) = compare_monomials_impl(t, j) - compare_monomials(i::Int, j::Int) = compare_monomials_impl(get1(i), j) - combine(i::Int, j::Int) = p.a[i] = MA.operate!!(op, p.a[i], q.a[j]) - combine(t::_NoVarTerm, j::Int) = (MA.operate!!(op, t[1], q.a[j]), t[2]) - function resize(n) - resize!(p.a, n) - return resize!(p.x.Z, n) - end - # We can modify the coefficient since it's the result of `combine`. - keep(t::_NoVarTerm) = !MA.iszero!!(t[1]) - keep(i::Int) = !MA.iszero!!(p.a[i]) - MP.polynomial_merge!( - nterms(p), - nterms(q), - get1, - get2, - set, - push, - compare_monomials, - combine, - keep, - resize, - Tuple{MA.promote_operation(op, T1, T2), Vector{Int}}, - ) - return p -end - -Base.:(+)(x::TermPoly{V,M}, y::TermPoly{V,M}) where {V,M} = plusorminus(x, y, +) -Base.:(-)(x::TermPoly{V,M}, y::TermPoly{V,M}) where {V,M} = plusorminus(x, y, -) -function Base.:(+)(x::TermPoly{V,M}, y::Union{Monomial,Variable}) where {V,M} - return x + MP.term(y) -end -function Base.:(+)(x::Union{Monomial,Variable}, y::TermPoly{V,M}) where {V,M} - return MP.term(x) + y -end - -function Base.:(-)(x::TermPoly{V,M,T}, y::DMonomialLike{V,M}) where {V,M,T} - return x - convert(MP.term_type(y, T), y) -end -function Base.:(-)(x::DMonomialLike{V,M}, y::TermPoly{V,M,T}) where {V,M,T} - return convert(MP.term_type(x, T), x) - y -end - -# `MA.operate(-, p)` redirects to `-p` as it assumes that `-p` can be modified -# through the MA API without modifying `p`. We should either copy `p.x` here -# or implement a `MA.operate(-, p)` that copies it. We choose the first option. -Base.:(-)(p::Polynomial) = Polynomial(-p.a, copy(p.x)) -# TODO use that with MA v0.2 -#Base.:(-)(p::Polynomial) = Polynomial(map(α -> MA.operate(-, α), p.a), copy(p.x)) - -include("mult.jl") diff --git a/src/promote.jl b/src/promote.jl index f739611..a30a67f 100644 --- a/src/promote.jl +++ b/src/promote.jl @@ -10,11 +10,7 @@ function MP.promote_variables(m1::Monomial, m2::Monomial) return Monomial(allvars, z1), Monomial(allvars, z2) end -# StarAlgebras promote_with_map implementations -# These are called by SA.maybe_promote(p, all_vars, map) when map is an ExponentMap, -# as part of SA.promote_bases_with_maps (defined in MultivariatePolynomials.jl). -# Guarded by isdefined since ExponentMap is not yet in released MultivariatePolynomials. - +# StarAlgebras promote_with_map implementations for Variables and Monomials function SA.promote_with_map( v::Variable{V,M}, all_vars::Vector{Variable{V,M}}, @@ -32,67 +28,9 @@ function SA.promote_with_map( return Monomial{V,M}(copy(all_vars), map(m.z)), map end -function SA.promote_with_map( - p::Polynomial{V,M,T}, - all_vars::Vector{Variable{V,M}}, - map::MP.ExponentMap, -) where {V,M,T} - new_Z = [map(z) for z in p.x.Z] - new_x = MonomialVector{V,M}(copy(all_vars), new_Z) - return Polynomial{V,M,T}(copy(p.a), new_x), map -end - function MP.promote_rule_constant( ::Type{T}, ::Type{<:DMonomialLike{V,M}}, ) where {V,M,T} return _Term{V,M,promote_type(T, Int)} end -function MP.promote_rule_constant( - ::Type{S}, - ::Type{_Term{V,M,T}}, -) where {S,V,M,T} - return _Term{V,M,promote_type(S, T)} -end -function MP.promote_rule_constant( - ::Type{S}, - ::Type{<:TermPoly{V,M,T}}, -) where {S,V,M,T} - return Polynomial{V,M,promote_type(S, T)} -end -MP.promote_rule_constant(::Type, ::Type{_Term{V,M}}) where {V,M} = Any -MP.promote_rule_constant(::Type, ::Type{Polynomial{V,M}}) where {V,M} = Any -function Base.promote_rule( - ::Type{_Term{V,M}}, - ::Type{_Term{V,M,T}}, -) where {V,M,T} - return _Term{V,M} -end -function Base.promote_rule( - ::Type{_Term{V,M,T}}, - ::Type{_Term{V,M}}, -) where {V,M,T} - return _Term{V,M} -end -function Base.promote_rule( - ::Type{_Term{V,M}}, - ::Type{<:DMonomialLike{V,M}}, -) where {V,M} - return _Term{V,M} -end -function Base.promote_rule( - ::Type{<:DMonomialLike{V,M}}, - ::Type{_Term{V,M}}, -) where {V,M} - return _Term{V,M} -end - -function Base.convert(::Type{_Term{V,M}}, m::DMonomialLike{V,M}) where {V,M} - return convert(_Term{V,M,Int}, m) -end -function Base.convert( - ::Type{Polynomial{V,M}}, - t::Union{TermPoly{V,M},DMonomialLike{V,M}}, -) where {V,M} - return MP.polynomial(t) -end diff --git a/src/subs.jl b/src/subs.jl index 66e179b..8960739 100644 --- a/src/subs.jl +++ b/src/subs.jl @@ -12,16 +12,6 @@ function fillmap!( vars::Vector{<:Variable{C}}, s::MP.Substitution, ) where {C} - # We may assign a complex or real variable to its value (ordinary substitution). - # We follow the following rules: - # - If a single substitution rule determines the value of a real variable, just substitute it. - # - If a single substitution rule determines the value of a complex variable or its conjugate, substitute the appropriate - # value whereever something related to this variable is found (i.e., the complex variable, the conjugate variable, or - # its real or imaginary part) - # - If a single substitution rule determines the value of the real or imaginary part of a complex variable alone, then only - # replace the real or imaginary parts if they occur explicitly. Don't do a partial substitution, i.e., `z` with the rule - # `zᵣ => 1` is left alone and not changed into `1 + im*zᵢ`. Even if both the real and imaginary parts are substituted as - # two individual rules (which we don't know of in this method), `z` will not be replaced. if s.first.kind == REAL for j in eachindex(vars) if vars[j] == s.first @@ -78,7 +68,6 @@ end _substype(s::MP.Substitutions) = _substype(s...) function _subsmap(::MP.Eval, vars, s::MP.Substitutions) - # Every variable should be replaced by some value of type T vals = SafeValues( BitSet(1:length(vars)), Vector{_substype(s)}(undef, length(vars)), @@ -98,7 +87,6 @@ function _subsmap( vars::Vector{Variable{V,M}}, s::MP.Substitutions, ) where {V,M} - # Some variable may not be replaced vals = Vector{promote_type(_substype(s), Variable{V,M})}(undef, length(vars)) copy!(vals, vars) @@ -110,32 +98,13 @@ subsmap(st, vars, s::MP.Substitutions) = _subsmap(st, vars, s) _vec(a::AbstractVector) = a _vec(a::Tuple) = [a...] function subsmap(st, vars, s::Tuple{MP.VectorMultiSubstitution}) - if vars === s[1].first || vars == s[1].first # shortcut, === happens when the user do p(variables(p) => ...) + if vars === s[1].first || vars == s[1].first _vec(s[1].second) else _subsmap(st, vars, s) end end -_add_variables!(α, β) = α -_add_variables!(p::PolyType, α) = p -_add_variables!(α, p::PolyType) = MP.operate!!(*, α, one(p)) -function _add_variables!(x::Variable, p::PolyType) - return MP.operate!!(*, x, one(p)) -end -function ___add_variables!(p, q) - varsvec = [MP.variables(p), MP.variables(q)] - allvars, maps = mergevars(varsvec) - if length(allvars) != length(MP.variables(p)) - __add_variables!(p, allvars, maps[1]) - end - return allvars, maps -end -function _add_variables!(p::PolyType, q::PolyType) - ___add_variables!(p, q) - return p -end - function _mono_eval(z::Union{Vector{Int},Tuple}, vals::AbstractVector) if length(z) != length(vals) error("Cannot evaluate a polynomial of `$(length(z))` variables with only `$(length(vals))` values.") @@ -143,13 +112,9 @@ function _mono_eval(z::Union{Vector{Int},Tuple}, vals::AbstractVector) if isempty(z) return one(eltype(vals))^1 end - # `Base.power_by_squaring` does a `copy` if `z[1]` is `1` - # which is redirected to `MA.mutable_copy` val = vals[1]^z[1] for i in 2:length(vals) - if iszero(z[i]) - val = _add_variables!(val, vals[i]) - else + if !iszero(z[i]) val = MA.operate!!(*, val, vals[i]^z[i]) end end @@ -158,60 +123,18 @@ end MP.substitute(::MP.AbstractSubstitutionType, ::Variable, vals::AbstractVector) = _mono_eval((1,), vals) MP.substitute(::MP.AbstractSubstitutionType, m::Monomial, vals::AbstractVector) = _mono_eval(m.z, vals) -function MP.substitute(st::MP.AbstractSubstitutionType, t::_Term, vals::AbstractVector) - return MP.coefficient(t) * MP.substitute(st, MP.monomial(t), vals) -end -function MP.substitute( - ::MP.Eval, - p::Polynomial{V,M,T}, - vals::AbstractVector{S}, -) where {V,M,T,S} - # I need to check for iszero otherwise I get : ArgumentError: reducing over an empty collection is not allowed - if iszero(p) - zero(MA.promote_operation(*, S, T)) - else - sum(i -> p.a[i] * _mono_eval(p.x.Z[i], vals), eachindex(p.a)) - end -end -function MP.substitute( - ::MP.Subs, - p::Polynomial{V,M,T}, - vals::AbstractVector{S}, -) where {V,M,T,S} - Tout = MA.promote_operation(*, T, MP.coefficient_type(S)) - q = zero_with_variables( - Polynomial{V,M,Tout}, - mergevars_of(Variable{V,M}, vals)[1], - ) - for i in eachindex(p.a) - MA.operate!(+, q, p.a[i] * _mono_eval(p.x.Z[i], vals)) - end - return q -end - -function MA.promote_operation( - ::typeof(MP.substitute), - ::Type{MP.Subs}, - ::Type{Monomial{V,M}}, - ::Type{Pair{Variable{V,M},T}}, -) where {V,M,T} - U = MA.promote_operation(*, T, T) - return MA.promote_operation(*, U, Monomial{V,M}) -end function MP.substitute( st::MP.AbstractSubstitutionType, - p::PolyType, + p::DMonomialLike, s::MP.AbstractSubstitution..., ) return MP.substitute(st, p, subsmap(st, MP.variables(p), s)) end -# TODO resolve ambiguity. Can remove after: -# https://github.com/JuliaAlgebra/MultivariatePolynomials.jl/pull/305 function MP.substitute( st::MP.AbstractSubstitutionType, - p::PolyType, + p::DMonomialLike, s::MP.AbstractMultiSubstitution, ) return MP.substitute(st, p, subsmap(st, MP.variables(p), (s,))) @@ -219,7 +142,7 @@ end function MP.substitute( st::MP.AbstractSubstitutionType, - p::PolyType, + p::DMonomialLike, s::MP.Substitutions, ) return MP.substitute(st, p, subsmap(st, MP.variables(p), s)) @@ -227,8 +150,6 @@ end (v::Variable)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), v, s) (m::Monomial)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), m, s) -(t::_Term)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), t, s) -(p::Polynomial)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), p, s) (p::Variable)(x::Number) = x function (p::Monomial)(x::NTuple{N,<:Number}) where {N} @@ -238,17 +159,3 @@ function (p::Monomial)(x::AbstractVector{<:Number}) return MP.substitute(MP.Eval(), p, x) end (p::Monomial)(x::Number...) = MP.substitute(MP.Eval(), p, variables(p) => x) -function (p::_Term)(x::NTuple{N,<:Number}) where {N} - return MP.substitute(MP.Eval(), p, variables(p) => x) -end -function (p::_Term)(x::AbstractVector{<:Number}) - return MP.substitute(MP.Eval(), p, x) -end -(p::_Term)(x::Number...) = MP.substitute(MP.Eval(), p, variables(p) => x) -function (p::Polynomial)(x::NTuple{N,<:Number}) where {N} - return MP.substitute(MP.Eval(), p, variables(p) => x) -end -function (p::Polynomial)(x::AbstractVector{<:Number}) - return MP.substitute(MP.Eval(), p, x) -end -(p::Polynomial)(x::Number...) = MP.substitute(MP.Eval(), p, variables(p) => x) From 73a511a747946a87e910e7009c69ff6eab09be08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 17 Apr 2026 13:51:53 +0200 Subject: [PATCH 2/3] Algebra in term --- src/DynamicPolynomials.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/DynamicPolynomials.jl b/src/DynamicPolynomials.jl index 3334a38..197c572 100644 --- a/src/DynamicPolynomials.jl +++ b/src/DynamicPolynomials.jl @@ -13,8 +13,9 @@ const DMonomialLike{V,M} = Union{Monomial{V,M},Variable{V,M}} MA.mutability(::Type{<:Monomial{<:Commutative}}) = MA.IsMutable() MA.mutability(::Type{<:Monomial{<:NonCommutative}}) = MA.IsNotMutable() -# Term type comes from MP (SA.Term) -const _Term{V,M,T} = MP.Term{T,Monomial{V,M}} +# Term type comes from SA — SA.Term{T,A,I} where A is the polynomial algebra +# _Term is now just a convenient alias used internally +const _Term{V,M,T} = SA.Term{T} include("monomial_vector.jl") From 13e58ee6c25912be361c0f6b6089a1f18b4ab26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 17 Apr 2026 15:42:02 +0200 Subject: [PATCH 3/3] Remove monomial --- src/DynamicPolynomials.jl | 110 +++++++++++++++++--------------------- src/comp.jl | 26 +-------- src/promote.jl | 31 +---------- src/var.jl | 4 +- 4 files changed, 53 insertions(+), 118 deletions(-) diff --git a/src/DynamicPolynomials.jl b/src/DynamicPolynomials.jl index 197c572..1991fe5 100644 --- a/src/DynamicPolynomials.jl +++ b/src/DynamicPolynomials.jl @@ -8,101 +8,87 @@ import MutableArithmetics as MA import StarAlgebras as SA include("var.jl") -include("mono.jl") -const DMonomialLike{V,M} = Union{Monomial{V,M},Variable{V,M}} -MA.mutability(::Type{<:Monomial{<:Commutative}}) = MA.IsMutable() -MA.mutability(::Type{<:Monomial{<:NonCommutative}}) = MA.IsNotMutable() -# Term type comes from SA — SA.Term{T,A,I} where A is the polynomial algebra -# _Term is now just a convenient alias used internally -const _Term{V,M,T} = SA.Term{T} +# Monomials are now MP.Polynomial{MP.Monomial, V, E} +# No separate Monomial struct — variables and exponents live in the basis element. -include("monomial_vector.jl") +# The monomial type for DP variables +const DMonomialLike{V} = Union{MP.Polynomial{MP.Monomial,V},Variable{V}} +# Convenience alias for the specific monomial type with DP variables +const DPMonomial{V,M} = MP.Polynomial{MP.Monomial,Vector{Variable{V,M}},Vector{Int}} function MP.variable_union_type( - ::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, + ::Union{Variable{V,M},Type{<:Variable{V,M}}}, ) where {V,M} return Variable{V,M} end function MP.variable_union_type( - ::Union{_Term{V,M},Type{<:_Term{V,M}}}, + ::Union{DPMonomial{V,M},Type{<:DPMonomial{V,M}}}, ) where {V,M} return Variable{V,M} end -MP.constant_monomial(::Type{<:DMonomialLike{V,M}}) where {V,M} = Monomial{V,M}() -function MP.constant_monomial(p::DMonomialLike) - return Monomial(copy(MP.variables(p)), zeros(Int, nvariables(p))) -end -MP.monomial_type(::Type{<:DMonomialLike{V,M}}) where {V,M} = Monomial{V,M} -MP.monomial_type(::DMonomialLike{V,M}) where {V,M} = Monomial{V,M} -MP.monomial_type(::Type{<:_Term{V,M}}) where {V,M} = Monomial{V,M} -MP.monomial_type(::_Term{V,M}) where {V,M} = Monomial{V,M} -MP.ordering(p::DMonomialLike) = MP.ordering(MP.variable_union_type(p)) -function MP.term_type( - ::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, - ::Type{T}, -) where {V,M,T} - return _Term{V,M,T} -end - -# polynomial_type returns AlgebraElement type -# We compute the FullBasis type directly to avoid recursion through _polynomial_type -function _dp_full_basis_type(::Type{Monomial{V,M}}) where {V,M} - Vars = Vector{Variable{V,M}} - E = Vector{Int} - P = MP.Polynomial{MP.Monomial,Vars,E} - O = MP.ordering(Variable{V,M}) - return SA.MappedBasis{ - P, E, - MP.ExponentsIterator{O,Nothing,E}, - MP.Variables{MP.Monomial,Vars}, - typeof(MP.exponents), - } -end +MP.constant_monomial(::Type{DPMonomial{V,M}}) where {V,M} = MP.Polynomial( + MP.Variables{MP.Monomial}(Variable{V,M}[]), + Int[], +) +MP.monomial_type(::Type{<:DPMonomial{V,M}}) where {V,M} = DPMonomial{V,M} +MP.monomial_type(::DPMonomial{V,M}) where {V,M} = DPMonomial{V,M} +MP.monomial_type(::Type{<:Variable{V,M}}) where {V,M} = DPMonomial{V,M} +MP.monomial_type(::Variable{V,M}) where {V,M} = DPMonomial{V,M} +# MP.ordering for Variable is in var.jl -function MP.polynomial_type( - ::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, +function MP.term_type( + ::Union{Variable{V,M},Type{<:Variable{V,M}}}, ::Type{T}, ) where {V,M,T} - return MP.algebra_element_type(Vector{T}, _dp_full_basis_type(Monomial{V,M})) -end -function MP.polynomial_type(::Type{_Term{V,M,T}}) where {V,M,T} - return MP.algebra_element_type(Vector{T}, _dp_full_basis_type(Monomial{V,M})) -end -function MP.polynomial_type(::Type{_Term{V,M}}) where {V,M} - return MP.algebra_element_type(Vector{Any}, _dp_full_basis_type(Monomial{V,M})) + # Create a term via the convenience constructor + # term_type needs to return a constructible type... + # For now just return SA.Term{T} since concrete type depends on algebra + return SA.Term{T} end -MP.variables(p::AbstractArray{<:DMonomialLike}) = mergevars(MP.variables.(p))[1] -function MP.nvariables( - p::Union{DMonomialLike,MonomialVector,AbstractArray{<:DMonomialLike}}, -) +MP.variables(p::AbstractArray{<:Variable}) = mergevars(MP.variables.(p))[1] +function MP.nvariables(p::Union{Variable,AbstractArray{<:Variable}}) return length(MP.variables(p)) end function MP.similar_variable( - P::Union{DMonomialLike{V,M},Type{<:DMonomialLike{V,M}}}, + P::Union{Variable{V,M},Type{<:Variable{V,M}}}, ::Type{Val{S}}, ) where {V,M,S} return MP.similar_variable(P, S) end -function MP.similar_variable(p::DMonomialLike{V,M}, s::Symbol) where {V,M} +function MP.similar_variable(p::Variable{V,M}, s::Symbol) where {V,M} return Variable(string(s), V, M, isreal(p) ? REAL : COMPLEX) end -function MP.similar_variable(::Type{<:DMonomialLike{V,M}}, s::Symbol) where {V,M} +function MP.similar_variable(::Type{<:Variable{V,M}}, s::Symbol) where {V,M} return Variable(string(s), V, M, REAL) end -include("promote.jl") +# Create monomial from variable: Variable → Polynomial{Monomial,...} +function Base.convert(::Type{DPMonomial{V,M}}, x::Variable{V,M}) where {V,M} + return MP.Polynomial{MP.Monomial}(x) +end -# Monomial multiplication (cmult.jl and ncmult.jl) -include("mult.jl") +# monomial(vars, exps) constructs a Polynomial{Monomial,...} +function MP.monomial(vars::Vector{Variable{V,M}}, z::Vector{Int}) where {V,M} + @assert !iscomm(V) || issorted(vars, rev = true) + return MP.Polynomial(MP.Variables{MP.Monomial}(vars), z) +end + +# exponents for variables is in var.jl include("comp.jl") +include("promote.jl") -include("diff.jl") -include("subs.jl") +# Variable power → monomial +Base.:(^)(x::Variable{V,M}, i::Int) where {V,M} = MP.Polynomial( + MP.Variables{MP.Monomial}([x]), + [i], +) -include("div.jl") +# Variable + Variable → uses term + term → AlgebraElement +Base.:(+)(x::Variable, y::Variable) = MP.term(x) + MP.term(y) +Base.:(-)(x::Variable, y::Variable) = MP.term(x) - MP.term(y) end # module diff --git a/src/comp.jl b/src/comp.jl index 87d019e..2c97d7e 100644 --- a/src/comp.jl +++ b/src/comp.jl @@ -1,7 +1,6 @@ import Base.== -# TODO This should be in Base with T instead of Variable{V,M}. -# See https://github.com/blegat/MultivariatePolynomials.jl/issues/3 +# Comparison of Variable vectors function Base.:(==)(x::Vector{Variable{V,M}}, y::Vector{Variable{V,M}}) where {V,M} if length(x) != length(y) false @@ -16,7 +15,6 @@ function Base.:(==)(x::Vector{Variable{V,M}}, y::Vector{Variable{V,M}}) where {V end # Comparison of Variable - const AnyCommutative{O} = Union{Commutative{O},NonCommutative{O}} function Base.cmp( @@ -30,26 +28,4 @@ function Base.cmp( end end -# TODO remove Base.:(==)(x::Variable, y::Variable) = iszero(cmp(x, y)) -Base.:(==)(x::Monomial, y::Monomial) = iszero(cmp(x, y)) - -# Comparison of MonomialVector -function (==)(x::MonomialVector{V,M}, y::MonomialVector{V,M}) where {V,M} - if length(x.Z) != length(y.Z) - return false - end - allvars, maps = mergevars([MP.variables(x), MP.variables(y)]) - for (a, b) in zip(x.Z, y.Z) - A = zeros(Int, length(allvars)) - B = zeros(Int, length(allvars)) - A[maps[1]] = a - B[maps[2]] = b - if A != B - return false - end - end - return true -end -(==)(mv::AbstractVector, x::MonomialVector) = monomial_vector(mv) == x -(==)(x::MonomialVector, mv::AbstractVector) = x == monomial_vector(mv) diff --git a/src/promote.jl b/src/promote.jl index a30a67f..dd34f90 100644 --- a/src/promote.jl +++ b/src/promote.jl @@ -1,36 +1,9 @@ -function MP.promote_variables(m1::Monomial, m2::Monomial) - if MP.variables(m1) == MP.variables(m2) - return m1, m2 - end - allvars, maps = mergevars([MP.variables(m1), MP.variables(m2)]) - z1 = zeros(Int, length(allvars)) - z1[maps[1]] = m1.z - z2 = zeros(Int, length(allvars)) - z2[maps[2]] = m2.z - return Monomial(allvars, z1), Monomial(allvars, z2) -end - -# StarAlgebras promote_with_map implementations for Variables and Monomials +# StarAlgebras promote_with_map for DP Variables function SA.promote_with_map( v::Variable{V,M}, all_vars::Vector{Variable{V,M}}, map::MP.ExponentMap, ) where {V,M} new_z = map([1]) - return Monomial{V,M}(copy(all_vars), new_z), map -end - -function SA.promote_with_map( - m::Monomial{V,M}, - all_vars::Vector{Variable{V,M}}, - map::MP.ExponentMap, -) where {V,M} - return Monomial{V,M}(copy(all_vars), map(m.z)), map -end - -function MP.promote_rule_constant( - ::Type{T}, - ::Type{<:DMonomialLike{V,M}}, -) where {V,M,T} - return _Term{V,M,promote_type(T, Int)} + return MP.Polynomial(MP.Variables{MP.Monomial}(copy(all_vars)), new_z), map end diff --git a/src/var.jl b/src/var.jl index 472f4ab..b341162 100644 --- a/src/var.jl +++ b/src/var.jl @@ -207,7 +207,7 @@ function MP.name_base_indices(v::Variable) end end -MP.monomial(v::Variable) = Monomial(v) +MP.monomial(v::Variable) = MP.Polynomial{MP.Monomial}(v) MP.variables(v::Variable) = [v] MP.exponents(::Variable) = [1] MP.ordering(v::Variable) = MP.ordering(typeof(v)) @@ -245,7 +245,7 @@ function Base.imag(x::Variable{V,M}) where {V,M} if x.kind == COMPLEX return Variable(x, IMAG_PART) elseif x.kind == CONJ - return _Term{V,M,Int}(-1, Monomial(Variable(x, IMAG_PART))) + return SA.Term(-1, MP.monomial(Variable(x, IMAG_PART))) else return MA.Zero() end