I’m far from being a compiler developer, but a behavior that I couldn’t find a way to mimic on Fortran is the possibility of obtaining recursive derivatives. With a simple example:
f(x, y) = 2 x^2 \cdot y \\ ~ \\
g(x, y) = \left(\frac{df}{dx}(x, y)\right)^2 \cdot \frac{x}{y}
And I want to obtain \frac{dg}{dx} automatically (without using the analytical \frac{df}{dx}). With usual forward diff
libraries this is not possible since they’re usually written like
type :: DualNumber
real :: value
real :: dx
end type
So when I extract dfdx
with something like f%dx
inside g(x, y)
, I lose track of the derivatives and can’t calculate dgdx
. In theory I could use recursive types to avoid that (and also get higher-order derivatives easily):
type :: DualNumber
real :: value
type(DualNumber), allocatable :: dx
end type
I have tried making this in a simple module just for testing, but I got horrible performances (both in memory and CPU time).
Meanwhile, in Julia I can do this:
using ForwardDiff
function f(x, y)
return 2*x^2 * y
end
dfdx(x, y) = ForwardDiff.derivative(x -> f(x, y), x)
function g(x, y)
return dfdx(x, y)^2 * x/y
end
dgdx(x, y) = ForwardDiff.derivative(x -> g(x, y), x)
And everything works fine (and fast). I think some simple interface like this for the end user would be astonishing!
I see that clad
(GitHub - vgvassilev/clad: clad -- automatic differentiation for C/C++) does source-to-source translation using the function’s AST, so maybe this could be possible with LFortran as well?
I had the idea of implementing some compile-time source-to-source translator, but unfortunately this exceeds my current knowledge