From 009dce884f5b971f5c8b3e81457d175d85e5a9a2 Mon Sep 17 00:00:00 2001 From: David Widmann Date: Mon, 7 Apr 2025 22:46:36 +0200 Subject: [PATCH] Fix seeding with undefined elements --- src/apiutils.jl | 56 +++++++++++++++++++++++++++++++++++++------- test/JacobianTest.jl | 14 +++++++++++ 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/apiutils.jl b/src/apiutils.jl index 39608d6c..f401a3fc 100644 --- a/src/apiutils.jl +++ b/src/apiutils.jl @@ -72,16 +72,36 @@ end function seed!(duals::AbstractArray{Dual{T,V,N}}, x, seed::Partials{N,V} = zero(Partials{N,V})) where {T,V,N} - for idx in structural_eachindex(duals, x) - duals[idx] = Dual{T,V,N}(x[idx], seed) + if isbitstype(V) + for idx in structural_eachindex(duals, x) + duals[idx] = Dual{T,V,N}(x[idx], seed) + end + else + for idx in structural_eachindex(duals, x) + if isassigned(x, idx) + duals[idx] = Dual{T,V,N}(x[idx], seed) + else + Base._unsetindex!(duals, idx) + end + end end return duals end function seed!(duals::AbstractArray{Dual{T,V,N}}, x, seeds::NTuple{N,Partials{N,V}}) where {T,V,N} - for (i, idx) in zip(1:N, structural_eachindex(duals, x)) - duals[idx] = Dual{T,V,N}(x[idx], seeds[i]) + if isbitstype(V) + for (i, idx) in zip(1:N, structural_eachindex(duals, x)) + duals[idx] = Dual{T,V,N}(x[idx], seeds[i]) + end + else + for (i, idx) in zip(1:N, structural_eachindex(duals, x)) + if isassigned(x, idx) + duals[idx] = Dual{T,V,N}(x[idx], seeds[i]) + else + Base._unsetindex!(duals, idx) + end + end end return duals end @@ -90,8 +110,18 @@ function seed!(duals::AbstractArray{Dual{T,V,N}}, x, index, seed::Partials{N,V} = zero(Partials{N,V})) where {T,V,N} offset = index - 1 idxs = Iterators.drop(structural_eachindex(duals, x), offset) - for idx in idxs - duals[idx] = Dual{T,V,N}(x[idx], seed) + if isbitstype(V) + for idx in idxs + duals[idx] = Dual{T,V,N}(x[idx], seed) + end + else + for idx in idxs + if isassigned(x, idx) + duals[idx] = Dual{T,V,N}(x[idx], seed) + else + Base._unsetindex!(duals, idx) + end + end end return duals end @@ -100,8 +130,18 @@ function seed!(duals::AbstractArray{Dual{T,V,N}}, x, index, seeds::NTuple{N,Partials{N,V}}, chunksize = N) where {T,V,N} offset = index - 1 idxs = Iterators.drop(structural_eachindex(duals, x), offset) - for (i, idx) in zip(1:chunksize, idxs) - duals[idx] = Dual{T,V,N}(x[idx], seeds[i]) + if isbitstype(V) + for (i, idx) in zip(1:chunksize, idxs) + duals[idx] = Dual{T,V,N}(x[idx], seeds[i]) + end + else + for (i, idx) in zip(1:chunksize, idxs) + if isassigned(x, idx) + duals[idx] = Dual{T,V,N}(x[idx], seeds[i]) + else + Base._unsetindex!(duals, idx) + end + end end return duals end diff --git a/test/JacobianTest.jl b/test/JacobianTest.jl index 1e52f7fa..76fa93ed 100644 --- a/test/JacobianTest.jl +++ b/test/JacobianTest.jl @@ -279,4 +279,18 @@ end end end +@testset "BigFloat" begin + # issues #436, #740 + for n in (2, 20) + x = BigFloat.(1:n) + @test x isa Vector{BigFloat} + y = similar(x) + @test !isassigned(y, 1) + res = ForwardDiff.jacobian(copyto!, y, x) + @test y == x + @test res isa Matrix{BigFloat} + @test res == I + end +end + end # module