diff --git a/src/derivative.jl b/src/derivative.jl index fa6d98fa..a60d8d0e 100644 --- a/src/derivative.jl +++ b/src/derivative.jl @@ -69,6 +69,8 @@ Set `check` to `Val{false}()` to disable tag checking. This can lead to perturba return result end +derivative(f, x::AbstractArray) = throw(DimensionMismatch("derivative(f, x) expects that x is a real number. Perhaps you meant gradient(f, x)?")) + ##################### # result extraction # ##################### diff --git a/src/gradient.jl b/src/gradient.jl index 7d905d51..06fed47c 100644 --- a/src/gradient.jl +++ b/src/gradient.jl @@ -49,6 +49,8 @@ end @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 # ##################### @@ -91,12 +93,18 @@ function extract_gradient_chunk!(::Type{T}, result::DiffResult, dual, index, chu return result end +extract_gradient_chunk!(::Type, result, dual::AbstractArray, index, chunksize) = throw(GRAD_ERROR) +extract_gradient_chunk!(::Type, result::DiffResult, dual::AbstractArray, index, chunksize) = throw(GRAD_ERROR) + +const GRAD_ERROR = DimensionMismatch("gradient(f, x) expects that f(x) is a real number. Perhaps you meant jacobian(f, x)?") + ############### # vector mode # ############### function vector_mode_gradient(f::F, x, cfg::GradientConfig{T}) where {T, F} ydual = vector_mode_dual_eval(f, x, cfg) + ydual isa Real || throw(GRAD_ERROR) result = similar(x, valtype(ydual)) return extract_gradient!(T, result, ydual) end diff --git a/src/jacobian.jl b/src/jacobian.jl index c24f294e..da0b2334 100644 --- a/src/jacobian.jl +++ b/src/jacobian.jl @@ -90,6 +90,8 @@ end @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 # ##################### @@ -143,6 +145,7 @@ reshape_jacobian(result::DiffResult, ydual, xdual) = reshape_jacobian(DiffResult function vector_mode_jacobian(f::F, x, cfg::JacobianConfig{T,V,N}) where {F,T,V,N} ydual = vector_mode_dual_eval(f, x, cfg) + ydual isa AbstractArray || throw(JACOBIAN_ERROR) result = similar(ydual, valtype(eltype(ydual)), length(ydual), N) extract_jacobian!(T, result, ydual, N) extract_value!(T, result, ydual) @@ -194,6 +197,8 @@ end return result end +const JACOBIAN_ERROR = DimensionMismatch("jacobian(f, x) expexts that f(x) is an array. Perhaps you meant gradient(f, x)?") + # chunk mode # #------------# @@ -216,6 +221,7 @@ function jacobian_chunk_mode_expr(work_array_definition::Expr, compute_ydual::Ex # do first chunk manually to calculate output type seed!(xdual, x, 1, seeds) $(compute_ydual) + ydual isa AbstractArray || throw(JACOBIAN_ERROR) $(result_definition) out_reshaped = reshape_jacobian(result, ydual, xdual) extract_jacobian_chunk!(T, out_reshaped, ydual, 1, N) diff --git a/test/DerivativeTest.jl b/test/DerivativeTest.jl index db9c03dd..f5645a7e 100644 --- a/test/DerivativeTest.jl +++ b/test/DerivativeTest.jl @@ -96,4 +96,8 @@ end @test (x -> ForwardDiff.derivative(y -> x^y, 1.5))(0.0) === 0.0 end +@testset "dimension error for derivative" begin + @test_throws DimensionMismatch ForwardDiff.derivative(sum, fill(2pi, 3)) +end + end # module diff --git a/test/GradientTest.jl b/test/GradientTest.jl index 7433f396..ac949944 100644 --- a/test/GradientTest.jl +++ b/test/GradientTest.jl @@ -156,4 +156,10 @@ end @test isempty(g_grad_const(zeros(Float64, 0))) end +@testset "dimension errors for gradient" begin + @test_throws DimensionMismatch ForwardDiff.gradient(identity, 2pi) # input + @test_throws DimensionMismatch ForwardDiff.gradient(identity, fill(2pi, 2)) # vector_mode_gradient + @test_throws DimensionMismatch ForwardDiff.gradient(identity, fill(2pi, 10^6)) # chunk_mode_gradient +end + end # module diff --git a/test/JacobianTest.jl b/test/JacobianTest.jl index c704d3e1..33a32f2d 100644 --- a/test/JacobianTest.jl +++ b/test/JacobianTest.jl @@ -225,4 +225,10 @@ for T in (StaticArrays.SArray, StaticArrays.MArray) @test DiffResults.jacobian(sresult3) == DiffResults.jacobian(result) end +@testset "dimension errors for jacobian" begin + @test_throws DimensionMismatch ForwardDiff.jacobian(identity, 2pi) # input + @test_throws DimensionMismatch ForwardDiff.jacobian(sum, fill(2pi, 2)) # vector_mode_jacobian + @test_throws DimensionMismatch ForwardDiff.jacobian(sum, fill(2pi, 10^6)) # chunk_mode_jacobian +end + end # module