Promote big duals in ForwardDiff

I’m computing some derivatives of functions where the interior temporarily enters the realm of BigFloat,

using ForwardDiff
g(x) = float(log(exp(x*1e6)))
ForwardDiff.derivative(g, 1.0)
NaN

In this example, the exponent is too large for float. One can promote a scalar which isn’t a dual, which surprisingly works.

using ForwardDiff
g(x) = float(log(exp(x*big(1e6))))
ForwardDiff.derivative(g, 1.0)
1.0e+06

Computing a derivative with respect to a BigFloat also works,

g2(x) = float(log(exp(x*1e6)))
ForwardDiff.derivative(g2, big(1.0))
1.0e+06

However, a naive approach where one attempts to promote a dual does not work.

g(x) = float(log(exp(big(x)*1e6)))
ForwardDiff.derivative(g, 1.0)
ERROR: LoadError: MethodError: no method matching big(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(g),Float64},Float64,1})
Closest candidates are:
  big(::Type{Complex{T}}) where T<:Real at complex.jl:1018
  big(::Type{var"#s828"} where var"#s828"<:Integer) at gmp.jl:465
  big(::Type{var"#s828"} where var"#s828"<:Rational) at gmp.jl:466
  ...

A really naive definition would be to define

import Base: big
big(x::ForwardDiff.Dual{TG, T}) where {TG, T} = big(one(T)) * x

Since such promotion rules aren’t in ForwardDiff, I’m wondering if there are dangers associated with this latter approach?

3 Likes