Skip to content

Commit 0ca8e5f

Browse files
feat: add fast in-place Polynomial + Variable implementation
1 parent 0e608dd commit 0ca8e5f

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/operators.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,33 @@ function MA.operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial{V, M, T}, x:
129129
return p
130130
end
131131

132+
function MA.operate!(op::Union{typeof(+), typeof(-)}, p::Polynomial{V, M, T}, x::Variable{V, M}) where {V, M, T}
133+
vars = MP.variables(p)
134+
idx = searchsortedfirst(vars, x; rev = true)
135+
monos = MP.monomials(p)
136+
if idx > length(vars) || !isequal(vars[idx], x)
137+
for mono in monos
138+
insert!(MP.exponents(mono), idx, 0)
139+
end
140+
insert!(vars, idx, x)
141+
end
142+
mono = Monomial{V, M}(vars, zeros(Int, length(vars)))
143+
mono.z[idx] = 1
144+
idx = searchsortedfirst(monos, mono)
145+
coeffs = MP.coefficients(p)
146+
N = MP.nterms(p)
147+
if idx > N || !isequal(monos[idx], mono)
148+
insert!(monos.Z, idx, MP.exponents(mono))
149+
insert!(coeffs, idx, zero(T))
150+
end
151+
coeffs[idx] = op(coeffs[idx], one(T))
152+
if iszero(coeffs[idx])
153+
deleteat!(coeffs, idx)
154+
deleteat!(monos, idx)
155+
end
156+
return p
157+
end
158+
132159
function MA.operate!(
133160
op::Union{typeof(+),typeof(-)},
134161
p::Polynomial,

test/mutable_arithmetics.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,29 @@ end
7373
# subsequent additions don't allocate
7474
@test (@allocated MA.operate!(-, poly2, 2)) == 0
7575
end
76+
77+
@testset "Polynomial + Variable" begin
78+
poly = 2 * x^2 + 3 * x * y + z * y^2
79+
poly2 = copy(poly)
80+
result = poly + x
81+
MA.operate!(+, poly, x)
82+
@test isequal(poly, result)
83+
# down from 18752 using the generic method
84+
# 368 or 304 depending on ordering
85+
@test (@allocated MA.operate!(+, poly2, x)) <= 368
86+
# down from 1904 using the generic method
87+
@test (@allocated MA.operate!(+, poly2, x)) <= 112
88+
89+
# also test `-`
90+
poly = 2 * x^2 + 3 * x * y + z * y^2
91+
poly2 = copy(poly)
92+
result = poly - x
93+
MA.operate!(-, poly, x)
94+
@test isequal(poly, result)
95+
# down from 18752 using the generic method
96+
# 368 or 304 depending on ordering
97+
@test (@allocated MA.operate!(-, poly2, x)) <= 368
98+
# down from 1904 using the generic method
99+
@test (@allocated MA.operate!(-, poly2, x)) <= 112
100+
end
76101
end

0 commit comments

Comments
 (0)