JuliaDiff / ForwardDiff.jl

Forward Mode Automatic Differentiation for Julia
Other
883 stars 141 forks source link

Reinterpret discards information and returns incorrect result #701

Open antoine-levitt opened 3 months ago

antoine-levitt commented 3 months ago
using ForwardDiff
E(x) = abs2(x[1])
xf = randn(ComplexF64, 2)
# WRONG
r2c(x) = reinterpret(ComplexF64, x)
c2r(x) = reinterpret(Float64, x)
# # OK
# r2c(x) = x[1:2] + im*x[3:4]
# c2r(x) = vcat(real(x), imag(x))
ForwardDiff.gradient(x -> E(r2c(x)), c2r(x))
antoine-levitt commented 3 months ago

The issue appears to be this somewhat unfortunate interaction:

julia> reinterpret(ComplexF64, ForwardDiff.Dual(1.0,1.0))
1.0 + 1.0im
thomvet commented 2 months ago

Reinterpret just takes the number of bits of the ForwardDiff.Dual and makes them into a ComplexF64.

So, this result is very much expected and in my opinion not a bug.

antoine-levitt commented 2 months ago

It makes sense technically, but it also means that the above example will fail: reinterpret works on the dual data structure, which is unusual (most operations apply to the primal variable). Is there any use for reinterpreting a dual in this way?

KristofferC commented 2 months ago

There are many other cases like this. For example, eltype on a Vector{Dual{Float64}} will return Dual{Float64}. Or typeof of a dual number. At some point you have to be able to talk about the actual program that is running.