Skip to content

Commit 34d0fea

Browse files
authored
Further allocation reduction in power computations (#361)
* working version with oop sqr! * Update Project.toml * Update src/TaylorSeries.jl * Update `zero(x)`; add in-place mul! for TaylorN * Get rid of most allocations in pow! for Taylor1{TaylorN{T}; add power_by_squaring!; add in-place sqr! method * Remove extra empty line * Add power_by_squaring methods to avoid method ambiguities (detected by Aqua) * Remove duplicated return * Add inbounds * Address review by @lbenet * Add extra arg to pow! * Update TaylorSeries IA extension * Update pow! and add fix suggested by @lbenet * Middle-of-the-road approach to suggestion by @lbenet * Handle pow! cases by dispatch-by-value * Remove unneeded deepcopy in setindex! method * Add `power_by_squaring(x, ::Val{3})` methods and add tests * Update comments * Bump patch version * Switch back from dispatch-by-value to if/else for pow! * Revert change in setindex! overload for Taylor1 * Add test for nested Taylor1s setindex! method * De-bump patch version * Another approach to suggestion by @lbenet * Fix typo * Fix another typo
1 parent 0585883 commit 34d0fea

File tree

12 files changed

+254
-67
lines changed

12 files changed

+254
-67
lines changed

ext/TaylorSeriesIAExt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function ^(a::Taylor1{Interval{T}}, r::S) where {T<:Real, S<:Real}
4141
c_order = l0 == 0 ? a.order : min(a.order, trunc(Int,r*a.order))
4242
c = Taylor1(zero(aux), c_order)
4343
for k = 0:c_order
44-
TS.pow!(c, aa, r, k)
44+
TS.pow!(c, aa, c, r, k)
4545
end
4646

4747
return c
@@ -66,7 +66,7 @@ function ^(a::TaylorN{Interval{T}}, r::S) where {T<:Real, S<:Real}
6666

6767
c = TaylorN( a0r, a.order)
6868
for ord in 1:a.order
69-
TS.pow!(c, aa, r, ord)
69+
TS.pow!(c, aa, c, r, ord)
7070
end
7171

7272
return c

src/arithmetic.jl

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@ for T in (:Taylor1, :HomogeneousPolynomial, :TaylorN)
162162
end
163163

164164
for T in (:Taylor1, :TaylorN)
165-
@eval zero(a::$T) = $T(zero.(a.coeffs))
165+
@eval function zero(a::$T)
166+
return $T(zero.(a.coeffs))
167+
end
166168
@eval function one(a::$T)
167169
b = zero(a)
168170
b[0] = one(b[0])
@@ -572,6 +574,42 @@ for T in (:Taylor1, :TaylorN)
572574
end
573575
end
574576

577+
# in-place product: `a` <- `a*b`
578+
# this method computes the product `a*b` and saves it back into `a`
579+
# assumes `a` and `b` are of same order
580+
function mul!(a::TaylorN{T}, b::TaylorN{T}) where {T<:Number}
581+
@inbounds for k in reverse(eachindex(a))
582+
mul!(a, a, b[0][1], k)
583+
for l in 1:k
584+
mul!(a[k], a[k-l], b[l])
585+
end
586+
end
587+
return nothing
588+
end
589+
function mul!(a::Taylor1{T}, b::Taylor1{T}) where {T<:Number}
590+
@inbounds for k in reverse(eachindex(a))
591+
# a[k] <- a[k]*b[0]
592+
mul!(a, a, b[0], k)
593+
for l in 1:k
594+
# a[k] <- a[k] + a[k-l] * b[l]
595+
a[k] += a[k-l] * b[l]
596+
end
597+
end
598+
return nothing
599+
end
600+
function mul!(a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}}) where {T<:NumberNotSeries}
601+
@inbounds for k in reverse(eachindex(a))
602+
mul!(a, a, b[0], k)
603+
for l in 1:k
604+
# a[k] += a[k-l] * b[l]
605+
for m in eachindex(a[k])
606+
mul!(a[k], a[k-l], b[l], m)
607+
end
608+
end
609+
end
610+
return nothing
611+
end
612+
575613
function mul!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}},
576614
ordT::Int) where {T<:NumberNotSeries}
577615
# Sanity

