JuliaDiff / ForwardDiff.jl

Forward Mode Automatic Differentiation for Julia
Other
892 stars 148 forks source link

StackOverflowError when differentiating a simple scalar function from SpecialFunctions.jl #567

Open Matematija opened 2 years ago

Matematija commented 2 years ago

Here is the MWE:

using ForwardDiff
using SpecialFunctions

log_i0(z::Number) = besseli(0,z) |> log
ForwardDiff.jacobian(x -> log_i0.(x), [1.1, 2.2, 3.3])

REPL output:

ERROR: LoadError: StackOverflowError:
Stacktrace:
 [1] besselix(nu::Int64, x::ForwardDiff.Dual{ForwardDiff.Tag{var"#8#9", Float64}, Float64, 3}) (repeats 79984 times)
   @ SpecialFunctions ~/.julia/packages/SpecialFunctions/NBIqR/src/bessel.jl:583
in expression starting at (...)

Interestingly,

ForwardDiff.jacobian(x -> log.(besseli.(0, x)), [1.1, 2.2, 3.3])

works great. Am I missing something super-obvious here? (My honest apologies if I am.)

Environment:

mcabbott commented 2 years ago

I think the stack overflow is telling you it's not supported.

The method is (I presume) meant to send besseli(0, 3) to besseli(0, 3.0), but instead catches dual numbers for which there is no more specific method:

https://github.com/JuliaMath/SpecialFunctions.jl/blob/master/src/bessel.jl#L583

There are methods accepting Dual only for certain Bessel functions:

https://github.com/JuliaDiff/DiffRules.jl/blob/master/src/rules.jl#L143-L150

Matematija commented 2 years ago

Okay, that makes sense, thank you. I am still confused as to why does the second example work without a problem then.