@@ -68,9 +68,54 @@ function MA.mutable_operate_to!(output::Polynomial{C}, op::Union{typeof(+), type
6868 return output
6969end
7070
71+ _copy_monos (m:: Monomial ) = copy (m)
72+ _copy_monos (t:: Term ) = Term (t. α, copy (t. x))
73+ _copy_monos (p:: Polynomial ) = Polynomial (p. a, copy (p. x))
74+ function _merge_vars! (p, q)
75+ if _vars (p) == _vars (q)
76+ return q
77+ end
78+ varsvec = [_vars (p), _vars (q)]
79+ allvars, maps = mergevars (varsvec)
80+ if length (allvars) != length (_vars (p))
81+ _add_variables! (p. x, allvars, maps[1 ])
82+ end
83+ if length (allvars) != length (_vars (q))
84+ # We could avoid promoting `q` to the same variables
85+ # like in `plusorminus` to avoid extra allocation but it then
86+ # gives slower comparison. There is a tradeoff and the approach used here
87+ # should be better of `q` has less terms and then the same term is compared
88+ # many times.
89+ q = _copy_monos (q)
90+ _add_variables! (q, allvars, maps[2 ])
91+ end
92+ return q
93+ end
7194function MA. mutable_operate! (op:: Union{typeof(+), typeof(-)} , p:: Polynomial ,
72- q:: Union{PolyVar, Monomial, Term} )
73- return MA. mutable_operate! (op, p, polynomial (q))
95+ v:: PolyVar )
96+ return MA. mutable_operate! (op, p, monomial (v))
97+ end
98+ function MA. mutable_operate! (op:: Union{typeof(+), typeof(-)} , p:: Polynomial ,
99+ t:: Union{Monomial, Term} )
100+ t = _merge_vars! (p, t)
101+ z = MP. exponents (t)
102+ i = findfirst (eachindex (p. a)) do i
103+ return samevars_grlex (p. x. Z[i], z) <= 0
104+ end
105+ if i === nothing
106+ push! (p. a, MA. operate (op, MP. coefficient (t)))
107+ push! (p. x. Z, copy (z))
108+ else
109+ comp = samevars_grlex (p. x. Z[i], z)
110+ if iszero (comp)
111+ MA. operate! (op, p. a[i], coefficient (t))
112+ else
113+ @assert comp < 0
114+ insert! (p. a, i, MA. operate (op, MP. coefficient (t)))
115+ insert! (p. x. Z, i, copy (z))
116+ end
117+ end
118+ return p
74119end
75120const _NoVarTerm{T} = Tuple{T, Vector{Int}}
76121function MA. mutable_operate! (op:: Union{typeof(+), typeof(-)} , p:: Polynomial{false} ,
80125# TODO need to check that this also works for non-commutative
81126function MA. mutable_operate! (op:: Union{typeof(+), typeof(-)} , p:: Polynomial{true} ,
82127 q:: Polynomial{true} )
83- if _vars (p) != _vars (q)
84- varsvec = [_vars (p), _vars (q)]
85- allvars, maps = mergevars (varsvec)
86- if length (allvars) != length (_vars (p))
87- _add_variables! (p. x, allvars, maps[1 ])
88- end
89- if length (allvars) == length (_vars (q))
90- rhs = q
91- else
92- # We could avoid promoting `q` to the same variables
93- # like in `plusorminus` to avoid extra allocation but it then
94- # gives slower comparison. There is a tradeoff and the approach used here
95- # should be better of `q` has less terms and then the same term is compared
96- # many times.
97- rhs = Polynomial (q. a, copy (q. x))
98- _add_variables! (rhs. x, allvars, maps[2 ])
99- end
100- return MA. mutable_operate! (op, p, rhs)
101- end
128+ q = _merge_vars! (p, q)
102129 get1 (i) = (p. a[i], p. x. Z[i])
103130 get2 (i) = (MA. scaling_convert (eltype (p. a), MA. operate (op, q. a[i])), copy (q. x. Z[i]))
104131 function set (i, t:: _NoVarTerm )
0 commit comments