src/auxiliary.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ If the length of `coeffs` is smaller than `order+1`, it resizes
1717
function resize_coeffs1!(coeffs::Array{T,1}, order::Int) where {T<:Number}
1818
lencoef = length(coeffs)
1919
resize!(coeffs, order+1)
20+
c1 = coeffs[1]
2021
if order > lencoef-1
21-
z = zero(coeffs[1])
2222
@simd for ord in lencoef+1:order+1
23-
@inbounds coeffs[ord] = z
23+
@inbounds coeffs[ord] = zero(c1)
2424
end
2525
end
2626
return nothing
@@ -39,9 +39,9 @@ function resize_coeffsHP!(coeffs::Array{T,1}, order::Int) where {T<:Number}
3939
@assert order get_order() && lencoef num_coeffs
4040
num_coeffs == lencoef && return nothing
4141
resize!(coeffs, num_coeffs)
42-
z = zero(coeffs[1])
42+
c1 = coeffs[1]
4343
@simd for ord in lencoef+1:num_coeffs
44-
@inbounds coeffs[ord] = z
44+
@inbounds coeffs[ord] = zero(c1)
4545
end
4646
return nothing
4747
end

src/constructors.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ struct TaylorN{T<:Number} <: AbstractSeries{T}
156156
order :: Int
157157

158158
function TaylorN{T}(v::Array{HomogeneousPolynomial{T},1}, order::Int) where T<:Number
159-
coeffs = zeros(HomogeneousPolynomial{T}, order)
159+
coeffs = isempty(v) ? zeros(HomogeneousPolynomial{T}, order) : zeros(v[1], order)
160160
@inbounds for i in eachindex(v)
161161
ord = v[i].order
162162
if ord order

src/dictmutfunct.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const _dict_binary_ops = Dict(
6060
:- => (:subst!, (:_res, :_arg1, :_arg2, :_k), :(_res = _arg1 - _arg2)),
6161
:* => (:mul!, (:_res, :_arg1, :_arg2, :_k), :(_res = _arg1 * _arg2)),
6262
:/ => (:div!, (:_res, :_arg1, :_arg2, :_k), :(_res = _arg1 / _arg2)),
63-
:^ => (:pow!, (:_res, :_arg1, :_arg2, :_k), :(_res = _arg1 ^ float(_arg2))),
63+
:^ => (:pow!, (:_res, :_arg1, :_aux, :_arg2, :_k), :(_res = _arg1 ^ float(_arg2)), :(_aux = zero(_arg1))),
6464
);
6565

6666
"""
@@ -196,4 +196,3 @@ internal mutating functions.
196196
Evaluating the entries generates symbols that represent
197197
the actual calls to the internal mutating functions.
198198
""" _dict_binary_calls
199-

src/evaluate.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ function _evaluate!(suma::TaylorN{T}, a::HomogeneousPolynomial{T}, ind::Int,
413413
else
414414
for ordQ in eachindex(val)
415415
zero!(vv, ordQ)
416-
pow!(vv, val, vpow, ordQ)
416+
pow!(vv, val, vv, vpow, ordQ)
417417
end
418418
end
419419
for ordQ in eachindex(suma)

src/functions.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ end
303303
return nothing
304304
end
305305

306+
@inline function zero!(a::TaylorN{Taylor1{T}}) where {T<:NumberNotSeries}
307+
for k in eachindex(a)
308+
zero!(a, k)
309+
end
310+
return nothing
311+
end
312+
306313
@inline function one!(c::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeries}
307314
zero!(c, k)
308315
if k == 0
@@ -316,6 +323,13 @@ end
316323
return nothing
317324
end
318325

326+
@inline function identity!(c::HomogeneousPolynomial{Taylor1{T}}, a::HomogeneousPolynomial{Taylor1{T}}, k::Int) where {T<:NumberNotSeries}
327+
@inbounds for l in eachindex(c[k])
328+
identity!(c[k], a[k], l)
329+
end
330+
return nothing
331+
end
332+
319333
for T in (:Taylor1, :TaylorN)
320334
@eval begin
321335
@inline function identity!(c::$T{T}, a::$T{T}, k::Int) where {T<:NumberNotSeries}

0 commit comments

Comments
 (0)