diff --git a/Project.toml b/Project.toml index d0138ce0..fa3e86f8 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ForwardDiff" uuid = "f6369f11-7733-5829-9624-2563aa707210" -version = "1.3.2" +version = "1.3.3" [deps] CommonSubexpressions = "bbf7d656-a473-5ed7-a52c-81e309532950" diff --git a/src/jacobian.jl b/src/jacobian.jl index b12142a3..b8ce58fb 100644 --- a/src/jacobian.jl +++ b/src/jacobian.jl @@ -93,7 +93,7 @@ jacobian(f, x::Real) = throw(DimensionMismatch("jacobian(f, x) expects that x is ##################### function extract_jacobian!(::Type{T}, result::AbstractArray, ydual::AbstractArray, n) where {T} - out_reshaped = reshape(result, length(ydual), n) + out_reshaped = result isa AbstractMatrix ? result : reshape(result, length(ydual), n) ydual_reshaped = vec(ydual) # Use closure to avoid GPU broadcasting with Type partials_wrap(ydual, nrange) = partials(T, ydual, nrange) diff --git a/test/AllocationsTest.jl b/test/AllocationsTest.jl index 9e7c38be..36df8eba 100644 --- a/test/AllocationsTest.jl +++ b/test/AllocationsTest.jl @@ -28,4 +28,20 @@ convert_test_574() = convert(ForwardDiff.Dual{Nothing,ForwardDiff.Dual{Nothing,F @test iszero(allocs_convert_test_574()) end +@testset "Test jacobian! allocations" begin + # jacobian! should not allocate when called with a pre-allocated result Matrix. + # Previously, reshape() inside extract_jacobian! allocated a wrapper + # object that could not be elided under --check-bounds=yes. + function allocs_jacobian!() + f!(y, x) = (y .= x .^ 2) + x = [1.0, 2.0, 3.0] + y = similar(x) + result = zeros(3, 3) + cfg = ForwardDiff.JacobianConfig(f!, y, x) + ForwardDiff.jacobian!(result, f!, y, x, cfg) # warmup + return @allocated ForwardDiff.jacobian!(result, f!, y, x, cfg) + end + @test iszero(allocs_jacobian!()) +end + end