diff --git a/src/ForwardDiff.jl b/src/ForwardDiff.jl index 93d3b246..d0bd6dab 100644 --- a/src/ForwardDiff.jl +++ b/src/ForwardDiff.jl @@ -8,7 +8,7 @@ if VERSION >= v"1.6" end using Random using LinearAlgebra - +using Base: require_one_based_indexing import Printf import NaNMath import SpecialFunctions diff --git a/src/derivative.jl b/src/derivative.jl index 5d7e5dab..accc2405 100644 --- a/src/derivative.jl +++ b/src/derivative.jl @@ -24,6 +24,7 @@ Set `check` to `Val{false}()` to disable tag checking. This can lead to perturba """ @inline function derivative(f!, y::AbstractArray, x::Real, cfg::DerivativeConfig{T} = DerivativeConfig(f!, y, x), ::Val{CHK}=Val{true}()) where {T, CHK} + require_one_based_indexing(y) CHK && checktag(T, f!, x) ydual = cfg.duals seed!(ydual, y) @@ -42,6 +43,7 @@ This method assumes that `isa(f(x), Union{Real,AbstractArray})`. """ @inline function derivative!(result::Union{AbstractArray,DiffResult}, f::F, x::R) where {F,R<:Real} + result isa DiffResult || require_one_based_indexing(result) T = typeof(Tag(f, R)) ydual = f(Dual{T}(x, one(x))) result = extract_value!(T, result, ydual) @@ -60,6 +62,7 @@ Set `check` to `Val{false}()` to disable tag checking. This can lead to perturba @inline function derivative!(result::Union{AbstractArray,DiffResult}, f!, y::AbstractArray, x::Real, cfg::DerivativeConfig{T} = DerivativeConfig(f!, y, x), ::Val{CHK}=Val{true}()) where {T, CHK} + result isa DiffResult ? require_one_based_indexing(y) : require_one_based_indexing(result, y) CHK && checktag(T, f!, x) ydual = cfg.duals seed!(ydual, y) diff --git a/src/gradient.jl b/src/gradient.jl index f9f173eb..e5eac003 100644 --- a/src/gradient.jl +++ b/src/gradient.jl @@ -14,6 +14,7 @@ This method assumes that `isa(f(x), Real)`. Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function gradient(f, x::AbstractArray, cfg::GradientConfig{T} = GradientConfig(f, x), ::Val{CHK}=Val{true}()) where {T, CHK} + require_one_based_indexing(x) CHK && checktag(T, f, x) if chunksize(cfg) == length(x) return vector_mode_gradient(f, x, cfg) @@ -32,6 +33,7 @@ This method assumes that `isa(f(x), Real)`. """ function gradient!(result::Union{AbstractArray,DiffResult}, f::F, x::AbstractArray, cfg::GradientConfig{T} = GradientConfig(f, x), ::Val{CHK}=Val{true}()) where {T, CHK, F} + result isa DiffResult ? require_one_based_indexing(x) : require_one_based_indexing(result, x) CHK && checktag(T, f, x) if chunksize(cfg) == length(x) vector_mode_gradient!(result, f, x, cfg) diff --git a/src/hessian.jl b/src/hessian.jl index 7de6109d..72ffbcde 100644 --- a/src/hessian.jl +++ b/src/hessian.jl @@ -12,6 +12,7 @@ This method assumes that `isa(f(x), Real)`. Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function hessian(f, x::AbstractArray, cfg::HessianConfig{T} = HessianConfig(f, x), ::Val{CHK}=Val{true}()) where {T,CHK} + require_one_based_indexing(x) CHK && checktag(T, f, x) ∇f = y -> gradient(f, y, cfg.gradient_config, Val{false}()) return jacobian(∇f, x, cfg.jacobian_config, Val{false}()) @@ -28,6 +29,7 @@ This method assumes that `isa(f(x), Real)`. Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function hessian!(result::AbstractArray, f, x::AbstractArray, cfg::HessianConfig{T} = HessianConfig(f, x), ::Val{CHK}=Val{true}()) where {T,CHK} + require_one_based_indexing(result, x) CHK && checktag(T, f, x) ∇f = y -> gradient(f, y, cfg.gradient_config, Val{false}()) jacobian!(result, ∇f, x, cfg.jacobian_config, Val{false}()) @@ -62,6 +64,7 @@ because `isa(result, DiffResult)`, `cfg` is constructed as `HessianConfig(f, res Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function hessian!(result::DiffResult, f, x::AbstractArray, cfg::HessianConfig{T} = HessianConfig(f, result, x), ::Val{CHK}=Val{true}()) where {T,CHK} + require_one_based_indexing(x) CHK && checktag(T, f, x) ∇f! = InnerGradientForHess(result, cfg, f) jacobian!(DiffResults.hessian(result), ∇f!, DiffResults.gradient(result), x, cfg.jacobian_config, Val{false}()) diff --git a/src/jacobian.jl b/src/jacobian.jl index bcda61d7..1d3fc368 100644 --- a/src/jacobian.jl +++ b/src/jacobian.jl @@ -16,6 +16,7 @@ This method assumes that `isa(f(x), AbstractArray)`. Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function jacobian(f, x::AbstractArray, cfg::JacobianConfig{T} = JacobianConfig(f, x), ::Val{CHK}=Val{true}()) where {T,CHK} + require_one_based_indexing(x) CHK && checktag(T, f, x) if chunksize(cfg) == length(x) return vector_mode_jacobian(f, x, cfg) @@ -33,6 +34,7 @@ stored in `y`. Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function jacobian(f!, y::AbstractArray, x::AbstractArray, cfg::JacobianConfig{T} = JacobianConfig(f!, y, x), ::Val{CHK}=Val{true}()) where {T, CHK} + require_one_based_indexing(y, x) CHK && checktag(T, f!, x) if chunksize(cfg) == length(x) return vector_mode_jacobian(f!, y, x, cfg) @@ -53,6 +55,7 @@ This method assumes that `isa(f(x), AbstractArray)`. Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function jacobian!(result::Union{AbstractArray,DiffResult}, f, x::AbstractArray, cfg::JacobianConfig{T} = JacobianConfig(f, x), ::Val{CHK}=Val{true}()) where {T, CHK} + result isa DiffResult ? require_one_based_indexing(x) : require_one_based_indexing(result, x) CHK && checktag(T, f, x) if chunksize(cfg) == length(x) vector_mode_jacobian!(result, f, x, cfg) @@ -73,6 +76,7 @@ This method assumes that `isa(f(x), AbstractArray)`. Set `check` to `Val{false}()` to disable tag checking. This can lead to perturbation confusion, so should be used with care. """ function jacobian!(result::Union{AbstractArray,DiffResult}, f!, y::AbstractArray, x::AbstractArray, cfg::JacobianConfig{T} = JacobianConfig(f!, y, x), ::Val{CHK}=Val{true}()) where {T,CHK} + result isa DiffResult ? require_one_based_indexing(y, x) : require_one_based_indexing(result, y, x) CHK && checktag(T, f!, x) if chunksize(cfg) == length(x) vector_mode_jacobian!(result, f!, y, x, cfg)