Thanks for your in depth reply!
I implemented your suggestions. See below for appraisals + snippets.
- This improved performance to within a factor of ~1.5 of the others.
function work(fun::T, d::V) where {T<:Functionals.Abstract, V}
integrand(x::U) where {U<:Number} = kernel(x) * T(x, d)
return QuadGK.quadgk(integrand, fun.lower, fun.upper)[1]
end
-
Won’t do this one yet.
-
Same improvement as 1.
function work(fun::T, ∂::Bool) where {T<:Functionals.Abstract}
let
Δ = Val{∂}
integrand(x::U) where {U<:Number} = kernel(x) * T(x, Δ)
return QuadGK.quadgk(integrand, fun.lower, fun.upper)[1]
end
end
- Same improvement as 1.
function work(fun::T, ∂::Bool) where {T<:Functionals.Abstract}
function generateintegrand(v::V) where {V}
integrand(x::U) where {U<:Number} = kernel(x) * T(x, v)
return integrand
end
integrand = generateintegrand(Val{∂})
return QuadGK.quadgk(integrand, fun.lower, fun.upper)[1]
end
5a. Equal performance with other implementations.
function work(fun::T, ::Type{Val{false}}) where {T<:Functionals.Abstract}
integrand(x::U) where {U<:Number} = kernel(x) * T(x, Val{false})
return QuadGK.quadgk(integrand, fun.lower, fun.upper)[1]
end
function work(fun::T, ::Type{Val{true}}) where {T<:Functionals.Abstract}
integrand(x::U) where {U<:Number} = kernel(x) * T(x, Val{true})
return QuadGK.quadgk(integrand, fun.lower, fun.upper)[1]
end
5b. Equal performance with other implementations.
function work(fun::T, ∂::Bool) where {T<:Functionals.Abstract}
integrand(x::U) where {U<:Number} = ∂ ? kernel(x) * T(x, Val{true}) : kernel(x) * T(x, Val{false})
return QuadGK.quadgk(integrand, fun.lower, fun.upper)[1]
end
My favourite solution is 5b, which will then be easily change to 2.
In my opinion the OOP approach is easier than the more Julian way just because ::Type{Val{true}}
is complicated. If this is no longer required in 0.7 then I expect that the Julian method will be the easiest method for me.
edit: clarified language