Hi! I am having trouble with the type stability of quadgk when the integrand function is using quadgk itself. Here is the MWE:
using QuadGK
f(x) = quadgk(y -> x*y, 0., 1.)[1]
quadgk(f, 0., 1.)
Using code_warntype on the latter function gives that the return type is Tuple{Any, Any}
:
julia> @code_warntype quadgk(f, 0., 1.)
MethodInstance for QuadGK.quadgk(::typeof(f), ::Float64, ::Float64)
from quadgk(f, segs::T...; atol, rtol, maxevals, order, norm, segbuf, eval_segbuf) where T @ QuadGK ~/.julia/packages/QuadGK/7rND3/src/api.jl:80
Static Parameters
T = Float64
Arguments
#self#::Core.Const(QuadGK.quadgk)
f::Core.Const(f)
segs::Tuple{Float64, Float64}
Locals
atol::Nothing
rtol::Nothing
maxevals::Int64
order::Int64
norm::typeof(LinearAlgebra.norm)
segbuf::Nothing
eval_segbuf::Nothing
Body::Tuple{Any, Any}
1 β %1 = QuadGK.nothing::Core.Const(nothing)
β (atol = %1)
β %3 = QuadGK.nothing::Core.Const(nothing)
β (rtol = %3)
β %5 = QuadGK.:^::Core.Const(^)
β %6 = Core.apply_type(Base.Val, 7)::Core.Const(Val{7})
β %7 = (%6)()::Core.Const(Val{7}())
β %8 = Base.literal_pow(%5, 10, %7)::Core.Const(10000000)
β (maxevals = %8)
β %10 = 7::Core.Const(7)
β (order = %10)
β %12 = QuadGK.norm::Core.Const(LinearAlgebra.norm)
β (norm = %12)
β %14 = QuadGK.nothing::Core.Const(nothing)
β (segbuf = %14)
β %16 = QuadGK.nothing::Core.Const(nothing)
β (eval_segbuf = %16)
β %18 = QuadGK.:(var"#quadgk#49")::Core.Const(QuadGK.var"#quadgk#49")
β %19 = Core.tuple(atol, rtol, maxevals::Core.Const(10000000), order::Core.Const(7), norm, segbuf, eval_segbuf, #self#, f)::Core.Const((nothing, nothing, 10000000, 7, LinearAlgebra.norm, nothing, nothing, QuadGK.quadgk, f))
β %20 = Core._apply_iterate(Base.iterate, %18, %19, segs)::Tuple{Any, Any}
βββ return %20
I initially thought that maybe this was due to performance of captured variables in closures Β· Issue #15276 Β· JuliaLang/julia Β· GitHub, but the usual fix does not seem to help:
function g(x)
G = let x=x
y -> x*y
end
quadgk(G, 0., 1.)[1]
end
quadgk(g, 0., 1.)
The code_warntype here shows the same type unstable result Tuple{Any, Any}
:
julia> @code_warntype quadgk(g, 0., 1.)
MethodInstance for QuadGK.quadgk(::typeof(g), ::Float64, ::Float64)
from quadgk(f, segs::T...; atol, rtol, maxevals, order, norm, segbuf, eval_segbuf) where T @ QuadGK ~/.julia/packages/QuadGK/7rND3/src/api.jl:80
Static Parameters
T = Float64
Arguments
#self#::Core.Const(QuadGK.quadgk)
f::Core.Const(g)
segs::Tuple{Float64, Float64}
Locals
atol::Nothing
rtol::Nothing
maxevals::Int64
order::Int64
norm::typeof(LinearAlgebra.norm)
segbuf::Nothing
eval_segbuf::Nothing
Body::Tuple{Any, Any}
1 β %1 = QuadGK.nothing::Core.Const(nothing)
β (atol = %1)
β %3 = QuadGK.nothing::Core.Const(nothing)
β (rtol = %3)
β %5 = QuadGK.:^::Core.Const(^)
β %6 = Core.apply_type(Base.Val, 7)::Core.Const(Val{7})
β %7 = (%6)()::Core.Const(Val{7}())
β %8 = Base.literal_pow(%5, 10, %7)::Core.Const(10000000)
β (maxevals = %8)
β %10 = 7::Core.Const(7)
β (order = %10)
β %12 = QuadGK.norm::Core.Const(LinearAlgebra.norm)
β (norm = %12)
β %14 = QuadGK.nothing::Core.Const(nothing)
β (segbuf = %14)
β %16 = QuadGK.nothing::Core.Const(nothing)
β (eval_segbuf = %16)
β %18 = QuadGK.:(var"#quadgk#49")::Core.Const(QuadGK.var"#quadgk#49")
β %19 = Core.tuple(atol, rtol, maxevals::Core.Const(10000000), order::Core.Const(7), norm, segbuf, eval_segbuf, #self#, f)::Core.Const((nothing, nothing, 10000000, 7, LinearAlgebra.norm, nothing, nothing, QuadGK.quadgk, g))
β %20 = Core._apply_iterate(Base.iterate, %18, %19, segs)::Tuple{Any, Any}
βββ return %20
Both f
and g
seem to be type-stable. Is there something I am missing here?