ForwardDiff tagcount with custom diff rules

I think you probably want this:

function JacobiElliptic.CarlsonAlg.E(x::ForwardDiff.Dual{T}, y::ForwardDiff.Dual{T}) where {T}
    xval = x.value
    yval = y.value

    ∂yE = iszero(yval) ? -π/8 : (JacobiElliptic.CarlsonAlg.E(xval, yval)-JacobiElliptic.CarlsonAlg.F(xval, yval))/(2yval)
    ForwardDiff.Dual{T}(JacobiElliptic.CarlsonAlg.E(xval, yval), ForwardDiff.Partials(((sqrt(1-yval*sin(xval)^2)), ∂yE)))
end

Two different tags means these are independent perturbations, which will occur when taking second derivatives – and will result in nested Dual types:

julia> using ForwardDiff: Dual, Tag, derivative

julia> Dual(1,2) + Dual(3,5)  # first derivative, both arguments perturbed together
Dual{Nothing}(4,7)

julia> Dual{Tag{1,1}}(1,2) + Dual{Tag{2,2}}(3,5)  # second derivative, two indep perturbations
Dual{Tag{2, 2}}(Dual{Tag{1, 1}}(4,2),Dual{Tag{1, 1}}(5,0))

julia> Dual{Tag{2,2}}(1,2) + Dual{Tag{1,1}}(3,5)  # same, but organised differently
Dual{Tag{2, 2}}(Dual{Tag{1, 1}}(4,5),Dual{Tag{1, 1}}(2,0))
1 Like