diff --git a/DifferentiationInterface/Project.toml b/DifferentiationInterface/Project.toml index 60381de60..19db4f1e4 100644 --- a/DifferentiationInterface/Project.toml +++ b/DifferentiationInterface/Project.toml @@ -1,7 +1,7 @@ name = "DifferentiationInterface" uuid = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63" authors = ["Guillaume Dalle", "Adrian Hill"] -version = "0.6.5" +version = "0.6.6" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" diff --git a/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/onearg.jl b/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/onearg.jl index 9e3a7c6b9..6e25058dc 100644 --- a/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/onearg.jl +++ b/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/onearg.jl @@ -159,38 +159,60 @@ end ## Gradient -### Unprepared +### Unprepared, only when chunk size not specified function DI.value_and_gradient!( - f::F, grad, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc = with_contexts(f, contexts...) - result = DiffResult(zero(eltype(x)), (grad,)) - result = gradient!(result, fc, x) - y = DR.value(result) - grad === DR.gradient(result) || copyto!(grad, DR.gradient(result)) - return y, grad + f::F, grad, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + result = DiffResult(zero(eltype(x)), (grad,)) + result = gradient!(result, fc, x) + y = DR.value(result) + grad === DR.gradient(result) || copyto!(grad, DR.gradient(result)) + return y, grad + else + prep = DI.prepare_gradient(f, backend, x, contexts...) + return DI.value_and_gradient!(f, grad, prep, backend, x, contexts...) + end end function DI.value_and_gradient( - f::F, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc = with_contexts(f, contexts...) - result = GradientResult(x) - result = gradient!(result, fc, x) - return DR.value(result), DR.gradient(result) + f::F, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + result = GradientResult(x) + result = gradient!(result, fc, x) + return DR.value(result), DR.gradient(result) + else + prep = DI.prepare_gradient(f, backend, x, contexts...) + return DI.value_and_gradient(f, prep, backend, x, contexts...) + end end function DI.gradient!( - f::F, grad, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc = with_contexts(f, contexts...) - return gradient!(grad, fc, x) + f::F, grad, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + return gradient!(grad, fc, x) + else + prep = DI.prepare_gradient(f, backend, x, contexts...) + return DI.gradient!(f, grad, prep, backend, x, contexts...) + end end -function DI.gradient(f::F, ::AutoForwardDiff, x, contexts::Vararg{Context,C}) where {F,C} - fc = with_contexts(f, contexts...) - return gradient(fc, x) +function DI.gradient( + f::F, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + return gradient(fc, x) + else + prep = DI.prepare_gradient(f, backend, x, contexts...) + return DI.gradient(f, prep, backend, x, contexts...) + end end ### Prepared @@ -252,37 +274,59 @@ end ## Jacobian -### Unprepared +### Unprepared, only when chunk size not specified function DI.value_and_jacobian!( - f::F, jac, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc = with_contexts(f, contexts...) - y = fc(x) - result = DiffResult(y, (jac,)) - result = jacobian!(result, fc, x) - y = DR.value(result) - jac === DR.jacobian(result) || copyto!(jac, DR.jacobian(result)) - return y, jac + f::F, jac, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + y = fc(x) + result = DiffResult(y, (jac,)) + result = jacobian!(result, fc, x) + y = DR.value(result) + jac === DR.jacobian(result) || copyto!(jac, DR.jacobian(result)) + return y, jac + else + prep = DI.prepare_jacobian(f, backend, x, contexts...) + return DI.value_and_jacobian!(f, jac, prep, backend, x, contexts...) + end end function DI.value_and_jacobian( - f::F, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc = with_contexts(f, contexts...) - return fc(x), jacobian(fc, x) + f::F, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + return fc(x), jacobian(fc, x) + else + prep = DI.prepare_jacobian(f, backend, x, contexts...) + return DI.value_and_jacobian(f, prep, backend, x, contexts...) + end end function DI.jacobian!( - f::F, jac, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc = with_contexts(f, contexts...) - return jacobian!(jac, fc, x) + f::F, jac, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + return jacobian!(jac, fc, x) + else + prep = DI.prepare_jacobian(f, backend, x, contexts...) + return DI.jacobian!(f, jac, prep, backend, x, contexts...) + end end -function DI.jacobian(f::F, ::AutoForwardDiff, x, contexts::Vararg{Context,C}) where {F,C} - fc = with_contexts(f, contexts...) - return jacobian(fc, x) +function DI.jacobian( + f::F, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc = with_contexts(f, contexts...) + return jacobian(fc, x) + else + prep = DI.prepare_jacobian(f, backend, x, contexts...) + return DI.jacobian(f, prep, backend, x, contexts...) + end end ### Prepared diff --git a/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/twoarg.jl b/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/twoarg.jl index c974ee8cd..a38c99ee6 100644 --- a/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/twoarg.jl +++ b/DifferentiationInterface/ext/DifferentiationInterfaceForwardDiffExt/twoarg.jl @@ -209,39 +209,59 @@ end ## Jacobian -### Unprepared +### Unprepared, only when chunk size is not specified function DI.value_and_jacobian( - f!::F, y, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc! = with_contexts(f!, contexts...) - jac = similar(y, length(y), length(x)) - result = MutableDiffResult(y, (jac,)) - result = jacobian!(result, fc!, y, x) - return DiffResults.value(result), DiffResults.jacobian(result) + f!::F, y, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc! = with_contexts(f!, contexts...) + jac = similar(y, length(y), length(x)) + result = MutableDiffResult(y, (jac,)) + result = jacobian!(result, fc!, y, x) + return DiffResults.value(result), DiffResults.jacobian(result) + else + prep = DI.prepare_jacobian(f!, y, backend, x, contexts...) + return DI.value_and_jacobian(f!, y, prep, backend, x, contexts...) + end end function DI.value_and_jacobian!( - f!::F, y, jac, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc! = with_contexts(f!, contexts...) - result = MutableDiffResult(y, (jac,)) - result = jacobian!(result, fc!, y, x) - return DiffResults.value(result), DiffResults.jacobian(result) + f!::F, y, jac, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc! = with_contexts(f!, contexts...) + result = MutableDiffResult(y, (jac,)) + result = jacobian!(result, fc!, y, x) + return DiffResults.value(result), DiffResults.jacobian(result) + else + prep = DI.prepare_jacobian(f!, y, backend, x, contexts...) + return DI.value_and_jacobian!(f!, y, jac, prep, backend, x, contexts...) + end end function DI.jacobian( - f!::F, y, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc! = with_contexts(f!, contexts...) - return jacobian(fc!, y, x) + f!::F, y, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc! = with_contexts(f!, contexts...) + return jacobian(fc!, y, x) + else + prep = DI.prepare_jacobian(f!, y, backend, x, contexts...) + return DI.jacobian(f!, y, prep, backend, x, contexts...) + end end function DI.jacobian!( - f!::F, y, jac, ::AutoForwardDiff, x, contexts::Vararg{Context,C} -) where {F,C} - fc! = with_contexts(f!, contexts...) - return jacobian!(jac, fc!, y, x) + f!::F, y, jac, backend::AutoForwardDiff{chunksize}, x, contexts::Vararg{Context,C} +) where {F,C,chunksize} + if isnothing(chunksize) + fc! = with_contexts(f!, contexts...) + return jacobian!(jac, fc!, y, x) + else + prep = DI.prepare_jacobian(f!, y, backend, x, contexts...) + return DI.jacobian!(f!, y, jac, prep, backend, x, contexts...) + end end ### Prepared