From 0d7b5e3a8c864a606ce3181d32838a1d43da324f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Mon, 20 Jul 2020 14:58:17 +0200 Subject: [PATCH 1/4] Implement mutable addition of term --- src/mono.jl | 7 +++++ src/operators.jl | 69 +++++++++++++++++++++++++++++++++--------------- src/poly.jl | 1 + src/term.jl | 1 + 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/mono.jl b/src/mono.jl index 699ba1b..e25d566 100644 --- a/src/mono.jl +++ b/src/mono.jl @@ -80,3 +80,10 @@ MP.monomial(m::Monomial) = m # end # i > length(m1.z) #end +function _add_variables!(mono::Monomial, allvars, map) + Future.copy!(mono.vars, allvars) + tmp = copy(mono.z) + resize!(mono.z, length(allvars)) + fill!(mono.z, 0) + mono.z[map] = tmp +end diff --git a/src/operators.jl b/src/operators.jl index dc2a077..494315f 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -68,9 +68,54 @@ function MA.mutable_operate_to!(output::Polynomial{C}, op::Union{typeof(+), type return output end +_copy_monos(m::Monomial) = copy(m) +_copy_monos(t::Term) = Term(t.α, copy(t.x)) +_copy_monos(p::Polynomial) = Polynomial(p.a, copy(p.x)) +function _merge_vars!(p, q) + if _vars(p) == _vars(q) + return q + end + varsvec = [_vars(p), _vars(q)] + allvars, maps = mergevars(varsvec) + if length(allvars) != length(_vars(p)) + _add_variables!(p.x, allvars, maps[1]) + end + if length(allvars) != length(_vars(q)) + # 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. + q = _copy_monos(q) + _add_variables!(q, allvars, maps[2]) + end + return q +end function MA.mutable_operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial, - q::Union{PolyVar, Monomial, Term}) - return MA.mutable_operate!(op, p, polynomial(q)) + v::PolyVar) + return MA.mutable_operate!(op, p, monomial(v)) +end +function MA.mutable_operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial, + t::Union{Monomial, Term}) + t = _merge_vars!(p, t) + z = MP.exponents(t) + i = findfirst(eachindex(p.a)) do i + return samevars_grlex(p.x.Z[i], z) <= 0 + end + if i === nothing + push!(p.a, MA.operate(op, MP.coefficient(t))) + push!(p.x.Z, copy(z)) + else + comp = samevars_grlex(p.x.Z[i], z) + if iszero(comp) + MA.operate!(op, p.a[i], coefficient(t)) + else + @assert comp < 0 + insert!(p.a, i, MA.operate(op, MP.coefficient(t))) + insert!(p.x.Z, i, copy(z)) + end + end + return p end const _NoVarTerm{T} = Tuple{T, Vector{Int}} function MA.mutable_operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial{false}, @@ -80,25 +125,7 @@ end # TODO need to check that this also works for non-commutative function MA.mutable_operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial{true}, q::Polynomial{true}) - if _vars(p) != _vars(q) - varsvec = [_vars(p), _vars(q)] - allvars, maps = mergevars(varsvec) - if length(allvars) != length(_vars(p)) - _add_variables!(p.x, allvars, maps[1]) - end - if length(allvars) == length(_vars(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.x, allvars, maps[2]) - end - return MA.mutable_operate!(op, p, rhs) - end + q = _merge_vars!(p, q) get1(i) = (p.a[i], p.x.Z[i]) get2(i) = (MA.scaling_convert(eltype(p.a), MA.operate(op, q.a[i])), copy(q.x.Z[i])) function set(i, t::_NoVarTerm) diff --git a/src/poly.jl b/src/poly.jl index a0eb367..b2d95a9 100644 --- a/src/poly.jl +++ b/src/poly.jl @@ -262,3 +262,4 @@ function MA.mutable_operate!(::typeof(one), p::Polynomial{C, T}) where {C, T} end return p end +_add_variables!(p::Polynomial, allvars, map) = _add_variables(p.x, allvars, map) diff --git a/src/term.jl b/src/term.jl index 2a923b2..810a4fc 100644 --- a/src/term.jl +++ b/src/term.jl @@ -68,3 +68,4 @@ function MA.mutable_operate!(::typeof(one), t::Term) MA.mutable_operate!(zero, t.x.z) return t end +_add_variables!(t::Term, allvars, map) = _add_variables(t.x, allvars, map) From 5a5a4124b806eada7eb64d2dd73c68c95a6b086f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 21 Jul 2020 19:22:56 +0200 Subject: [PATCH 2/4] Fix --- src/poly.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/poly.jl b/src/poly.jl index b2d95a9..2d406c1 100644 --- a/src/poly.jl +++ b/src/poly.jl @@ -262,4 +262,4 @@ function MA.mutable_operate!(::typeof(one), p::Polynomial{C, T}) where {C, T} end return p end -_add_variables!(p::Polynomial, allvars, map) = _add_variables(p.x, allvars, map) +_add_variables!(p::Polynomial, allvars, map) = _add_variables!(p.x, allvars, map) From 33429fe8d046d9e18af84e99abe23d76c9924ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 21 Jul 2020 19:46:28 +0200 Subject: [PATCH 3/4] Fix --- src/operators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators.jl b/src/operators.jl index 494315f..271a9a5 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -108,7 +108,7 @@ function MA.mutable_operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial, else comp = samevars_grlex(p.x.Z[i], z) if iszero(comp) - MA.operate!(op, p.a[i], coefficient(t)) + p.a[i] = MA.operate!(op, p.a[i], coefficient(t)) else @assert comp < 0 insert!(p.a, i, MA.operate(op, MP.coefficient(t))) From 60fd145297f7483b811c59b5078f9264425486d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 21 Jul 2020 20:03:04 +0200 Subject: [PATCH 4/4] Fix --- src/term.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/term.jl b/src/term.jl index 810a4fc..b7ff5ef 100644 --- a/src/term.jl +++ b/src/term.jl @@ -68,4 +68,4 @@ function MA.mutable_operate!(::typeof(one), t::Term) MA.mutable_operate!(zero, t.x.z) return t end -_add_variables!(t::Term, allvars, map) = _add_variables(t.x, allvars, map) +_add_variables!(t::Term, allvars, map) = _add_variables!(t.x, allvars, map)