# DiffResults

Many differentiation techniques can calculate primal values and multiple orders of derivatives simultaneously. In other words, there are techniques for computing `f(x)`

, `∇f(x)`

and `H(f(x))`

in one fell swoop!

For this purpose, DiffResults provides the `DiffResult`

type, which can be passed to in-place differentiation methods instead of an output buffer. The method then loads all computed results into the given `DiffResult`

, which the user can then query afterwards.

Here's an example of `DiffResult`

in action using ForwardDiff:

```
julia> using ForwardDiff, DiffResults
julia> f(x) = sum(sin, x) + prod(tan, x) * sum(sqrt, x);
julia> x = rand(4);
# construct a `DiffResult` with storage for a Hessian, gradient,
# and primal value based on the type and shape of `x`.
julia> result = DiffResults.HessianResult(x)
# Instead of passing an output buffer to `hessian!`, we pass `result`.
# Note that we re-alias to `result` - this is important! See `hessian!`
# docs for why we do this.
julia> result = ForwardDiff.hessian!(result, f, x);
# ...and now we can get all the computed data from `result`
julia> DiffResults.value(result) == f(x)
true
julia> DiffResults.gradient(result) == ForwardDiff.gradient(f, x)
true
julia> DiffResults.hessian(result) == ForwardDiff.hessian(f, x)
true
```

The rest of this document describes the API for constructing, accessing, and mutating `DiffResult`

instances. For details on how to use a `DiffResult`

with a specific package's methods, please consult that package's documentation.

## Constructing a `DiffResult`

`DiffResults.DiffResult`

— Type```
DiffResult(value::Union{Number,AbstractArray}, derivs::Tuple{Vararg{Number}})
DiffResult(value::Union{Number,AbstractArray}, derivs::Tuple{Vararg{AbstractArray}})
```

Return `r::DiffResult`

, with output value storage provided by `value`

and output derivative storage provided by `derivs`

.

In reality, `DiffResult`

is an abstract supertype of two concrete types, `MutableDiffResult`

and `ImmutableDiffResult`

. If all `value`

/`derivs`

are all `Number`

s or `StaticArray`

s, then `r`

will be immutable (i.e. `r::ImmutableDiffResult`

). Otherwise, `r`

will be mutable (i.e. `r::MutableDiffResult`

).

Note that `derivs`

can be provide in splatted form, i.e. `DiffResult(value, derivs...)`

.

`DiffResults.JacobianResult`

— Function`JacobianResult(x::AbstractArray)`

Construct a `DiffResult`

that can be used for Jacobian calculations where `x`

is the input to the target function. This method assumes that the target function's output dimension equals its input dimension.

Note that `JacobianResult`

allocates its own storage; `x`

is only used for type and shape information. If you want to allocate storage yourself, use the `DiffResult`

constructor instead.

`JacobianResult(y::AbstractArray, x::AbstractArray)`

Construct a `DiffResult`

that can be used for Jacobian calculations where `x`

is the input to the target function, and `y`

is the output (e.g. when taking the Jacobian of `f!(y, x)`

).

Like the single argument version, `y`

and `x`

are only used for type and shape information and are not stored in the returned `DiffResult`

.

`DiffResults.GradientResult`

— Function`GradientResult(x::AbstractArray)`

Construct a `DiffResult`

that can be used for gradient calculations where `x`

is the input to the target function.

Note that `GradientResult`

allocates its own storage; `x`

is only used for type and shape information. If you want to allocate storage yourself, use the `DiffResult`

constructor instead.

`DiffResults.HessianResult`

— Function`HessianResult(x::AbstractArray)`

Construct a `DiffResult`

that can be used for Hessian calculations where `x`

is the input to the target function.

Note that `HessianResult`

allocates its own storage; `x`

is only used for type and shape information. If you want to allocate storage yourself, use the `DiffResult`

constructor instead.

## Accessing data from a `DiffResult`

`DiffResults.value`

