# 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

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.DiffResultType
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 Numbers or StaticArrays, 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.JacobianResultFunction
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.GradientResultFunction
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.HessianResultFunction
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.valueFunction
value(r::DiffResult)

Return the primal value stored in r.

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

DiffResults.derivativeFunction
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.gradientFunction
gradient(r::DiffResult)

Return the gradient stored in r.

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

DiffResults.jacobianFunction
jacobian(r::DiffResult)

Return the Jacobian stored in r.

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

DiffResults.hessianFunction
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.