diff --git a/ext/ForwardDiffStaticArraysExt.jl b/ext/ForwardDiffStaticArraysExt.jl index 63f841db..fe65eb33 100644 --- a/ext/ForwardDiffStaticArraysExt.jl +++ b/ext/ForwardDiffStaticArraysExt.jl @@ -3,7 +3,7 @@ module ForwardDiffStaticArraysExt using ForwardDiff, StaticArrays using ForwardDiff.LinearAlgebra using ForwardDiff.DiffResults -using ForwardDiff: Dual, partials, GradientConfig, JacobianConfig, HessianConfig, Tag, Chunk, +using ForwardDiff: Dual, partials, Partials, GradientConfig, JacobianConfig, HessianConfig, Tag, Chunk, gradient, hessian, jacobian, gradient!, hessian!, jacobian!, extract_gradient!, extract_jacobian!, extract_value!, vector_mode_gradient, vector_mode_gradient!, @@ -81,6 +81,16 @@ end end end +@generated function extract_jacobian(::Type{T}, ydual::Partials{M}, x::S) where {M, T, S<:StaticArray} + N = length(x) + result = Expr(:tuple, [:(partials(T, ydual[$i], $j)) for i in 1:M, j in 1:N]...) + return quote + $(Expr(:meta, :inline)) + V = StaticArrays.similar_type(S, valtype(eltype($ydual)), Size($M, $N)) + return V($result) + end +end + @inline function ForwardDiff.vector_mode_jacobian(f::F, x::StaticArray) where {F} T = typeof(Tag(f, eltype(x))) return extract_jacobian(T, static_dual_eval(T, f, x), x) diff --git a/test/HessianTest.jl b/test/HessianTest.jl index 4c667e5e..9f12f91c 100644 --- a/test/HessianTest.jl +++ b/test/HessianTest.jl @@ -163,4 +163,13 @@ end @test ForwardDiff.hessian(x->dot(x,H,x), zeros(3)) ≈ [2 6 10; 6 10 14; 10 14 18] end +@testset "allocation-free hessian with StaticArrays" begin + #https://github.com/JuliaDiff/ForwardDiff.jl/issues/720 + g = r -> (r[1]^2 - 3) * (r[2]^2 - 2) + x = SA_F32[0.5, 2.7] + hres = DiffResults.HessianResult(x) + ForwardDiff.hessian!(hres, g, x) + @test @allocated(ForwardDiff.hessian!(hres, g, x)) == 0 +end + end # module