Skip to content

Commit 3ca468b

Browse files
committed
Improve multiplication with PolyVar, Monomial
1 parent 04a0d08 commit 3ca468b

File tree

1 file changed

+70
-27
lines changed

1 file changed

+70
-27
lines changed

src/alg.jl

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,37 +31,71 @@ function (*)(x::PolyVar, y::PolyVar)
3131
Monomial(x > y ? [x,y] : [y,x], [1,1])
3232
end
3333
end
34+
function multiplyvar(v, x)
35+
i = findfirst(w->w <= x, v)
36+
if i > 0 && v[i] == x
37+
# /!\ no copy done here for efficiency, do not mess up with vars
38+
w = v
39+
updatez = z -> begin
40+
newz = copy(z)
41+
newz[i] += 1
42+
newz
43+
end
44+
else
45+
n = length(v)
46+
if i == 0
47+
i = n+1
48+
end
49+
I = 1:i-1
50+
J = i:n
51+
K = J+1
52+
w = Vector{PolyVar}(n+1)
53+
w[I] = v[I]
54+
w[i] = x
55+
w[K] = v[J]
56+
updatez = z -> begin
57+
newz = Vector{Int}(n+1)
58+
newz[I] = z[I]
59+
newz[i] = 1
60+
newz[K] = z[J]
61+
newz
62+
end
63+
end
64+
w, updatez
65+
end
66+
function multiplymono(v, x)
67+
if v == x.vars
68+
# /!\ no copy done here for efficiency, do not mess up with vars
69+
w = v
70+
updatez = z -> z + x.z
71+
else
72+
w, maps = myunion([v, x.vars])
73+
updatez = z -> begin
74+
newz = zeros(Int, length(w))
75+
newz[maps[1]] += z
76+
newz[maps[2]] += x.z
77+
newz
78+
end
79+
end
80+
w, updatez
81+
end
3482
function (*)(x::PolyVar, y::Monomial)
35-
i = 1
36-
vars = y.vars
37-
n = length(vars)
38-
while i <= n && x < vars[i]
39-
i += 1
40-
end
41-
if i > n
42-
Monomial([vars; x], [y.z; 1])
43-
elseif x == vars[i]
44-
znew = copy(y.z)
45-
znew[i] += 1
46-
Monomial(vars, znew)
47-
else
48-
znew = copy(y.z)
49-
znew[i] += 1
50-
Monomial([vars[1:i-1]; x; vars[i:end]], [y.z[1:i-1]; 1; y.z[i:end]])
51-
end
83+
w, updatez = multiplyvar(y.vars, x)
84+
Monomial(w, updatez(y.z))
85+
end
86+
function (*)(x::PolyVar, y::MonomialVector)
87+
w, updatez = multiplyvar(y.vars, x)
88+
MonomialVector(w, updatez.(y.Z))
5289
end
53-
(*)(x::Monomial, y::PolyVar) = y * x
5490
function (*)(x::Monomial, y::Monomial)
55-
if x.vars == y.vars
56-
Monomial(x.vars, x.z + y.z)
57-
else
58-
allvars, maps = myunion([x.vars, y.vars])
59-
z = zeros(Int, length(allvars))
60-
z[maps[1]] += x.z
61-
z[maps[2]] += y.z
62-
Monomial(allvars, z)
63-
end
91+
w, updatez = multiplymono(y.vars, x)
92+
Monomial(w, updatez(y.z))
6493
end
94+
function (*)(x::Monomial, y::MonomialVector)
95+
w, updatez = multiplymono(y.vars, x)
96+
MonomialVector(w, updatez.(y.Z))
97+
end
98+
(*)(x::Monomial, y::PolyVar) = y * x
6599

66100
# non-PolyType * PolyType: specific methods for speed
67101
*(p::PolyType, α) = α * p
@@ -80,6 +114,15 @@ end
80114
*(p::PolyType, q::Term) = TermContainer(p) * q
81115
*(p::PolyType, q::VecPolynomial) = TermContainer(p) * q
82116

117+
# I do not want to cast x to TermContainer because that would force the promotion of eltype(q) with Int
118+
function *{S<:Union{PolyVar,Monomial}}(x::S, t::Term)
119+
Term(t.α, x*t.x)
120+
end
121+
function *{S<:Union{PolyVar,Monomial},T}(x::S, p::VecPolynomial{T})
122+
# /!\ No copy of a is done
123+
VecPolynomial{T}(p.a, x*p.x)
124+
end
125+
83126
# TermContainer * TermContainer
84127
*(x::Term, y::Term) = Term(x.α*y.α, x.x*y.x)
85128
*(p::VecPolynomial, t::Term) = t * p

0 commit comments

Comments
 (0)