From 7d0b12c8138d5b117f815939fbf015dad509f9c9 Mon Sep 17 00:00:00 2001 From: Chris Rackauckas Date: Fri, 17 Feb 2023 16:09:53 -0500 Subject: [PATCH 1/5] Turn StaticArrays into an Extension Pacakge omg so fast! no requires on v1.8 extension typo fix imports fix all tests fix the backwards compat with no requires add missing ones tag overload valtype add partials Update ext/ForwardDiffStaticArraysExt.jl Co-authored-by: David Widmann a few more imports finish the migration --- Project.toml | 9 +- ext/ForwardDiffStaticArraysExt.jl | 134 ++++++++++++++++++++++++++++++ src/ForwardDiff.jl | 5 +- src/apiutils.jl | 13 --- src/dual.jl | 13 --- src/gradient.jl | 27 ------ src/hessian.jl | 25 ------ src/jacobian.jl | 44 ---------- 8 files changed, 146 insertions(+), 124 deletions(-) create mode 100644 ext/ForwardDiffStaticArraysExt.jl diff --git a/Project.toml b/Project.toml index 1bd9a6ae..c902f996 100644 --- a/Project.toml +++ b/Project.toml @@ -28,12 +28,19 @@ SpecialFunctions = "0.8, 0.9, 0.10, 1.0, 2" StaticArrays = "0.8.3, 0.9, 0.10, 0.11, 0.12, 1.0" julia = "1" +[extensions] +ForwardDiffStaticArraysExt = "StaticArrays" + [extras] Calculus = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9" DiffTests = "de460e47-3fe3-5279-bb4a-814414816d5d" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Calculus", "DiffTests", "SparseArrays", "Test", "InteractiveUtils"] +test = ["Calculus", "DiffTests", "SparseArrays", "Test", "InteractiveUtils", "StaticArrays"] + +[weakdeps] +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" \ No newline at end of file diff --git a/ext/ForwardDiffStaticArraysExt.jl b/ext/ForwardDiffStaticArraysExt.jl new file mode 100644 index 00000000..cd2ec9cd --- /dev/null +++ b/ext/ForwardDiffStaticArraysExt.jl @@ -0,0 +1,134 @@ +module ForwardDiffStaticArraysExt + +using ForwardDiff +using ForwardDiff.DiffResults: DiffResults, DiffResult, ImmutableDiffResult, MutableDiffResult +using ForwardDiff.LinearAlgebra +import ForwardDiff: Dual, Chunk, value, extract_jacobian!, extract_value!, extract_gradient!, extract_jacobian!, + GradientConfig, JacobianConfig, HessianConfig, vector_mode_gradient, vector_mode_gradient!, + Tag, valtype, partials, gradient, gradient!, jacobian, jacobian!, hessian, hessian!, vector_mode_jacobian, + vector_mode_jacobian! +using StaticArrays + +@generated function dualize(::Type{T}, x::StaticArray) where T + N = length(x) + dx = Expr(:tuple, [:(Dual{T}(x[$i], chunk, Val{$i}())) for i in 1:N]...) + V = StaticArrays.similar_type(x, Dual{T,eltype(x),N}) + return quote + chunk = Chunk{$N}() + $(Expr(:meta, :inline)) + return $V($(dx)) + end +end + +@inline static_dual_eval(::Type{T}, f, x::StaticArray) where T = f(dualize(T, x)) + +@inline ForwardDiff.gradient(f, x::StaticArray) = vector_mode_gradient(f, x) +@inline ForwardDiff.gradient(f, x::StaticArray, cfg::GradientConfig) = gradient(f, x) +@inline ForwardDiff.gradient(f, x::StaticArray, cfg::GradientConfig, ::Val) = gradient(f, x) + +@inline ForwardDiff.gradient!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray) = vector_mode_gradient!(result, f, x) +@inline ForwardDiff.gradient!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::GradientConfig) = gradient!(result, f, x) +@inline ForwardDiff.gradient!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::GradientConfig, ::Val) = gradient!(result, f, x) + +@generated function extract_gradient(::Type{T}, y::Real, x::S) where {T,S<:StaticArray} + result = Expr(:tuple, [:(partials(T, y, $i)) for i in 1:length(x)]...) + return quote + $(Expr(:meta, :inline)) + V = StaticArrays.similar_type(S, valtype($y)) + return V($result) + end +end + +@inline function ForwardDiff.vector_mode_gradient(f, x::StaticArray) + T = typeof(Tag(f, eltype(x))) + return extract_gradient(T, static_dual_eval(T, f, x), x) +end + +@inline function ForwardDiff.vector_mode_gradient!(result, f, x::StaticArray) + T = typeof(Tag(f, eltype(x))) + return extract_gradient!(T, result, static_dual_eval(T, f, x)) +end + +@inline ForwardDiff.jacobian(f, x::StaticArray) = vector_mode_jacobian(f, x) +@inline ForwardDiff.jacobian(f, x::StaticArray, cfg::JacobianConfig) = jacobian(f, x) +@inline ForwardDiff.jacobian(f, x::StaticArray, cfg::JacobianConfig, ::Val) = jacobian(f, x) + +@inline ForwardDiff.jacobian!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray) = vector_mode_jacobian!(result, f, x) +@inline ForwardDiff.jacobian!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::JacobianConfig) = jacobian!(result, f, x) +@inline ForwardDiff.jacobian!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::JacobianConfig, ::Val) = jacobian!(result, f, x) + +@generated function extract_jacobian(::Type{T}, ydual::StaticArray, x::S) where {T,S<:StaticArray} + M, N = length(ydual), 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 + +function extract_jacobian(::Type{T}, ydual::AbstractArray, x::StaticArray) where T + result = similar(ydual, valtype(eltype(ydual)), length(ydual), length(x)) + return extract_jacobian!(T, result, ydual, length(x)) +end + +@inline function ForwardDiff.vector_mode_jacobian(f, x::StaticArray) + T = typeof(Tag(f, eltype(x))) + return extract_jacobian(T, static_dual_eval(T, f, x), x) +end + +@inline function ForwardDiff.vector_mode_jacobian!(result, f, x::StaticArray) + T = typeof(Tag(f, eltype(x))) + ydual = static_dual_eval(T, f, x) + result = extract_jacobian!(T, result, ydual, length(x)) + result = extract_value!(T, result, ydual) + return result +end + +@inline function ForwardDiff.vector_mode_jacobian!(result::ImmutableDiffResult, f, x::StaticArray) + T = typeof(Tag(f, eltype(x))) + ydual = static_dual_eval(T, f, x) + result = DiffResults.jacobian!(result, extract_jacobian(T, ydual, x)) + result = DiffResults.value!(d -> value(T,d), result, ydual) + return result +end + +ForwardDiff.hessian(f, x::StaticArray) = jacobian(y -> gradient(f, y), x) +ForwardDiff.hessian(f, x::StaticArray, cfg::HessianConfig) = hessian(f, x) +ForwardDiff.hessian(f, x::StaticArray, cfg::HessianConfig, ::Val) = hessian(f, x) + +ForwardDiff.hessian!(result::AbstractArray, f, x::StaticArray) = jacobian!(result, y -> gradient(f, y), x) + +ForwardDiff.hessian!(result::MutableDiffResult, f, x::StaticArray) = hessian!(result, f, x, HessianConfig(f, result, x)) + +ForwardDiff.hessian!(result::ImmutableDiffResult, f, x::StaticArray, cfg::HessianConfig) = hessian!(result, f, x) +ForwardDiff.hessian!(result::ImmutableDiffResult, f, x::StaticArray, cfg::HessianConfig, ::Val) = hessian!(result, f, x) + +function ForwardDiff.hessian!(result::ImmutableDiffResult, f, x::StaticArray) + T = typeof(Tag(f, eltype(x))) + d1 = dualize(T, x) + d2 = dualize(T, d1) + fd2 = f(d2) + val = value(T,value(T,fd2)) + grad = extract_gradient(T,value(T,fd2), x) + hess = extract_jacobian(T,partials(T,fd2), x) + result = DiffResults.hessian!(result, hess) + result = DiffResults.gradient!(result, grad) + result = DiffResults.value!(result, val) + return result +end + +function LinearAlgebra.eigvals(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} + λ,Q = eigen(Symmetric(value.(parent(A)))) + parts = ntuple(j -> diag(Q' * getindex.(partials.(A), j) * Q), N) + Dual{Tg}.(λ, tuple.(parts...)) +end + +function LinearAlgebra.eigen(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} + λ = eigvals(A) + _,Q = eigen(Symmetric(value.(parent(A)))) + parts = ntuple(j -> Q*ForwardDiff._lyap_div!(Q' * getindex.(partials.(A), j) * Q - Diagonal(getindex.(partials.(λ), j)), value.(λ)), N) + Eigen(λ,Dual{Tg}.(Q, tuple.(parts...))) +end + +end \ No newline at end of file diff --git a/src/ForwardDiff.jl b/src/ForwardDiff.jl index 93d3b246..fc89e104 100644 --- a/src/ForwardDiff.jl +++ b/src/ForwardDiff.jl @@ -2,7 +2,6 @@ module ForwardDiff using DiffRules, DiffResults using DiffResults: DiffResult, MutableDiffResult, ImmutableDiffResult -using StaticArrays if VERSION >= v"1.6" using Preferences end @@ -25,6 +24,10 @@ include("gradient.jl") include("jacobian.jl") include("hessian.jl") +if !isdefined(Base, :get_extension) + include("../ext/ForwardDiffStaticArraysExt.jl") +end + export DiffResults end # module diff --git a/src/apiutils.jl b/src/apiutils.jl index 971c368c..5a2a1df9 100644 --- a/src/apiutils.jl +++ b/src/apiutils.jl @@ -18,19 +18,6 @@ end # vector mode function evaluation # ################################### -@generated function dualize(::Type{T}, x::StaticArray) where T - N = length(x) - dx = Expr(:tuple, [:(Dual{T}(x[$i], chunk, Val{$i}())) for i in 1:N]...) - V = StaticArrays.similar_type(x, Dual{T,eltype(x),N}) - return quote - chunk = Chunk{$N}() - $(Expr(:meta, :inline)) - return $V($(dx)) - end -end - -@inline static_dual_eval(::Type{T}, f, x::StaticArray) where T = f(dualize(T, x)) - function vector_mode_dual_eval!(f::F, cfg::Union{JacobianConfig,GradientConfig}, x) where {F} xdual = cfg.duals seed!(xdual, x, cfg.seeds) diff --git a/src/dual.jl b/src/dual.jl index d5847083..c0fb4744 100644 --- a/src/dual.jl +++ b/src/dual.jl @@ -708,12 +708,6 @@ function LinearAlgebra.eigvals(A::Symmetric{<:Dual{Tg,T,N}}) where {Tg,T<:Real,N Dual{Tg}.(λ, tuple.(parts...)) end -function LinearAlgebra.eigvals(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} - λ,Q = eigen(Symmetric(value.(parent(A)))) - parts = ntuple(j -> diag(Q' * getindex.(partials.(A), j) * Q), N) - Dual{Tg}.(λ, tuple.(parts...)) -end - function LinearAlgebra.eigvals(A::Hermitian{<:Complex{<:Dual{Tg,T,N}}}) where {Tg,T<:Real,N} λ,Q = eigen(Hermitian(value.(real.(parent(A))) .+ im .* value.(imag.(parent(A))))) parts = ntuple(j -> diag(real.(Q' * (getindex.(partials.(real.(A)) .+ im .* partials.(imag.(A)), j)) * Q)), N) @@ -743,13 +737,6 @@ function LinearAlgebra.eigen(A::Symmetric{<:Dual{Tg,T,N}}) where {Tg,T<:Real,N} Eigen(λ,Dual{Tg}.(Q, tuple.(parts...))) end -function LinearAlgebra.eigen(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} - λ = eigvals(A) - _,Q = eigen(Symmetric(value.(parent(A)))) - parts = ntuple(j -> Q*_lyap_div!(Q' * getindex.(partials.(A), j) * Q - Diagonal(getindex.(partials.(λ), j)), value.(λ)), N) - Eigen(λ,Dual{Tg}.(Q, tuple.(parts...))) -end - function LinearAlgebra.eigen(A::SymTridiagonal{<:Dual{Tg,T,N}}) where {Tg,T<:Real,N} λ = eigvals(A) _,Q = eigen(SymTridiagonal(value.(parent(A)))) diff --git a/src/gradient.jl b/src/gradient.jl index f9f173eb..614bea67 100644 --- a/src/gradient.jl +++ b/src/gradient.jl @@ -41,29 +41,12 @@ function gradient!(result::Union{AbstractArray,DiffResult}, f::F, x::AbstractArr return result end -@inline gradient(f, x::StaticArray) = vector_mode_gradient(f, x) -@inline gradient(f, x::StaticArray, cfg::GradientConfig) = gradient(f, x) -@inline gradient(f, x::StaticArray, cfg::GradientConfig, ::Val) = gradient(f, x) - -@inline gradient!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray) = vector_mode_gradient!(result, f, x) -@inline gradient!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::GradientConfig) = gradient!(result, f, x) -@inline gradient!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::GradientConfig, ::Val) = gradient!(result, f, x) - gradient(f, x::Real) = throw(DimensionMismatch("gradient(f, x) expects that x is an array. Perhaps you meant derivative(f, x)?")) ##################### # result extraction # ##################### -@generated function extract_gradient(::Type{T}, y::Real, x::S) where {T,S<:StaticArray} - result = Expr(:tuple, [:(partials(T, y, $i)) for i in 1:length(x)]...) - return quote - $(Expr(:meta, :inline)) - V = StaticArrays.similar_type(S, valtype($y)) - return V($result) - end -end - function extract_gradient!(::Type{T}, result::DiffResult, y::Real) where {T} result = DiffResults.value!(result, y) grad = DiffResults.gradient(result) @@ -115,16 +98,6 @@ function vector_mode_gradient!(result, f::F, x, cfg::GradientConfig{T}) where {T return result end -@inline function vector_mode_gradient(f, x::StaticArray) - T = typeof(Tag(f, eltype(x))) - return extract_gradient(T, static_dual_eval(T, f, x), x) -end - -@inline function vector_mode_gradient!(result, f, x::StaticArray) - T = typeof(Tag(f, eltype(x))) - return extract_gradient!(T, result, static_dual_eval(T, f, x)) -end - ############## # chunk mode # ############## diff --git a/src/hessian.jl b/src/hessian.jl index 7de6109d..9a9c4f77 100644 --- a/src/hessian.jl +++ b/src/hessian.jl @@ -67,28 +67,3 @@ function hessian!(result::DiffResult, f, x::AbstractArray, cfg::HessianConfig{T} jacobian!(DiffResults.hessian(result), ∇f!, DiffResults.gradient(result), x, cfg.jacobian_config, Val{false}()) return ∇f!.result end - -hessian(f, x::StaticArray) = jacobian(y -> gradient(f, y), x) -hessian(f, x::StaticArray, cfg::HessianConfig) = hessian(f, x) -hessian(f, x::StaticArray, cfg::HessianConfig, ::Val) = hessian(f, x) - -hessian!(result::AbstractArray, f, x::StaticArray) = jacobian!(result, y -> gradient(f, y), x) - -hessian!(result::MutableDiffResult, f, x::StaticArray) = hessian!(result, f, x, HessianConfig(f, result, x)) - -hessian!(result::ImmutableDiffResult, f, x::StaticArray, cfg::HessianConfig) = hessian!(result, f, x) -hessian!(result::ImmutableDiffResult, f, x::StaticArray, cfg::HessianConfig, ::Val) = hessian!(result, f, x) - -function hessian!(result::ImmutableDiffResult, f, x::StaticArray) - T = typeof(Tag(f, eltype(x))) - d1 = dualize(T, x) - d2 = dualize(T, d1) - fd2 = f(d2) - val = value(T,value(T,fd2)) - grad = extract_gradient(T,value(T,fd2), x) - hess = extract_jacobian(T,partials(T,fd2), x) - result = DiffResults.hessian!(result, hess) - result = DiffResults.gradient!(result, grad) - result = DiffResults.value!(result, val) - return result -end diff --git a/src/jacobian.jl b/src/jacobian.jl index bcda61d7..cd417a79 100644 --- a/src/jacobian.jl +++ b/src/jacobian.jl @@ -82,35 +82,12 @@ function jacobian!(result::Union{AbstractArray,DiffResult}, f!, y::AbstractArray return result end -@inline jacobian(f, x::StaticArray) = vector_mode_jacobian(f, x) -@inline jacobian(f, x::StaticArray, cfg::JacobianConfig) = jacobian(f, x) -@inline jacobian(f, x::StaticArray, cfg::JacobianConfig, ::Val) = jacobian(f, x) - -@inline jacobian!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray) = vector_mode_jacobian!(result, f, x) -@inline jacobian!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::JacobianConfig) = jacobian!(result, f, x) -@inline jacobian!(result::Union{AbstractArray,DiffResult}, f, x::StaticArray, cfg::JacobianConfig, ::Val) = jacobian!(result, f, x) - jacobian(f, x::Real) = throw(DimensionMismatch("jacobian(f, x) expects that x is an array. Perhaps you meant derivative(f, x)?")) ##################### # result extraction # ##################### -@generated function extract_jacobian(::Type{T}, ydual::StaticArray, x::S) where {T,S<:StaticArray} - M, N = length(ydual), 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 - -function extract_jacobian(::Type{T}, ydual::AbstractArray, x::StaticArray) where T - result = similar(ydual, valtype(eltype(ydual)), length(ydual), length(x)) - return extract_jacobian!(T, result, ydual, length(x)) -end - function extract_jacobian!(::Type{T}, result::AbstractArray, ydual::AbstractArray, n) where {T} out_reshaped = reshape(result, length(ydual), n) ydual_reshaped = vec(ydual) @@ -180,27 +157,6 @@ function vector_mode_jacobian!(result, f!::F, y, x, cfg::JacobianConfig{T}) wher return result end -@inline function vector_mode_jacobian(f, x::StaticArray) - T = typeof(Tag(f, eltype(x))) - return extract_jacobian(T, static_dual_eval(T, f, x), x) -end - -@inline function vector_mode_jacobian!(result, f, x::StaticArray) - T = typeof(Tag(f, eltype(x))) - ydual = static_dual_eval(T, f, x) - result = extract_jacobian!(T, result, ydual, length(x)) - result = extract_value!(T, result, ydual) - return result -end - -@inline function vector_mode_jacobian!(result::ImmutableDiffResult, f, x::StaticArray) - T = typeof(Tag(f, eltype(x))) - ydual = static_dual_eval(T, f, x) - result = DiffResults.jacobian!(result, extract_jacobian(T, ydual, x)) - result = DiffResults.value!(d -> value(T,d), result, ydual) - return result -end - const JACOBIAN_ERROR = DimensionMismatch("jacobian(f, x) expects that f(x) is an array. Perhaps you meant gradient(f, x)?") # chunk mode # From 1728e0fba79d5b9aaee2570bbb3c094da75e33ea Mon Sep 17 00:00:00 2001 From: Chris Rackauckas Date: Sun, 19 Feb 2023 16:12:40 -0500 Subject: [PATCH 2/5] Match the other PR in form --- ext/ForwardDiffStaticArraysExt.jl | 43 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/ext/ForwardDiffStaticArraysExt.jl b/ext/ForwardDiffStaticArraysExt.jl index cd2ec9cd..367a3b2b 100644 --- a/ext/ForwardDiffStaticArraysExt.jl +++ b/ext/ForwardDiffStaticArraysExt.jl @@ -1,12 +1,12 @@ module ForwardDiffStaticArraysExt -using ForwardDiff -using ForwardDiff.DiffResults: DiffResults, DiffResult, ImmutableDiffResult, MutableDiffResult -using ForwardDiff.LinearAlgebra -import ForwardDiff: Dual, Chunk, value, extract_jacobian!, extract_value!, extract_gradient!, extract_jacobian!, - GradientConfig, JacobianConfig, HessianConfig, vector_mode_gradient, vector_mode_gradient!, - Tag, valtype, partials, gradient, gradient!, jacobian, jacobian!, hessian, hessian!, vector_mode_jacobian, - vector_mode_jacobian! +using ForwardDiff, StaticArrays, LinearAlgebra, DiffResults +using ForwardDiff: Dual, partials, GradientConfig, JacobianConfig, HessianConfig, Tag, Chunk, + gradient, hessian, jacobian, gradient!, hessian!, jacobian!, + extract_gradient!, extract_jacobian!, extract_value!, + vector_mode_gradient, vector_mode_gradient!, + vector_mode_jacobian, vector_mode_jacobian!, valtype, value, _lyap_div! +using DiffResults: DiffResult, ImmutableDiffResult, MutableDiffResult using StaticArrays @generated function dualize(::Type{T}, x::StaticArray) where T @@ -22,6 +22,20 @@ end @inline static_dual_eval(::Type{T}, f, x::StaticArray) where T = f(dualize(T, x)) +function LinearAlgebra.eigvals(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} + λ,Q = eigen(Symmetric(value.(parent(A)))) + parts = ntuple(j -> diag(Q' * getindex.(partials.(A), j) * Q), N) + Dual{Tg}.(λ, tuple.(parts...)) +end + +function LinearAlgebra.eigen(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} + λ = eigvals(A) + _,Q = eigen(Symmetric(value.(parent(A)))) + parts = ntuple(j -> Q*ForwardDiff._lyap_div!(Q' * getindex.(partials.(A), j) * Q - Diagonal(getindex.(partials.(λ), j)), value.(λ)), N) + Eigen(λ,Dual{Tg}.(Q, tuple.(parts...))) +end + +# Gradient @inline ForwardDiff.gradient(f, x::StaticArray) = vector_mode_gradient(f, x) @inline ForwardDiff.gradient(f, x::StaticArray, cfg::GradientConfig) = gradient(f, x) @inline ForwardDiff.gradient(f, x::StaticArray, cfg::GradientConfig, ::Val) = gradient(f, x) @@ -49,6 +63,7 @@ end return extract_gradient!(T, result, static_dual_eval(T, f, x)) end +# Jacobian @inline ForwardDiff.jacobian(f, x::StaticArray) = vector_mode_jacobian(f, x) @inline ForwardDiff.jacobian(f, x::StaticArray, cfg::JacobianConfig) = jacobian(f, x) @inline ForwardDiff.jacobian(f, x::StaticArray, cfg::JacobianConfig, ::Val) = jacobian(f, x) @@ -93,6 +108,7 @@ end return result end +# Hessian ForwardDiff.hessian(f, x::StaticArray) = jacobian(y -> gradient(f, y), x) ForwardDiff.hessian(f, x::StaticArray, cfg::HessianConfig) = hessian(f, x) ForwardDiff.hessian(f, x::StaticArray, cfg::HessianConfig, ::Val) = hessian(f, x) @@ -118,17 +134,4 @@ function ForwardDiff.hessian!(result::ImmutableDiffResult, f, x::StaticArray) return result end -function LinearAlgebra.eigvals(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} - λ,Q = eigen(Symmetric(value.(parent(A)))) - parts = ntuple(j -> diag(Q' * getindex.(partials.(A), j) * Q), N) - Dual{Tg}.(λ, tuple.(parts...)) -end - -function LinearAlgebra.eigen(A::Symmetric{<:Dual{Tg,T,N}, <:StaticArrays.StaticMatrix}) where {Tg,T<:Real,N} - λ = eigvals(A) - _,Q = eigen(Symmetric(value.(parent(A)))) - parts = ntuple(j -> Q*ForwardDiff._lyap_div!(Q' * getindex.(partials.(A), j) * Q - Diagonal(getindex.(partials.(λ), j)), value.(λ)), N) - Eigen(λ,Dual{Tg}.(Q, tuple.(parts...))) -end - end \ No newline at end of file From 7e090cbee8186a15fc20e0a91c9f6214a1ed32c1 Mon Sep 17 00:00:00 2001 From: Chris Rackauckas Date: Sun, 19 Feb 2023 16:20:02 -0500 Subject: [PATCH 3/5] remove duplicate using --- ext/ForwardDiffStaticArraysExt.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/ForwardDiffStaticArraysExt.jl b/ext/ForwardDiffStaticArraysExt.jl index 367a3b2b..4a5677aa 100644 --- a/ext/ForwardDiffStaticArraysExt.jl +++ b/ext/ForwardDiffStaticArraysExt.jl @@ -7,7 +7,6 @@ using ForwardDiff: Dual, partials, GradientConfig, JacobianConfig, HessianConfig vector_mode_gradient, vector_mode_gradient!, vector_mode_jacobian, vector_mode_jacobian!, valtype, value, _lyap_div! using DiffResults: DiffResult, ImmutableDiffResult, MutableDiffResult -using StaticArrays @generated function dualize(::Type{T}, x::StaticArray) where T N = length(x) From 4b1fab18d55decb50b31c4e51d2812cc1834d145 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sun, 19 Feb 2023 16:21:14 -0500 Subject: [PATCH 4/5] Update src/ForwardDiff.jl --- src/ForwardDiff.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ForwardDiff.jl b/src/ForwardDiff.jl index fc89e104..a27d6dba 100644 --- a/src/ForwardDiff.jl +++ b/src/ForwardDiff.jl @@ -1,7 +1,7 @@ module ForwardDiff using DiffRules, DiffResults -using DiffResults: DiffResult, MutableDiffResult, ImmutableDiffResult +using DiffResults: DiffResult, MutableDiffResult if VERSION >= v"1.6" using Preferences end From bc3a395c9a87b1a7d5f1a884a8180ab1b6bdd04a Mon Sep 17 00:00:00 2001 From: Chris Rackauckas Date: Sun, 19 Feb 2023 17:23:35 -0500 Subject: [PATCH 5/5] only import ForwardDiff and StaticArrays --- ext/ForwardDiffStaticArraysExt.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/ForwardDiffStaticArraysExt.jl b/ext/ForwardDiffStaticArraysExt.jl index 4a5677aa..cb9222ff 100644 --- a/ext/ForwardDiffStaticArraysExt.jl +++ b/ext/ForwardDiffStaticArraysExt.jl @@ -1,6 +1,8 @@ module ForwardDiffStaticArraysExt -using ForwardDiff, StaticArrays, LinearAlgebra, DiffResults +using ForwardDiff, StaticArrays +using ForwardDiff.LinearAlgebra +using ForwardDiff.DiffResults using ForwardDiff: Dual, partials, GradientConfig, JacobianConfig, HessianConfig, Tag, Chunk, gradient, hessian, jacobian, gradient!, hessian!, jacobian!, extract_gradient!, extract_jacobian!, extract_value!,