— Function`value(r::DiffResult)`

Return the primal value stored in `r`

.

Note that this method returns a reference, not a copy.

`DiffResults.derivative`

— Function`derivative(r::DiffResult, ::Type{Val{i}} = Val{1})`

Return the `ith`

derivative stored in `r`

, defaulting to the first derivative.

Note that this method returns a reference, not a copy.

`DiffResults.gradient`

— Function`gradient(r::DiffResult)`

Return the gradient stored in `r`

.

Equivalent to `derivative(r, Val{1})`

.

`DiffResults.jacobian`

— Function`jacobian(r::DiffResult)`

Return the Jacobian stored in `r`

.

Equivalent to `derivative(r, Val{1})`

.

`DiffResults.hessian`

— Function`hessian(r::DiffResult)`

Return the Hessian stored in `r`

.

Equivalent to `derivative(r, Val{2})`

.

## Mutating a `DiffResult`

`DiffResults.value!`

— Function`value!(r::DiffResult, x)`

Return `s::DiffResult`

with the same data as `r`

, except for `value(s) == x`

.

This function may or may not mutate `r`

. If `r::ImmutableDiffResult`

, a totally new instance will be created and returned, whereas if `r::MutableDiffResult`

, then `r`

will be mutated in-place and returned. Thus, this function should be called as `r = value!(r, x)`

.

`value!(f, r::DiffResult, x)`

Equivalent to `value!(r::DiffResult, map(f, x))`

, but without the implied temporary allocation (when possible).

`DiffResults.derivative!`

— Function`derivative!(r::DiffResult, x, ::Type{Val{i}} = Val{1})`

Return `s::DiffResult`

with the same data as `r`

, except `derivative(s, Val{i}) == x`

.

This function may or may not mutate `r`

. If `r::ImmutableDiffResult`

, a totally new instance will be created and returned, whereas if `r::MutableDiffResult`

, then `r`

will be mutated in-place and returned. Thus, this function should be called as `r = derivative!(r, x, Val{i})`

.

`derivative!(f, r::DiffResult, x, ::Type{Val{i}} = Val{1})`

Equivalent to `derivative!(r::DiffResult, map(f, x), Val{i})`

, but without the implied temporary allocation (when possible).

`DiffResults.gradient!`

— Function`gradient!(r::DiffResult, x)`

Return `s::DiffResult`

with the same data as `r`

, except `gradient(s) == x`

.

Equivalent to `derivative!(r, x, Val{1})`

; see `derivative!`

docs for aliasing behavior.

`gradient!(f, r::DiffResult, x)`

Equivalent to `gradient!(r::DiffResult, map(f, x))`

, but without the implied temporary allocation (when possible).

Equivalent to `derivative!(f, r, x, Val{1})`

; see `derivative!`

docs for aliasing behavior.

`DiffResults.jacobian!`

— Function`jacobian!(r::DiffResult, x)`

Return `s::DiffResult`

with the same data as `r`

, except `jacobian(s) == x`

.

Equivalent to `derivative!(r, x, Val{1})`

; see `derivative!`

docs for aliasing behavior.

`jacobian!(f, r::DiffResult, x)`

Equivalent to `jacobian!(r::DiffResult, map(f, x))`

, but without the implied temporary allocation (when possible).

Equivalent to `derivative!(f, r, x, Val{1})`

; see `derivative!`

docs for aliasing behavior.

`DiffResults.hessian!`

— Function`hessian!(r::DiffResult, x)`

Return `s::DiffResult`

with the same data as `r`

, except `hessian(s) == x`

.

Equivalent to `derivative!(r, x, Val{2})`

; see `derivative!`

docs for aliasing behavior.

`hessian!(f, r::DiffResult, x)`

Equivalent to `hessian!(r::DiffResult, map(f, x))`

, but without the implied temporary allocation (when possible).

Equivalent to `derivative!(f, r, x, Val{2})`

; see `derivative!`

docs for aliasing behavior.