Wow, that was awesomely easy. I think I did it right, although I’m only just using Flux for the first time:
using QuadGK
using Flux
using Flux.Tracker: TrackedReal, @grad, data, track, gradient
myquad(f, a, b) = quadgk(f,a,b)[1]
myquad(f, a::TrackedReal, b::TrackedReal) = track(myquad, f, a, b)
myquad(f, a , b::TrackedReal) = track(myquad, f, a, b)
myquad(f, a::TrackedReal, b ) = track(myquad, f, a, b)
@grad myquad(f, a, b) = myquad(f, data(a), data(b)), Δ -> (nothing, -Δ*f(a), Δ*f(b))
f(x) = 2*myquad(x->x^2,x,0)
f′(x) = gradient(f, x)[1]
f′′(x) = gradient(f′, x)[1]
f(1) # -0.6666666666666666
f′(1.) # -2.0 (tracked)
f′′(1.) # -4.0 (tracked)
I wonder whether type stability is possible, but I should probably just go read the Flux docs…
I am curious if the other tools have something like this, I was not able to find it in ForwardDiff.jl/ReverseDiff.jl.