diff --git a/docs/src/index.md b/docs/src/index.md index 0697635..d05d41a 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -26,9 +26,11 @@ julia> x = rand(4); # 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. +# Instead of passing an output buffer to `ForwardDiff.hessian!`, we pass `result`. +# Note that we re-alias to `result`: +# This is not required in this example since `ForwardDiff.hessian!` mutates `result`; +# however, in general it is important since immutable `DiffResult` instances +# (e.g. `DiffResult` objects with static arrays) cannot be updated in-place. julia> result = ForwardDiff.hessian!(result, f, x); # ...and now we can get all the computed data from `result` @@ -65,12 +67,12 @@ DiffResults.jacobian DiffResults.hessian ``` -## Mutating a `DiffResult` +## Modifying a `DiffResult` ```@docs -DiffResults.value! -DiffResults.derivative! -DiffResults.gradient! -DiffResults.jacobian! -DiffResults.hessian! +DiffResults.value!! +DiffResults.derivative!! +DiffResults.gradient!! +DiffResults.jacobian!! +DiffResults.hessian!! ``` diff --git a/src/DiffResults.jl b/src/DiffResults.jl index c440d50..b091423 100644 --- a/src/DiffResults.jl +++ b/src/DiffResults.jl @@ -145,28 +145,36 @@ Note that this method returns a reference, not a copy. value(r::DiffResult) = r.value """ - value!(r::DiffResult, x) + 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)`. +!!! warn + 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!(r::MutableDiffResult, x::Number) = (r.value = x; return r) -value!(r::MutableDiffResult, x::AbstractArray) = (copyto!(value(r), x); return r) -value!(r::ImmutableDiffResult{O,V}, x::Union{Number,AbstractArray}) where {O,V} = ImmutableDiffResult(convert(V, x), r.derivs) +value!!(r::MutableDiffResult, x::Number) = (r.value = x; return r) +value!!(r::MutableDiffResult, x::AbstractArray) = (copyto!(value(r), x); return r) +value!!(r::ImmutableDiffResult{O,V}, x::Union{Number,AbstractArray}) where {O,V} = ImmutableDiffResult(convert(V, x), r.derivs) """ - value!(f, r::DiffResult, x) + value!!(f, r::DiffResult, x) -Equivalent to `value!(r::DiffResult, map(f, x))`, but without the implied temporary +Equivalent to `value!!(r::DiffResult, map(f, x))`, but without the implied temporary allocation (when possible). + +!!! warn + 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!!(f, r, x)`. """ -value!(f, r::MutableDiffResult, x::Number) = (r.value = f(x); return r) -value!(f, r::MutableDiffResult, x::AbstractArray) = (map!(f, value(r), x); return r) -value!(f, r::ImmutableDiffResult{O,V}, x::Number) where {O,V} = value!(r, convert(V, f(x))) -value!(f, r::ImmutableDiffResult{O,V}, x::AbstractArray) where {O,V} = value!(r, convert(V, map(f, x))) +value!!(f, r::MutableDiffResult, x::Number) = (r.value = f(x); return r) +value!!(f, r::MutableDiffResult, x::AbstractArray) = (map!(f, value(r), x); return r) +value!!(f, r::ImmutableDiffResult{O,V}, x::Number) where {O,V} = value!!(r, convert(V, f(x))) +value!!(f, r::ImmutableDiffResult{O,V}, x::AbstractArray) where {O,V} = value!!(r, convert(V, map(f, x))) # derivative/derivative! # #------------------------# @@ -181,61 +189,68 @@ Note that this method returns a reference, not a copy. derivative(r::DiffResult, ::Type{Val{i}} = Val{1}) where {i} = r.derivs[i] """ - derivative!(r::DiffResult, x, ::Type{Val{i}} = Val{1}) + 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})`. +!!! warn + 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})`. """ -function derivative!(r::MutableDiffResult, x::Number, ::Type{Val{i}} = Val{1}) where {i} +function derivative!!(r::MutableDiffResult, x::Number, ::Type{Val{i}} = Val{1}) where {i} r.derivs = tuple_setindex(r.derivs, x, Val{i}) return r end -function derivative!(r::MutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} +function derivative!!(r::MutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} copyto!(derivative(r, Val{i}), x) return r end -function derivative!(r::ImmutableDiffResult, x::Union{Number,StaticArray}, ::Type{Val{i}} = Val{1}) where {i} +function derivative!!(r::ImmutableDiffResult, x::Union{Number,StaticArray}, ::Type{Val{i}} = Val{1}) where {i} return ImmutableDiffResult(value(r), tuple_setindex(r.derivs, x, Val{i})) end -function derivative!(r::ImmutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} +function derivative!!(r::ImmutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} T = tuple_eltype(r.derivs, Val{i}) return ImmutableDiffResult(value(r), tuple_setindex(r.derivs, T(x), Val{i})) end """ - derivative!(f, r::DiffResult, x, ::Type{Val{i}} = Val{1}) + derivative!!(f, r::DiffResult, x, ::Type{Val{i}} = Val{1}) -Equivalent to `derivative!(r::DiffResult, map(f, x), Val{i})`, but without the implied +Equivalent to `derivative!!(r::DiffResult, map(f, x), Val{i})`, but without the implied temporary allocation (when possible). + +!!! warn + 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!!(f, r, x, Val{i})`. """ -function derivative!(f, r::MutableDiffResult, x::Number, ::Type{Val{i}} = Val{1}) where {i} +function derivative!!(f, r::MutableDiffResult, x::Number, ::Type{Val{i}} = Val{1}) where {i} r.derivs = tuple_setindex(r.derivs, f(x), Val{i}) return r end -function derivative!(f, r::MutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} +function derivative!!(f, r::MutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} map!(f, derivative(r, Val{i}), x) return r end -function derivative!(f, r::ImmutableDiffResult, x::Number, ::Type{Val{i}} = Val{1}) where {i} - return derivative!(r, f(x), Val{i}) +function derivative!!(f, r::ImmutableDiffResult, x::Number, ::Type{Val{i}} = Val{1}) where {i} + return derivative!!(r, f(x), Val{i}) end -function derivative!(f, r::ImmutableDiffResult, x::StaticArray, ::Type{Val{i}} = Val{1}) where {i} - return derivative!(r, map(f, x), Val{i}) +function derivative!!(f, r::ImmutableDiffResult, x::StaticArray, ::Type{Val{i}} = Val{1}) where {i} + return derivative!!(r, map(f, x), Val{i}) end -function derivative!(f, r::ImmutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} +function derivative!!(f, r::ImmutableDiffResult, x::AbstractArray, ::Type{Val{i}} = Val{1}) where {i} T = tuple_eltype(r.derivs, Val{i}) - return derivative!(r, map(f, T(x)), Val{i}) + return derivative!!(r, map(f, T(x)), Val{i}) end # special-cased methods # @@ -251,23 +266,35 @@ Equivalent to `derivative(r, Val{1})`. gradient(r::DiffResult) = derivative(r) """ - gradient!(r::DiffResult, x) + 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. +Equivalent to `derivative!!(r, x, Val{1})`. + +!!! warn + 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 = gradient!!(r, x)`. """ -gradient!(r::DiffResult, x) = derivative!(r, x) +gradient!!(r::DiffResult, x) = derivative!!(r, x) """ - gradient!(f, r::DiffResult, x) + gradient!!(f, r::DiffResult, x) -Equivalent to `gradient!(r::DiffResult, map(f, x))`, but without the implied temporary +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. +Equivalent to `derivative!!(f, r, x, Val{1})`. + +!!! warn + 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 = gradient!!(f, r, x)`. """ -gradient!(f, r::DiffResult, x) = derivative!(f, r, x) +gradient!!(f, r::DiffResult, x) = derivative!!(f, r, x) """ jacobian(r::DiffResult) @@ -279,23 +306,35 @@ Equivalent to `derivative(r, Val{1})`. jacobian(r::DiffResult) = derivative(r) """ - jacobian!(r::DiffResult, x) + 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. +Equivalent to `derivative!!(r, x, Val{1})`. + +!!! warn + 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 = jacobian!!(r, x)`. """ -jacobian!(r::DiffResult, x) = derivative!(r, x) +jacobian!!(r::DiffResult, x) = derivative!!(r, x) """ - jacobian!(f, r::DiffResult, x) + jacobian!!(f, r::DiffResult, x) -Equivalent to `jacobian!(r::DiffResult, map(f, x))`, but without the implied temporary +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. +Equivalent to `derivative!!(f, r, x, Val{1})`. + +!!! warn + 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 = jacobian!!(f, r, x)`. """ -jacobian!(f, r::DiffResult, x) = derivative!(f, r, x) +jacobian!!(f, r::DiffResult, x) = derivative!!(f, r, x) """ hessian(r::DiffResult) @@ -307,23 +346,35 @@ Equivalent to `derivative(r, Val{2})`. hessian(r::DiffResult) = derivative(r, Val{2}) """ - hessian!(r::DiffResult, x) + 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. +Equivalent to `derivative!!(r, x, Val{2})`. + +!!! warn + 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 = hessian!(r, x)`. """ -hessian!(r::DiffResult, x) = derivative!(r, x, Val{2}) +hessian!!(r::DiffResult, x) = derivative!!(r, x, Val{2}) """ - hessian!(f, r::DiffResult, x) + hessian!!(f, r::DiffResult, x) -Equivalent to `hessian!(r::DiffResult, map(f, x))`, but without the implied temporary +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. +Equivalent to `derivative!!(f, r, x, Val{2})`. + +!!! warn + 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 = hessian!!(f, r, x)`. """ -hessian!(f, r::DiffResult, x) = derivative!(f, r, x, Val{2}) +hessian!!(f, r::DiffResult, x) = derivative!!(f, r, x, Val{2}) ################### # Pretty Printing # @@ -333,4 +384,23 @@ Base.show(io::IO, r::ImmutableDiffResult) = print(io, "ImmutableDiffResult($(r.v Base.show(io::IO, r::MutableDiffResult) = print(io, "MutableDiffResult($(r.value), $(r.derivs))") +################ +# Deprecations # +################ + +Base.@deprecate value!(r::DiffResult, x::Union{Number,AbstractArray}) value!!(r, x) false +Base.@deprecate value!(f, r::DiffResult, x::Union{Number,AbstractArray}) value!!(f, r, x) false + +Base.@deprecate derivative!(r::DiffResult, x::Union{Number,AbstractArray}, ::Type{Val{i}} = Val{1}) where {i} derivative!!(r, x, Val{i}) false +Base.@deprecate derivative!(f, r::DiffResult, x::Union{Number,AbstractArray}, ::Type{Val{i}} = Val{1}) where {i} derivative!!(f, r, x, Val{i}) false + +Base.@deprecate gradient!(r::DiffResult, x) gradient!!(r, x) false +Base.@deprecate gradient!(f, r::DiffResult, x) gradient!!(f, r, x) false + +Base.@deprecate jacobian!(r::DiffResult, x) jacobian!!(r, x) false +Base.@deprecate jacobian!(f, r::DiffResult, x) jacobian!!(f, r, x) false + +Base.@deprecate hessian!(r::DiffResult, x) hessian!!(r, x) false +Base.@deprecate hessian!(f, r::DiffResult, x) hessian!!(f, r, x) false + end # module diff --git a/test/runtests.jl b/test/runtests.jl index 41affbe..9a4feb7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,8 @@ using DiffResults, StaticArrays, Test using DiffResults: DiffResult, GradientResult, JacobianResult, HessianResult, - value, value!, derivative, derivative!, gradient, gradient!, - jacobian, jacobian!, hessian, hessian! + value, value!!, derivative, derivative!!, gradient, gradient!!, + jacobian, jacobian!!, hessian, hessian!! @testset "DiffResult" begin @@ -54,58 +54,58 @@ using DiffResults: DiffResult, GradientResult, JacobianResult, HessianResult, @test rsmix == rsmix_copy @test rsmix === rsmix_copy - @testset "value/value!" begin + @testset "value/value!!" begin @test value(rn) === n0 @test value(rx) === x0 @test value(rs) === s0 @test value(rsmix) === n0 - rn = value!(rn, n1) + rn = value!!(rn, n1) @test value(rn) === n1 - rn = value!(rn, n0) + rn = value!!(rn, n0) x0_new, x0_copy = rand(k), copy(x0) - rx = value!(rx, x0_new) + rx = value!!(rx, x0_new) @test value(rx) === x0 == x0_new - rx = value!(rx, x0_copy) + rx = value!!(rx, x0_copy) s0_new = rand(k) - rs = value!(rs, s0_new) + rs = value!!(rs, s0_new) @test value(rs) == s0_new @test typeof(value(rs)) === typeof(s0) - rs = value!(rs, s0) + rs = value!!(rs, s0) - rsmix = value!(rsmix, n1) + rsmix = value!!(rsmix, n1) @test value(rsmix) === n1 - rsmix = value!(rsmix, n0) + rsmix = value!!(rsmix, n0) - rn = value!(exp, rn, n1) + rn = value!!(exp, rn, n1) @test value(rn) === exp(n1) - rn = value!(rn, n0) + rn = value!!(rn, n0) x0_new, x0_copy = rand(k), copy(x0) - rx = value!(exp, rx, x0_new) + rx = value!!(exp, rx, x0_new) @test value(rx) === x0 == exp.(x0_new) - rx = value!(rx, x0_copy) + rx = value!!(rx, x0_copy) s0_new = rand(k) - rs = value!(exp, rs, s0_new) + rs = value!!(exp, rs, s0_new) @test value(rs) == exp.(s0_new) @test typeof(value(rs)) === typeof(s0) - rs = value!(rs, s0) + rs = value!!(rs, s0) - rsmix = value!(exp, rsmix, n1) + rsmix = value!!(exp, rsmix, n1) @test value(rsmix) === exp(n1) - rsmix = value!(rsmix, n0) + rsmix = value!!(rsmix, n0) ksqrt = Int(sqrt(k)) T = typeof(SMatrix{ksqrt,ksqrt}(rand(ksqrt,ksqrt))) - rs_new = value!(rs, convert(T, value(rs))) + rs_new = value!!(rs, convert(T, value(rs))) @test rs_new === rs end - @testset "derivative/derivative!" begin + @testset "derivative/derivative!!" begin @test derivative(rn) === n1 @test derivative(rn, Val{2}) === n2 @@ -119,175 +119,175 @@ using DiffResults: DiffResult, GradientResult, JacobianResult, HessianResult, @test derivative(rsmix) === s0 @test derivative(rsmix, Val{2}) === s1 - rn = derivative!(rn, n0) + rn = derivative!!(rn, n0) @test derivative(rn) === n0 - rn = derivative!(rn, n1) + rn = derivative!!(rn, n1) x1_new, x1_copy = rand(k, k), copy(x1) - rx = derivative!(rx, x1_new) + rx = derivative!!(rx, x1_new) @test derivative(rx) === x1 == x1_new - rx = derivative!(rx, x1_copy) + rx = derivative!!(rx, x1_copy) s1_new = rand(k, k) - rs = derivative!(rs, s1_new) + rs = derivative!!(rs, s1_new) @test derivative(rs) == s1_new @test typeof(derivative(rs)) === typeof(s1) - rs = derivative!(rs, s1) + rs = derivative!!(rs, s1) s0_new = rand(k) - rsmix = derivative!(rsmix, s0_new) + rsmix = derivative!!(rsmix, s0_new) @test derivative(rsmix) == s0_new @test typeof(derivative(rsmix)) === typeof(s0) - rsmix = derivative!(rsmix, s0) + rsmix = derivative!!(rsmix, s0) - rn = derivative!(rn, n1, Val{2}) + rn = derivative!!(rn, n1, Val{2}) @test derivative(rn, Val{2}) === n1 - rn = derivative!(rn, n2, Val{2}) + rn = derivative!!(rn, n2, Val{2}) x2_new, x2_copy = rand(k, k, k), copy(x2) - rx = derivative!(rx, x2_new, Val{2}) + rx = derivative!!(rx, x2_new, Val{2}) @test derivative(rx, Val{2}) === x2 == x2_new - rx = derivative!(rx, x2_copy, Val{2}) + rx = derivative!!(rx, x2_copy, Val{2}) s2_new = rand(k, k, k) - rs = derivative!(rs, s2_new, Val{2}) + rs = derivative!!(rs, s2_new, Val{2}) @test derivative(rs, Val{2}) == s2_new @test typeof(derivative(rs, Val{2})) === typeof(s2) - rs = derivative!(rs, s2, Val{2}) + rs = derivative!!(rs, s2, Val{2}) s1_new = rand(k, k) - rsmix = derivative!(rsmix, s1_new, Val{2}) + rsmix = derivative!!(rsmix, s1_new, Val{2}) @test derivative(rsmix, Val{2}) == s1_new @test typeof(derivative(rsmix, Val{2})) === typeof(s1) - rsmix = derivative!(rsmix, s1, Val{2}) + rsmix = derivative!!(rsmix, s1, Val{2}) - rn = derivative!(exp, rn, n0) + rn = derivative!!(exp, rn, n0) @test derivative(rn) === exp(n0) - rn = derivative!(rn, n1) + rn = derivative!!(rn, n1) x1_new, x1_copy = rand(k, k), copy(x1) - rx = derivative!(exp, rx, x1_new) + rx = derivative!!(exp, rx, x1_new) @test derivative(rx) === x1 == exp.(x1_new) - rx = derivative!(exp, rx, x1_copy) + rx = derivative!!(exp, rx, x1_copy) s1_new = rand(k, k) - rs = derivative!(exp, rs, s1_new) + rs = derivative!!(exp, rs, s1_new) @test derivative(rs) == exp.(s1_new) @test typeof(derivative(rs)) === typeof(s1) - rs = derivative!(exp, rs, s1) + rs = derivative!!(exp, rs, s1) s0_new = rand(k) - rsmix = derivative!(exp, rsmix, s0_new) + rsmix = derivative!!(exp, rsmix, s0_new) @test derivative(rsmix) == exp.(s0_new) @test typeof(derivative(rsmix)) === typeof(s0) - rsmix = derivative!(exp, rsmix, s0) + rsmix = derivative!!(rsmix, s0) - rn = derivative!(exp, rn, n1, Val{2}) + rn = derivative!!(exp, rn, n1, Val{2}) @test derivative(rn, Val{2}) === exp(n1) - rn = derivative!(rn, n2, Val{2}) + rn = derivative!!(rn, n2, Val{2}) x2_new, x2_copy = rand(k, k, k), copy(x2) - rx = derivative!(exp, rx, x2_new, Val{2}) + rx = derivative!!(exp, rx, x2_new, Val{2}) @test derivative(rx, Val{2}) === x2 == exp.(x2_new) - rx = derivative!(exp, rx, x2_copy, Val{2}) + rx = derivative!!(exp, rx, x2_copy, Val{2}) s2_new = rand(k, k, k) - rs = derivative!(exp, rs, s2_new, Val{2}) + rs = derivative!!(exp, rs, s2_new, Val{2}) @test derivative(rs, Val{2}) == exp.(s2_new) @test typeof(derivative(rs, Val{2})) === typeof(s2) - rs = derivative!(exp, rs, s2, Val{2}) + rs = derivative!!(exp, rs, s2, Val{2}) s1_new = rand(k, k) - rsmix = derivative!(exp, rsmix, s1_new, Val{2}) + rsmix = derivative!!(exp, rsmix, s1_new, Val{2}) @test derivative(rsmix, Val{2}) == exp.(s1_new) @test typeof(derivative(rsmix, Val{2})) === typeof(s1) - rsmix = derivative!(exp, rsmix, s1, Val{2}) + rsmix = derivative!!(rsmix, s1, Val{2}) end - @testset "gradient/gradient!" begin + @testset "gradient/gradient!!" begin x1_new, x1_copy = rand(k, k), copy(x1) - rx = gradient!(rx, x1_new) + rx = gradient!!(rx, x1_new) @test gradient(rx) === x1 == x1_new - rx = gradient!(rx, x1_copy) + rx = gradient!!(rx, x1_copy) s1_new = rand(k, k) - rs = gradient!(rs, s1_new) + rs = gradient!!(rs, s1_new) @test gradient(rs) == s1_new @test typeof(gradient(rs)) === typeof(s1) - rs = gradient!(rs, s1) + rs = gradient!!(rs, s1) x1_new, x1_copy = rand(k, k), copy(x1) - rx = gradient!(exp, rx, x1_new) + rx = gradient!!(exp, rx, x1_new) @test gradient(rx) === x1 == exp.(x1_new) - rx = gradient!(exp, rx, x1_copy) + rx = gradient!!(exp, rx, x1_copy) s0_new = rand(k) - rsmix = gradient!(exp, rsmix, s0_new) + rsmix = gradient!!(exp, rsmix, s0_new) @test gradient(rsmix) == exp.(s0_new) @test typeof(gradient(rsmix)) === typeof(s0) - rsmix = gradient!(exp, rsmix, s0) + rsmix = gradient!!(rsmix, s0) T = typeof(SVector{k*k}(rand(k*k))) - rs_new = gradient!(rs, convert(T, gradient(rs))) + rs_new = gradient!!(rs, convert(T, gradient(rs))) @test rs_new === rs end - @testset "jacobian/jacobian!" begin + @testset "jacobian/jacobian!!" begin x1_new, x1_copy = rand(k, k), copy(x1) - rx = jacobian!(rx, x1_new) + rx = jacobian!!(rx, x1_new) @test jacobian(rx) === x1 == x1_new - rx = jacobian!(rx, x1_copy) + rx = jacobian!!(rx, x1_copy) s1_new = rand(k, k) - rs = jacobian!(rs, s1_new) + rs = jacobian!!(rs, s1_new) @test jacobian(rs) == s1_new @test typeof(jacobian(rs)) === typeof(s1) - rs = jacobian!(rs, s1) + rs = jacobian!!(rs, s1) x1_new, x1_copy = rand(k, k), copy(x1) - rx = jacobian!(exp, rx, x1_new) + rx = jacobian!!(exp, rx, x1_new) @test jacobian(rx) === x1 == exp.(x1_new) - rx = jacobian!(exp, rx, x1_copy) + rx = jacobian!!(exp, rx, x1_copy) s0_new = rand(k) - rsmix = jacobian!(exp, rsmix, s0_new) + rsmix = jacobian!!(exp, rsmix, s0_new) @test jacobian(rsmix) == exp.(s0_new) @test typeof(jacobian(rsmix)) === typeof(s0) - rsmix = jacobian!(exp, rsmix, s0) + rsmix = jacobian!!(rsmix, s0) T = typeof(SVector{k*k}(rand(k*k))) - rs_new = jacobian!(rs, convert(T, jacobian(rs))) + rs_new = jacobian!!(rs, convert(T, jacobian(rs))) @test rs_new === rs end - @testset "hessian/hessian!" begin + @testset "hessian/hessian!!" begin x2_new, x2_copy = rand(k, k, k), copy(x2) - rx = hessian!(rx, x2_new) + rx = hessian!!(rx, x2_new) @test hessian(rx) === x2 == x2_new - rx = hessian!(rx, x2_copy) + rx = hessian!!(rx, x2_copy) s2_new = rand(k, k, k) - rs = hessian!(rs, s2_new) + rs = hessian!!(rs, s2_new) @test hessian(rs) == s2_new @test typeof(hessian(rs)) === typeof(s2) - rs = hessian!(rs, s2) + rs = hessian!!(rs, s2) x2_new, x2_copy = rand(k, k, k), copy(x2) - rx = hessian!(exp, rx, x2_new) + rx = hessian!!(exp, rx, x2_new) @test hessian(rx) === x2 == exp.(x2_new) - rx = hessian!(exp, rx, x2_copy) + rx = hessian!!(exp, rx, x2_copy) s1_new = rand(k, k) - rsmix = hessian!(exp, rsmix, s1_new) + rsmix = hessian!!(exp, rsmix, s1_new) @test hessian(rsmix) == exp.(s1_new) @test typeof(hessian(rsmix)) === typeof(s1) - rsmix = hessian!(exp, rsmix, s1) + rsmix = hessian!!(rsmix, s1) T = typeof(SVector{k*k*k}(rand(k*k*k))) - rs_new = hessian!(rs, convert(T, hessian(rs))) + rs_new = hessian!!(rs, convert(T, hessian(rs))) @test rs_new === rs @test size(gradient(HessianResult(x0))) == size(x0) @@ -296,4 +296,244 @@ using DiffResults: DiffResult, GradientResult, JacobianResult, HessianResult, @test HessianResult(Float32.(x0)).derivs[1] isa Vector{Float32} end + + @testset "deprecations" begin + @testset "value!" begin + @test value(rn) === n0 + @test value(rx) === x0 + @test value(rs) === s0 + @test value(rsmix) === n0 + + rn = @test_deprecated DiffResults.value!(rn, n1) + @test value(rn) === n1 + rn = value!!(rn, n0) + + x0_new, x0_copy = rand(k), copy(x0) + rx = @test_deprecated DiffResults.value!(rx, x0_new) + @test value(rx) === x0 == x0_new + rx = value!!(rx, x0_copy) + + s0_new = rand(k) + rs = @test_deprecated DiffResults.value!(rs, s0_new) + @test value(rs) == s0_new + @test typeof(value(rs)) === typeof(s0) + rs = value!!(rs, s0) + + rsmix = @test_deprecated DiffResults.value!(rsmix, n1) + @test value(rsmix) === n1 + rsmix = value!!(rsmix, n0) + + rn = @test_deprecated DiffResults.value!(exp, rn, n1) + @test value(rn) === exp(n1) + rn = value!!(rn, n0) + + x0_new, x0_copy = rand(k), copy(x0) + rx = @test_deprecated DiffResults.value!(exp, rx, x0_new) + @test value(rx) === x0 == exp.(x0_new) + rx = value!!(rx, x0_copy) + + s0_new = rand(k) + rs = @test_deprecated DiffResults.value!(exp, rs, s0_new) + @test value(rs) == exp.(s0_new) + @test typeof(value(rs)) === typeof(s0) + rs = value!!(rs, s0) + + rsmix = @test_deprecated DiffResults.value!(exp, rsmix, n1) + @test value(rsmix) === exp(n1) + rsmix = value!!(rsmix, n0) + + ksqrt = Int(sqrt(k)) + T = typeof(SMatrix{ksqrt,ksqrt}(rand(ksqrt,ksqrt))) + rs_new = @test_deprecated DiffResults.value!(rs, convert(T, value(rs))) + @test rs_new === rs + end + + @testset "derivative!" begin + @test derivative(rn) === n1 + @test derivative(rn, Val{2}) === n2 + + @test derivative(rx) === x1 + @test derivative(rx, Val{2}) === x2 + + @test derivative(rs) === s1 + @test derivative(rs, Val{2}) === s2 + + @test derivative(rsmix) === s0 + @test derivative(rsmix, Val{2}) === s1 + + rn = @test_deprecated DiffResults.derivative!(rn, n0) + @test derivative(rn) === n0 + rn = derivative!!(rn, n1) + + x1_new, x1_copy = rand(k, k), copy(x1) + rx = @test_deprecated DiffResults.derivative!(rx, x1_new) + @test derivative(rx) === x1 == x1_new + rx = derivative!!(rx, x1_copy) + + s1_new = rand(k, k) + rs = @test_deprecated DiffResults.derivative!(rs, s1_new) + @test derivative(rs) == s1_new + @test typeof(derivative(rs)) === typeof(s1) + rs = derivative!!(rs, s1) + + s0_new = rand(k) + rsmix = @test_deprecated DiffResults.derivative!(rsmix, s0_new) + @test derivative(rsmix) == s0_new + @test typeof(derivative(rsmix)) === typeof(s0) + rsmix = derivative!!(rsmix, s0) + + rn = @test_deprecated DiffResults.derivative!(rn, n1, Val{2}) + @test derivative(rn, Val{2}) === n1 + rn = derivative!!(rn, n2, Val{2}) + + x2_new, x2_copy = rand(k, k, k), copy(x2) + rx = @test_deprecated DiffResults.derivative!(rx, x2_new, Val{2}) + @test derivative(rx, Val{2}) === x2 == x2_new + rx = derivative!!(rx, x2_copy, Val{2}) + + s2_new = rand(k, k, k) + rs = @test_deprecated DiffResults.derivative!(rs, s2_new, Val{2}) + @test derivative(rs, Val{2}) == s2_new + @test typeof(derivative(rs, Val{2})) === typeof(s2) + rs = derivative!!(rs, s2, Val{2}) + + s1_new = rand(k, k) + rsmix = @test_deprecated DiffResults.derivative!(rsmix, s1_new, Val{2}) + @test derivative(rsmix, Val{2}) == s1_new + @test typeof(derivative(rsmix, Val{2})) === typeof(s1) + rsmix = derivative!!(rsmix, s1, Val{2}) + + rn = @test_deprecated DiffResults.derivative!(exp, rn, n0) + @test derivative(rn) === exp(n0) + rn = derivative!!(rn, n1) + + x1_new, x1_copy = rand(k, k), copy(x1) + rx = @test_deprecated DiffResults.derivative!(exp, rx, x1_new) + @test derivative(rx) === x1 == exp.(x1_new) + rx = derivative!!(exp, rx, x1_copy) + + s1_new = rand(k, k) + rs = @test_deprecated DiffResults.derivative!(exp, rs, s1_new) + @test derivative(rs) == exp.(s1_new) + @test typeof(derivative(rs)) === typeof(s1) + rs = derivative!!(exp, rs, s1) + + s0_new = rand(k) + rsmix = @test_deprecated DiffResults.derivative!(exp, rsmix, s0_new) + @test derivative(rsmix) == exp.(s0_new) + @test typeof(derivative(rsmix)) === typeof(s0) + rsmix = derivative!!(exp, rsmix, s0) + + rn = @test_deprecated DiffResults.derivative!(exp, rn, n1, Val{2}) + @test derivative(rn, Val{2}) === exp(n1) + rn = derivative!!(rn, n2, Val{2}) + + x2_new, x2_copy = rand(k, k, k), copy(x2) + rx = @test_deprecated DiffResults.derivative!(exp, rx, x2_new, Val{2}) + @test derivative(rx, Val{2}) === x2 == exp.(x2_new) + rx = derivative!!(exp, rx, x2_copy, Val{2}) + + s2_new = rand(k, k, k) + rs = @test_deprecated DiffResults.derivative!(exp, rs, s2_new, Val{2}) + @test derivative(rs, Val{2}) == exp.(s2_new) + @test typeof(derivative(rs, Val{2})) === typeof(s2) + rs = derivative!!(exp, rs, s2, Val{2}) + + s1_new = rand(k, k) + rsmix = @test_deprecated DiffResults.derivative!(exp, rsmix, s1_new, Val{2}) + @test derivative(rsmix, Val{2}) == exp.(s1_new) + @test typeof(derivative(rsmix, Val{2})) === typeof(s1) + rsmix = derivative!!(exp, rsmix, s1, Val{2}) + end + + @testset "gradient!" begin + x1_new, x1_copy = rand(k, k), copy(x1) + rx = @test_deprecated DiffResults.gradient!(rx, x1_new) + @test gradient(rx) === x1 == x1_new + rx = gradient!!(rx, x1_copy) + + s1_new = rand(k, k) + rs = @test_deprecated DiffResults.gradient!(rs, s1_new) + @test gradient(rs) == s1_new + @test typeof(gradient(rs)) === typeof(s1) + rs = gradient!!(rs, s1) + + x1_new, x1_copy = rand(k, k), copy(x1) + rx = @test_deprecated DiffResults.gradient!(exp, rx, x1_new) + @test gradient(rx) === x1 == exp.(x1_new) + rx = gradient!!(exp, rx, x1_copy) + + s0_new = rand(k) + rsmix = @test_deprecated DiffResults.gradient!(exp, rsmix, s0_new) + @test gradient(rsmix) == exp.(s0_new) + @test typeof(gradient(rsmix)) === typeof(s0) + rsmix = gradient!!(rsmix, s0) + + T = typeof(SVector{k*k}(rand(k*k))) + rs_new = @test_deprecated DiffResults.gradient!(rs, convert(T, gradient(rs))) + @test rs_new === rs + end + + @testset "jacobian!" begin + x1_new, x1_copy = rand(k, k), copy(x1) + rx = @test_deprecated DiffResults.jacobian!(rx, x1_new) + @test jacobian(rx) === x1 == x1_new + rx = jacobian!!(rx, x1_copy) + + s1_new = rand(k, k) + rs = @test_deprecated DiffResults.jacobian!(rs, s1_new) + @test jacobian(rs) == s1_new + @test typeof(jacobian(rs)) === typeof(s1) + rs = jacobian!!(rs, s1) + + x1_new, x1_copy = rand(k, k), copy(x1) + rx = @test_deprecated DiffResults.jacobian!(exp, rx, x1_new) + @test jacobian(rx) === x1 == exp.(x1_new) + rx = jacobian!!(exp, rx, x1_copy) + + s0_new = rand(k) + rsmix = @test_deprecated DiffResults.jacobian!(exp, rsmix, s0_new) + @test jacobian(rsmix) == exp.(s0_new) + @test typeof(jacobian(rsmix)) === typeof(s0) + rsmix = jacobian!!(rsmix, s0) + + T = typeof(SVector{k*k}(rand(k*k))) + rs_new = @test_deprecated DiffResults.jacobian!(rs, convert(T, jacobian(rs))) + @test rs_new === rs + end + + @testset "hessian!" begin + x2_new, x2_copy = rand(k, k, k), copy(x2) + rx = @test_deprecated DiffResults.hessian!(rx, x2_new) + @test hessian(rx) === x2 == x2_new + rx = hessian!!(rx, x2_copy) + + s2_new = rand(k, k, k) + rs = @test_deprecated DiffResults.hessian!(rs, s2_new) + @test hessian(rs) == s2_new + @test typeof(hessian(rs)) === typeof(s2) + rs = hessian!!(rs, s2) + + x2_new, x2_copy = rand(k, k, k), copy(x2) + rx = hessian!!(exp, rx, x2_new) + @test hessian(rx) === x2 == exp.(x2_new) + rx = hessian!!(exp, rx, x2_copy) + + s1_new = rand(k, k) + rsmix = @test_deprecated DiffResults.hessian!(exp, rsmix, s1_new) + @test hessian(rsmix) == exp.(s1_new) + @test typeof(hessian(rsmix)) === typeof(s1) + rsmix = hessian!!(rsmix, s1) + + T = typeof(SVector{k*k*k}(rand(k*k*k))) + rs_new = @test_deprecated DiffResults.hessian!(rs, convert(T, hessian(rs))) + @test rs_new === rs + + @test size(gradient(HessianResult(x0))) == size(x0) + @test size(gradient(HessianResult(x1))) == size(x1) + @test size(gradient(HessianResult(x2))) == size(x2) + + @test HessianResult(Float32.(x0)).derivs[1] isa Vector{Float32} + end + end end