Skip to content

Commit 7bb3714

Browse files
committed
Add polynomial!, in-place version of polynomial
1 parent 76ee2d0 commit 7bb3714

File tree

3 files changed

+29
-34
lines changed

3 files changed

+29
-34
lines changed

src/differentiation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ differentiate(α::T, v::AbstractVariable) where T = zero(T)
3737
differentiate(v1::AbstractVariable, v2::AbstractVariable) = v1 == v2 ? 1 : 0
3838
differentiate(t::AbstractTermLike, v::AbstractVariable) = coefficient(t) * differentiate(monomial(t), v)
3939
# The polynomial function will take care of removing the zeros
40-
differentiate(p::APL, v::AbstractVariable) = polynomial(differentiate.(terms(p), v), SortedState())
40+
differentiate(p::APL, v::AbstractVariable) = polynomial!(differentiate.(terms(p), v), SortedState())
4141
differentiate(p::RationalPoly, v::AbstractVariable) = (differentiate(p.num, v) * p.den - p.num * differentiate(p.den, v)) / p.den^2
4242

4343
const ARPL = Union{APL, RationalPoly}

src/operators.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,15 @@ function mul_to_terms!(ts::Vector{<:AbstractTerm}, p1::APL, p2::APL)
182182
return ts
183183
end
184184
function Base.:*(p::AbstractPolynomial, q::AbstractPolynomial)
185-
polynomial(mul_to_terms!(MA.promote_operation(*, termtype(p), termtype(q))[], p, q))
185+
polynomial!(mul_to_terms!(MA.promote_operation(*, termtype(p), termtype(q))[], p, q))
186186
end
187187

188188
Base.isapprox(p::APL, α; kwargs...) = isapprox(promote(p, α)...; kwargs...)
189189
Base.isapprox(α, p::APL; kwargs...) = isapprox(promote(p, α)...; kwargs...)
190190

191191
Base.:-(m::AbstractMonomialLike) = (-1) * m
192192
Base.:-(t::AbstractTermLike) = (-coefficient(t)) * monomial(t)
193-
Base.:-(p::APL) = polynomial((-).(terms(p)))
193+
Base.:-(p::APL) = polynomial!((-).(terms(p)))
194194
Base.:+(p::Union{APL, RationalPoly}) = p
195195
Base.:*(p::Union{APL, RationalPoly}) = p
196196

