1+ """
2+ struct Polynomial{CoeffType,T<:AbstractTerm{CoeffType},V<:AbstractVector{T}} <: AbstractPolynomial{CoeffType}
3+ terms::V
4+ end
5+
6+ Representation of a multivariate polynomial as a vector of nonzero terms sorted
7+ in ascending monomial order.
8+ """
19struct Polynomial{CoeffType,T<: AbstractTerm{CoeffType} ,V<: AbstractVector{T} } < :
210 AbstractPolynomial{CoeffType}
311 terms:: V
@@ -7,8 +15,16 @@ struct Polynomial{CoeffType,T<:AbstractTerm{CoeffType},V<:AbstractVector{T}} <:
715 end
816end
917
18+ # It shouldn't be needed to call this. A polynomial should always be in
19+ # canonical format so it is only called inside an internal call.
20+ function _canonicalize! (p:: Polynomial )
21+ sort! (p. terms)
22+ uniqterms! (p. terms)
23+ return
24+ end
25+
1026function coefficients (p:: Polynomial )
11- return LazyMap {coefficienttype (p)} (coefficient, terms (p))
27+ return LazyMap {coefficient_type (p)} (coefficient, terms (p))
1228end
1329function monomials (p:: Polynomial )
1430 return LazyMap {monomial_type(p)} (monomial, terms (p))
@@ -43,7 +59,7 @@ function Base.convert(
4359 return convert (Polynomial{C,TT,Vector{TT}}, p)
4460end
4561function Base. convert (:: Type{Polynomial} , p:: AbstractPolynomialLike )
46- return convert (Polynomial{coefficienttype (p)}, p)
62+ return convert (Polynomial{coefficient_type (p)}, p)
4763end
4864
4965_change_eltype (:: Type{<:Vector} , :: Type{T} ) where {T} = Vector{T}
@@ -141,6 +157,9 @@ function MA.operate_to!(
141157 # TODO could use MA.mul_to!! for indices that were presents in `result` before the `resize!`.
142158 result. terms[i] = p. terms[i] * t
143159 end
160+ if ! multiplication_preserves_monomial_order (typeof (result))
161+ _canonicalize! (result)
162+ end
144163 return result
145164 end
146165end
@@ -158,6 +177,9 @@ function MA.operate_to!(
158177 # TODO could use MA.mul_to!! for indices that were presents in `result` before the `resize!`.
159178 result. terms[i] = t * p. terms[i]
160179 end
180+ if ! multiplication_preserves_monomial_order (typeof (result))
181+ _canonicalize! (result)
182+ end
161183 return result
162184 end
163185end
@@ -268,7 +290,7 @@ function __polynomial_merge!(
268290 if tp isa Int && j isa Int
269291 tp = get1 (tp)
270292 end
271- grlex (* (monomials (q)[j], monomial .(t)... ), monomial (tp))
293+ grlex (monomial ( * (monomials (q)[j], monomial .(t)... ) ), monomial (tp))
272294 end
273295 end
274296 get2 = let t = t, q = q
@@ -338,12 +360,28 @@ function __polynomial_merge!(
338360 q:: Polynomial ,
339361 buffer = nothing ,
340362) where {T,TT}
363+ if ! multiplication_preserves_monomial_order (typeof (p))
364+ # This function assumes that the monomials of `t * q` will preserve the
365+ # order of the terms of `q` so if it's not the case, we fallback to
366+ # another one.
367+ __polynomial_merge! (
368+ MA. add_sub_op (op),
369+ p,
370+ get1,
371+ set,
372+ push,
373+ resize,
374+ keep,
375+ t * q,
376+ )
377+ return
378+ end
341379 compare_monomials = let t = t, get1 = get1, q = q
342380 (tp, j) -> begin
343381 if tp isa Int && j isa Int
344382 tp = get1 (tp)
345383 end
346- grlex (monomial (t) * monomials (q)[j], monomial (tp))
384+ grlex (monomial (monomial ( t) * monomials (q)[j]) , monomial (tp))
347385 end
348386 end
349387 get2 = let t = t, q = q
@@ -550,8 +588,7 @@ function MA.operate_to!(
550588)
551589 empty! (output. terms)
552590 mul_to_terms! (output. terms, p, q)
553- sort! (output. terms, lt = (< ))
554- uniqterms! (output. terms)
591+ _canonicalize! (output)
555592 return output
556593end
557594function MA. operate! (:: typeof (* ), p:: Polynomial , q:: Polynomial )
@@ -567,6 +604,9 @@ function MA.operate!(::typeof(*), p::Polynomial, t::AbstractTermLike)
567604 for i in eachindex (p. terms)
568605 p. terms[i] = MA. operate!! (* , p. terms[i], t)
569606 end
607+ if ! multiplication_preserves_monomial_order (typeof (p))
608+ _canonicalize! (p)
609+ end
570610 return p
571611end
572612function map_exponents! (f, p:: Polynomial , m:: AbstractMonomialLike )
0 commit comments