-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid some allocations in mutating methods #347
Changes from 14 commits
d8989a7
e1f39b3
fb339f6
bca5bb0
cdbb75e
7b3bf25
f60296e
75628c7
20771fc
0187b2d
90c5096
31ce07f
8443ff4
83c581c
e6d9167
c78eb49
b9f9b13
6f05d47
f07594f
20c20d0
a5fceb8
21b99b7
40b5267
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -482,7 +482,7 @@ end | |
function mul!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}}, | ||
ordT::Int) where {T<:NumberNotSeries} | ||
# Sanity | ||
zero!(res, a, ordT) | ||
zero!(res, ordT) | ||
for k in 0:ordT | ||
@inbounds for ordQ in eachindex(a[ordT]) | ||
mul!(res[ordT], a[k], b[ordT-k], ordQ) | ||
|
@@ -665,6 +665,19 @@ function /(a::Taylor1{TaylorN{T}}, b::Taylor1{TaylorN{T}}) where {T<:NumberNotSe | |
return res | ||
end | ||
|
||
function /(a::NumberNotSeries, b::Taylor1{TaylorN{T}}) where {T<:NumberNotSeries} | ||
iszero(a) && !iszero(b) && return zero(a) | ||
|
||
# order and coefficient of first factorized term | ||
# In this case, since a[k]=0 for k>0, we can simplify to: | ||
# ordfact, cdivfact = 0, a/b[0] | ||
|
||
res = Taylor1(a/b[0], b.order) | ||
for ordT in eachindex(res) | ||
div!(res, a, b, ordT) | ||
end | ||
return res | ||
end | ||
|
||
@inline function divfactorization(a1::Taylor1, b1::Taylor1) | ||
# order of first factorized term; a1 and b1 assumed to be of the same order | ||
|
@@ -731,8 +744,25 @@ end | |
return nothing | ||
end | ||
|
||
div!(v::Taylor1, b::NumberNotSeries, a::Taylor1, k::Int) = | ||
div!(v::Taylor1, Taylor1(b, a.order), a, k) | ||
@inline function div!(c::Taylor1, a::NumberNotSeries, | ||
b::Taylor1, k::Int) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we should impose There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, although I think we can make an extra tweak to avoid some allocations for |
||
iszero(a) && !iszero(b) && zero!(c, k) | ||
# order and coefficient of first factorized term | ||
# In this case, since a[k]=0 for k>0, we can simplify to: | ||
# ordfact, cdivfact = 0, a/b[0] | ||
if k == 0 | ||
@inbounds c[0] = a/b[0] | ||
return nothing | ||
end | ||
|
||
imin = max(0, k-b.order) | ||
PerezHz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@inbounds c[k] = c[imin] * b[k-imin] | ||
@inbounds for i = imin+1:k-1 | ||
c[k] += c[i] * b[k-i] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is related to the TODO above. We do have methods that indeed accumulate as mentioned above for TaylorN. I wonder if replacing this line with those methods can provide further improvements. The suggested code is: # c[k] += c[i] * b[k-i] # current code
for ord in eachindex(c[k])
mul!(c[k], c[i], b[k-i], ord)
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for the suggestion, I'll give it a try and see if we can get rid of some more allocations 😄 ! |
||
end | ||
@inbounds c[k] = -c[k]/b[0] | ||
return nothing | ||
end | ||
|
||
# NOTE: Here `div!` *accumulates* the result of a / b in c[k] (k > 0) | ||
@inline function div!(c::TaylorN, a::TaylorN, b::TaylorN, k::Int) | ||
|
@@ -758,7 +788,7 @@ end | |
@inbounds res[0] = cdivfact | ||
return nothing | ||
end | ||
zero!(res, a, ordT) | ||
zero!(res, ordT) | ||
imin = max(0, ordT+ordfact-b.order) | ||
aux = TaylorN(zero(a[ordT][0][1]), a[ordT].order) | ||
for k in imin:ordT-1 | ||
|
@@ -783,6 +813,48 @@ end | |
return nothing | ||
end | ||
|
||
@inline function mul!(res::Taylor1{TaylorN{T}}, a::NumberNotSeries, | ||
b::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeries} | ||
for l in eachindex(b[k]) | ||
for m in eachindex(b[k][l]) | ||
res[k][l][m] = a*b[k][l][m] | ||
end | ||
end | ||
return nothing | ||
end | ||
|
||
mul!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}}, | ||
b::NumberNotSeries, k::Int) where {T<:NumberNotSeries} = mul!(res, b, a, k) | ||
|
||
@inline function div!(res::Taylor1{TaylorN{T}}, a::Taylor1{TaylorN{T}}, | ||
b::NumberNotSeries, k::Int) where {T<:NumberNotSeries} | ||
for l in eachindex(a[k]) | ||
for m in eachindex(a[k][l]) | ||
res[k][l][m] = a[k][l][m]/b | ||
end | ||
end | ||
return nothing | ||
end | ||
|
||
# ### TODO: use non-allocating div!(::TaylorN,::TaylorN,::TaylorN) | ||
# @inline function div!(c::Taylor1{TaylorN{T}}, a::NumberNotSeries, | ||
# b::Taylor1{TaylorN{T}}, k::Int) where {T<:NumberNotSeries} | ||
# # order and coefficient of first factorized term | ||
# # In this case, since a[k]=0 for k>0, we can simplify to: | ||
# # ordfact, cdivfact = 0, a/b[0] | ||
# if k == 0 | ||
# @inbounds c[0] = a/b[0] | ||
# return nothing | ||
# end | ||
|
||
# imin = max(0, k-b.order) | ||
# @inbounds c[k] = c[imin] * b[k-imin] | ||
# @inbounds for i = imin+1:k-1 | ||
# c[k] += c[i] * b[k-i] | ||
# end | ||
# @inbounds c[k] = -c[k]/b[0] | ||
# return nothing | ||
# end | ||
|
||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose the following here to ensure type stability (this is untested)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that
a::NumberNotSeries
is perhaps too strong, because it leaves outsidea::TaylorN{T}
, which is a method worth having too.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion! I added the fix for type-stability and widened the type for
a
to allow forTaylorN{T}