@@ -249,8 +249,8 @@ Base.:*(m::AbstractMonomialLike, t::AbstractTermLike) = coefficient(t) * (m * mo
249249
Base.:*(t::AbstractTermLike, m::AbstractMonomialLike) = coefficient(t) * (monomial(t) * m)
250250
Base.:*(t1::AbstractTermLike, t2::AbstractTermLike) = (coefficient(t1) * coefficient(t2)) * (monomial(t1) * monomial(t2))
251251

252-
Base.:*(t::AbstractTermLike, p::APL) = polynomial(map(te -> t * te, terms(p)))
253-
Base.:*(p::APL, t::AbstractTermLike) = polynomial(map(te -> te * t, terms(p)))
252+
Base.:*(t::AbstractTermLike, p::APL) = polynomial!(map(te -> t * te, terms(p)))
253+
Base.:*(p::APL, t::AbstractTermLike) = polynomial!(map(te -> te * t, terms(p)))
254254
Base.:*(p::APL, q::APL) = polynomial(p) * polynomial(q)
255255

256256
# guaranteed that monomial(t1) > monomial(t2)
@@ -260,6 +260,7 @@ function _polynomial_2terms(t1::TT, t2::TT, ::Type{T}) where {TT<:AbstractTerm,
260260
elseif iszero(t2)
261261
polynomial(t1, T)
262262
else
263+
# not `polynomial!` because we `t1` and `t2` cannot be modified
263264
polynomial(termtype(TT, T)[t1, t2], SortedUniqState())
264265
end
265266
end

src/polynomial.jl

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export polynomial, polynomialtype, terms, nterms, coefficients, monomials
1+
export polynomial, polynomial!, polynomialtype, terms, nterms, coefficients, monomials
22
export coefficienttype, monomialtype
33
export mindegree, maxdegree, extdegree
44
export leadingterm, leadingcoefficient, leadingmonomial
@@ -49,17 +49,32 @@ Calling `polynomial([2, 4, 1], [x, x^2*y, x*y])` should return ``4x^2y + xy + 2x
4949
polynomial(p::AbstractPolynomial) = p
5050
polynomial(p::APL{T}, ::Type{T}) where T = polynomial(terms(p))
5151
polynomial(p::APL{T}) where T = polynomial(p, T)
52-
polynomial(ts::AbstractVector, s::ListState=MessyState()) = sum(ts)
53-
polynomial(ts::AbstractVector{<:AbstractTerm}, s::SortedUniqState) = polynomial(coefficient.(ts), monomial.(ts), s)
54-
polynomial(a::AbstractVector, x::AbstractVector, s::ListState=MessyState()) = polynomial([α * m for (α, m) in zip(a, x)], s)
55-
polynomial(f::Function, mv::AbstractVector{<:AbstractMonomialLike}) = polynomial([f(i) * mv[i] for i in 1:length(mv)])
5652
function polynomial(Q::AbstractMatrix, mv::AbstractVector)
5753
LinearAlgebra.dot(mv, Q * mv)
5854
end
5955
function polynomial(Q::AbstractMatrix, mv::AbstractVector, ::Type{T}) where T
6056
polynomial(polynomial(Q, mv), T)
6157
end
6258

59+
polynomial(f::Function, mv::AbstractVector{<:AbstractMonomialLike}) = polynomial!([f(i) * mv[i] for i in 1:length(mv)])
60+
61+
polynomial(a::AbstractVector, x::AbstractVector, s::ListState=MessyState()) = polynomial([α * m for (α, m) in zip(a, x)], s)
62+
63+
polynomial(ts::AbstractVector, s::ListState=MessyState()) = sum(ts)
64+
65+
polynomial!(ts::AbstractVector{<:AbstractTerm}, s::SortedUniqState) = polynomial(coefficient.(ts), monomial.(ts), s)
66+
67+
function polynomial!(ts::AbstractVector{<:AbstractTerm}, s::SortedState)
68+
polynomial!(uniqterms!(ts), SortedUniqState())
69+
end
70+
function polynomial!(ts::AbstractVector{<:AbstractTerm}, s::UnsortedState=MessyState())
71+
polynomial!(sort!(ts, lt=(>)), sortstate(s))
72+
end
73+
74+
_collect(v::Vector) = v
75+
_collect(v::AbstractVector) = collect(v)
76+
polynomial(ts::AbstractVector{<:AbstractTerm}, args::Vararg{ListState, N}) where {N} = polynomial!(MA.mutable_copy(_collect(ts)), args...)
77+
6378
"""
6479
polynomialtype(p::AbstractPolynomialLike)
6580
@@ -85,25 +100,6 @@ polynomialtype(::Union{P, Type{P}}, ::Type{T}) where {P <: APL, T} = polynomialt
85100
polynomialtype(::Union{AbstractVector{PT}, Type{<:AbstractVector{PT}}}) where PT <: APL = polynomialtype(PT)
86101
polynomialtype(::Union{AbstractVector{PT}, Type{<:AbstractVector{PT}}}, ::Type{T}) where {PT <: APL, T} = polynomialtype(PT, T)
87102

88-
function uniqterms(ts::AbstractVector{T}) where T <: AbstractTerm
89-
result = T[]
90-
sizehint!(result, length(ts))
91-
for t in ts
92-
if !iszero(t)
93-
if isempty(result) || monomial(t) != monomial(last(result))
94-
push!(result, t)
95-
else
96-
coef = coefficient(last(result)) + coefficient(t)
97-
if iszero(coef)
98-
pop!(result)
99-
else
100-
result[end] = coef * monomial(t)
101-
end
102-
end
103-
end
104-
end
105-
result
106-
end
107103
function uniqterms!(ts::AbstractVector{<: AbstractTerm})
108104
i = firstindex(ts)
109105
for j in Iterators.drop(eachindex(ts), 1)
@@ -126,8 +122,6 @@ function uniqterms!(ts::AbstractVector{<: AbstractTerm})
126122
end
127123
ts
128124
end
129-
polynomial(ts::AbstractVector{<:AbstractTerm}, s::SortedState) = polynomial(uniqterms(ts), SortedUniqState())
130-
polynomial(ts::AbstractVector{<:AbstractTerm}, s::UnsortedState=MessyState()) = polynomial(sort(ts, lt=(>)), sortstate(s))
131125

132126
"""
133127
terms(p::AbstractPolynomialLike)
@@ -358,7 +352,7 @@ Returns `p / leadingcoefficient(p)` where the leading coefficient of the returne
358352
"""
359353
function monic(p::APL)
360354
α = leadingcoefficient(p)
361-
polynomial(_divtoone.(terms(p), α))
355+
polynomial!(_divtoone.(terms(p), α))
362356
end
363357
monic(m::AbstractMonomialLike) = m
364358
monic(t::AbstractTermLike{T}) where T = one(T) * monomial(t)
@@ -386,14 +380,14 @@ function mapcoefficientsnz(f::Function, p::AbstractPolynomialLike)
386380
# Invariant: p has only nonzero coefficient
387381
# therefore f(α) will be nonzero for every coefficient α of p
388382
# hence we can use Uniq
389-
polynomial(mapcoefficientsnz.(f, terms(p)), SortedUniqState())
383+
polynomial!(mapcoefficientsnz.(f, terms(p)), SortedUniqState())
390384
end
391385
mapcoefficientsnz(f::Function, t::AbstractTermLike) = f(coefficient(t)) * monomial(t)
392386

393387
Base.round(t::AbstractTermLike; args...) = round(coefficient(t); args...) * monomial(t)
394388
function Base.round(p::AbstractPolynomialLike; args...)
395389
# round(0.1) is zero so we cannot use SortedUniqState
396-
polynomial(round.(terms(p); args...), SortedState())
390+
polynomial!(round.(terms(p); args...), SortedState())
397391
end
398392

399393
Base.ndims(::Type{<:AbstractPolynomialLike}) = 0

0 commit comments

Comments
 (0)