Skip to content

Commit e670596

Browse files
authored
Fix seeding with undefined elements (#743)
* Fix seeding with undefined elements * Extend tests to cover all branches * Bump version to 1.0.2
1 parent fbf48ae commit e670596

File tree

3 files changed

+78
-9
lines changed

3 files changed

+78
-9
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ForwardDiff"
22
uuid = "f6369f11-7733-5829-9624-2563aa707210"
3-
version = "1.0.1"
3+
version = "1.0.2"
44

55
[deps]
66
CommonSubexpressions = "bbf7d656-a473-5ed7-a52c-81e309532950"

src/apiutils.jl

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,36 @@ end
7272

7373
function seed!(duals::AbstractArray{Dual{T,V,N}}, x,
7474
seed::Partials{N,V} = zero(Partials{N,V})) where {T,V,N}
75-
for idx in structural_eachindex(duals, x)
76-
duals[idx] = Dual{T,V,N}(x[idx], seed)
75+
if isbitstype(V)
76+
for idx in structural_eachindex(duals, x)
77+
duals[idx] = Dual{T,V,N}(x[idx], seed)
78+
end
79+
else
80+
for idx in structural_eachindex(duals, x)
81+
if isassigned(x, idx)
82+
duals[idx] = Dual{T,V,N}(x[idx], seed)
83+
else
84+
Base._unsetindex!(duals, idx)
85+
end
86+
end
7787
end
7888
return duals
7989
end
8090

8191
function seed!(duals::AbstractArray{Dual{T,V,N}}, x,
8292
seeds::NTuple{N,Partials{N,V}}) where {T,V,N}
83-
for (i, idx) in zip(1:N, structural_eachindex(duals, x))
84-
duals[idx] = Dual{T,V,N}(x[idx], seeds[i])
93+
if isbitstype(V)
94+
for (i, idx) in zip(1:N, structural_eachindex(duals, x))
95+
duals[idx] = Dual{T,V,N}(x[idx], seeds[i])
96+
end
97+
else
98+
for (i, idx) in zip(1:N, structural_eachindex(duals, x))
99+
if isassigned(x, idx)
100+
duals[idx] = Dual{T,V,N}(x[idx], seeds[i])
101+
else
102+
Base._unsetindex!(duals, idx)
103+
end
104+
end
85105
end
86106
return duals
87107
end
@@ -90,8 +110,18 @@ function seed!(duals::AbstractArray{Dual{T,V,N}}, x, index,
90110
seed::Partials{N,V} = zero(Partials{N,V})) where {T,V,N}
91111
offset = index - 1
92112
idxs = Iterators.drop(structural_eachindex(duals, x), offset)
93-
for idx in idxs
94-
duals[idx] = Dual{T,V,N}(x[idx], seed)
113+
if isbitstype(V)
114+
for idx in idxs
115+
duals[idx] = Dual{T,V,N}(x[idx], seed)
116+
end
117+
else
118+
for idx in idxs
119+
if isassigned(x, idx)
120+
duals[idx] = Dual{T,V,N}(x[idx], seed)
121+
else
122+
Base._unsetindex!(duals, idx)
123+
end
124+
end
95125
end
96126
return duals
97127
end
@@ -100,8 +130,18 @@ function seed!(duals::AbstractArray{Dual{T,V,N}}, x, index,
100130
seeds::NTuple{N,Partials{N,V}}, chunksize = N) where {T,V,N}
101131
offset = index - 1
102132
idxs = Iterators.drop(structural_eachindex(duals, x), offset)
103-
for (i, idx) in zip(1:chunksize, idxs)
104-
duals[idx] = Dual{T,V,N}(x[idx], seeds[i])
133+
if isbitstype(V)
134+
for (i, idx) in zip(1:chunksize, idxs)
135+
duals[idx] = Dual{T,V,N}(x[idx], seeds[i])
136+
end
137+
else
138+
for (i, idx) in zip(1:chunksize, idxs)
139+
if isassigned(x, idx)
140+
duals[idx] = Dual{T,V,N}(x[idx], seeds[i])
141+
else
142+
Base._unsetindex!(duals, idx)
143+
end
144+
end
105145
end
106146
return duals
107147
end

test/JacobianTest.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,33 @@ end
279279
end
280280
end
281281

282+
# issues #436, #740
283+
@testset "BigFloat" begin
284+
# Unassigned entries in the output
285+
x = BigFloat.(1:9)
286+
for chunksize in (1, 2, 9)
287+
y = similar(x)
288+
@test all(i -> !isassigned(y, i), eachindex(y))
289+
cfg = ForwardDiff.JacobianConfig(copyto!, y, x, ForwardDiff.Chunk{chunksize}())
290+
res = ForwardDiff.jacobian(copyto!, y, x, cfg)
291+
@test y == x
292+
@test res isa Matrix{BigFloat}
293+
@test res == I
294+
end
295+
296+
# Unassigned (but unused) entry in the input and unassigned entries in the output
297+
resize!(x, 10)
298+
f = (y, x) -> copyto!(y, 1, x, 1, 9)
299+
for chunksize in (1, 2, 10)
300+
y = similar(x, 9)
301+
@test all(i -> !isassigned(y, i), eachindex(y))
302+
cfg = ForwardDiff.JacobianConfig(f, y, x, ForwardDiff.Chunk{chunksize}())
303+
res = ForwardDiff.jacobian(f, y, x, cfg)
304+
@test y == x[1:(end-1)]
305+
@test res isa Matrix{BigFloat}
306+
@test res[:, 1:(end-1)] == I
307+
@test all(iszero, res[:, end])
308+
end
309+
end
310+
282311
end # module

0 commit comments

Comments
 (0)