-
Notifications
You must be signed in to change notification settings - Fork 29
Description
Hi, thanks for the great package.
I have been wondering about the role of mutable arguments for inplace operators based on inplace functions and could not find decisive information in the documentation.
Currently, the documentation only notes that
The positional arguments between f/f! and backend are always mutated, regardless of the bang ! in the operator name. In particular, for in-place functions f!(y, x), every variant of every operator will mutate y.
In a call DI.jacobian!(f!, y, Dy, backend, x), should y be considered just a temporary array? Or does it generally also hold the primal result values (like with DI.value_and_jacobian!)?
This question has been raised as well by @adrhill in #6 but I could not find an answer skimming the superseding issues.
When testing with ForwardDiff the array y holds the result:
import ForwardDiff
import DifferentiationInterface as DI
## out-of-place test function, ℝ³ → ℝ²
f(x) = [ sum(x); sum(abs2, x) ]
## inplace test function, ℝ³ → ℝ²
f!(y, x) = begin
y[1] = sum(x)
y[2] = sum(abs2, x)
return nothing
end
## test point
x = [1.0, 2.0, 3.0]
## use `ForwardDiff` for testing
bcknd = DI.AutoForwardDiff()
## compute Jacobian inplace, from out-of-place function:
Dy_oop = similar(x, 2, 3)
DI.jacobian!(f, Dy_oop, bcknd, x)
## compute Jacobian inplace, from inplace function:
y_tmp = similar(x, 2) # scratch?
Dy_ip = similar(x, 2, 3)
DI.jacobian!(f!, y_tmp, Dy_ip, bcknd, x)
## Jacobian result matrices are equal …
@assert Dy_ip == Dy_oop
## … but `y_tmp` also holds correct result
@assert y_tmp == f(x)