# Computing value and first & second derivatives of a scalar function with scalar input, using ForwardDiff

**URL:** <https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866>\
**Category:** Numerics\
**Tags:** forwarddiff, autodiff\
**Created:** [August 16, 2023, 3:29pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866 "2023-08-16T15:29:50Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [August 16, 2023, 3:29pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866/1 "2023-08-16T15:29:50Z")

</div>

I cannot find, either in the documentation of ForwardDiff, or on the web more widely, any information on how to compute the second derivative of a scalar function with a scalar input. How can I do this? (Given a function `f` that takes `x<:Real` as input).

Is there a way to compute the function output and first and second derivatives simultaneously, like calling `hessian` with a `DiffResult`? Note that this latter approach only works with array-like inputs.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [August 16, 2023, 3:36pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866/2 "2023-08-16T15:36:06Z")

</div>

I think just differentiating twice would work. Although you probably wanna take a look at [GitHub - JuliaDiff/TaylorDiff.jl: Taylor-mode automatic differentiation for higher-order derivatives](https://github.com/JuliaDiff/TaylorDiff.jl) too

---

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [August 16, 2023, 4:12pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866/3 "2023-08-16T16:12:04Z")

</div>

My current solution is as follows:

```julia
function computehessian(f, x::AbstractArray)
    result = DiffResults.HessianResult(x)
    result = ForwardDiff.hessian!(result, f, x)
    return DiffResults.value(result), DiffResults.gradient(result), DiffResults.hessian(result)
end

computehessian(f, x::T) where T <: Number = map(first, computehessian(f ∘ first, StaticArrays.SVector{1, T}(x)))

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [August 16, 2023, 7:05pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866/4 "2023-08-16T19:05:20Z")

</div>

You can differentiate twice:

```julia
df(x) = ForwardDiff.derivative(f,x)
d2f(x) = ForwardDiff.derivative(df,x)

sought_result = (f(x), df(x), d2f(x))

```

---

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [August 16, 2023, 9:00pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866/5 "2023-08-16T21:00:31Z")

</div>

> [@rafael.guerra](#):
>
> ```julia
> df(x) = ForwardDiff.derivative(f,x)
> d2f(x) = ForwardDiff.derivative(df,x)
> 
> sought_result = (f(x), df(x), d2f(x))
> 
> ```

Thanks. The following code:

```julia
using ForwardDiff, DiffResults, StaticArrays, BenchmarkTools

function computehessian(f, x::AbstractArray)
    result = DiffResults.HessianResult(x)
    result = ForwardDiff.hessian!(result, f, x)
    return DiffResults.value(result), DiffResults.gradient(result), DiffResults.hessian(result)
end
computehessian(f, x::T) where T <: Number = map(first, computehessian(f ∘ first, SVector{1, T}(x)))

function computehessian2(f, x)
    df(x) = ForwardDiff.derivative(f, x)
    d2f(x) = ForwardDiff.derivative(df, x)
    return (f(x), df(x), d2f(x))
end

x = rand()
@btime computehessian(exp, $x)
@btime computehessian2(exp, $x)

```

produces

```julia
  50.279 ns (1 allocation: 64 bytes)
  27.513 ns (0 allocations: 0 bytes)

```

so it seems your approach is better. 😃

---

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [August 16, 2023, 9:18pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866/6 "2023-08-16T21:18:13Z")

</div>

However, with a more complicated `f` function it isn’t so clear cut:

```julia
x = rand()
w = rand()
s1 = rand()
s2 = rand()
f(w, s1, s2, x) = log(w * s1 * exp(-0.5 * x * s1 ^ 2) + (1-w) * s2 * exp(-0.5 * x * s2 ^ 2))
expandfunc(args, v) = args[1](args[2:end]..., v)
fixallbutlast(func, args...) = Base.Fix1(expandfunc, (func, args...))
g = fixallbutlast(f, w, s1, s2)
@btime computehessian($g, $x)
@btime computehessian2($g, $x)

```

outputs:

```julia
  69.701 ns (1 allocation: 64 bytes)
  83.289 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [August 16, 2023, 10:04pm UTC](https://discourse.julialang.org/t/computing-value-and-first-second-derivatives-of-a-scalar-function-with-scalar-input-using-forwarddiff/102866/7 "2023-08-16T22:04:33Z")

</div>

Given this slow-down (caused by calling `f` 4 times instead of once), I think it strange that the `hessian!` functionality doesn’t exist for scalar `x`, so I opened an [issue](https://github.com/JuliaDiff/ForwardDiff.jl/issues/661) about it.
