SLEEF.jl
                                
                                 SLEEF.jl copied to clipboard
                                
                                    SLEEF.jl copied to clipboard
                            
                            
                            
                        Automatic derivatives of SLEEF trig functions cause stack-overflow
Not sure if this is a SLEEF problem for a ForwardDiff problem but I would have expected a different error than a stack overflow when trying to take automatic derivatives of SLEEF trig functions.
julia> using ForwardDiff: derivative
julia> using SLEEF
julia> derivative(SLEEF.sin, 1.0)
ERROR: StackOverflowError:
Stacktrace:
 [1] sin(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(SLEEF.sin),Float64},Float64,1}) at
/Users/mason/.julia/packages/SLEEF/pKpdp/src/SLEEF.jl:105 (repeats 80000 times)
Note: defining the action of trig functions on ForwardDiff.Duals does give the correct behaviour.
julia> using ForwardDiff: derivative, Dual, value, partials
julia> using SLEEF
julia> SLEEF.sin(d::Dual{T,V,N}) where {T,V,N} = Dual{T,V,N}(SLEEF.sin(value(d)), SLEEF.cos(value(d)) * partials(d))
julia> derivative(SLEEF.sin, 3.14)
-0.9999987317275395
can you try sin_fast ? (the fast trig function doesn't use a DualNumber wrapper, which may be causing the stack overflow)
julia> using ForwardDiff: derivative
julia> using SLEEF
julia> derivative(SLEEF.sin_fast, 1.0)
ERROR: StackOverflowError:
Stacktrace:
 [1] sin_fast(::Dual{ForwardDiff.Tag{typeof(SLEEF.sin_fast),Float64},Float64,1}) at 
/Users/mason/.julia/packages/SLEEF/pKpdp/src/SLEEF.jl:105 (repeats 80000 times)
Ref https://github.com/JuliaLang/julia/issues/26552, particularly https://github.com/JuliaLang/julia/issues/26552#issuecomment-374980927.
Ok thanks @tkoolen , it seems that this can be improved.
So I guess the best way of going about this is something like the following?
using ForwardDiff: derivative
f(x::Union{Float32,Float64}) = exp(x)
for func in (:f,)
    priv = Symbol('_',func)
    @eval begin
    $priv(x::T) where {T<:Union{Float32,Float64}} = $func(x)
    $func(x::Real) = $priv(float(x))
    end
end
julia> derivative(f, 1.0)
ERROR: MethodError: no method matching _f(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(f),Float64},Float64,1})
altough it's not clear to my why forwarddiff doesn't work without a custom wrapper.
I was puzzeled as to why the base math function worked with ForwardDiff, but now I see that ForwardDiff relies on DiffRules to be able to differentiate the base math functions.
In principle it should be able to support SLEEF, ideally without having to add anything to DiffRules, but I am not sure how to do that.
Is this the same reason SLEEF functions don't work with Zygote?
julia> Zygote.gradient(SLEEF.exp, 1.3)                                      
ERROR: Non-differentiable function Core.Intrinsics.bitcast