# Nth (univariate) derivative using AD

**URL:** <https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504>\
**Category:** General Usage\
**Tags:** question, forwarddiff\
**Created:** [September 20, 2022, 7:50am UTC](https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504 "2022-09-20T07:50:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [September 20, 2022, 7:50am UTC](https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504/1 "2022-09-20T07:50:54Z")

</div>

I need an n th derivative of a univariate function for testing purposes. I came up with

```julia
import ForwardDiff

function ddn(f, x, ::Val{N}) where {N}
    fn = foldl((f, _) -> x -> ForwardDiff.derivative(f, x),
               ntuple(_ -> nothing, Val(N)); init = f)
    fn(x)
end

@code_warntype ddn(sin, 0.0, Val(3)) # type stable

```

but I am interested in other solutions.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [September 20, 2022, 7:54am UTC](https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504/2 "2022-09-20T07:54:38Z")

</div>

I’ve seen people use [GitHub - JuliaDiff/TaylorSeries.jl: Taylor polynomial expansions in one and several independent variables.](https://github.com/JuliaDiff/TaylorSeries.jl) for higher-order scalar differentiation. I can’t tell you if this is the recommended approach today though.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [September 20, 2022, 8:54am UTC](https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504/3 "2022-09-20T08:54:45Z")

</div>

I thought Diffractor was meant to be especially suited to higher-order derivatives? I’m not really an AD user myself but based on some of the discussions I’ve seen on Slack it sounds like people have got it to work on quite a few test cases at this point, although afaik it’s still rather experimental.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [September 20, 2022, 2:39pm UTC](https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504/4 "2022-09-20T14:39:41Z")

</div>

Thanks for all the replies. I went with the original code above, finding it the simplest — I only need it for unit testing.

Incidentally, I found that implementing a [quick & dirty AD system](https://github.com/tpapp/SpectralKit.jl/blob/c8d6c19f73fc520f7ee07dfcb8c71c7d015b6699/src/derivatives.jl) in \<50 LOC is the best solution I could come up with for calculating higher-order derivatives of Chebyshev polynomials and their Smolyak combinations. It only supports `+`, `-`, `*` for the polynomials, and `/` in addition for transformations.

After many years of Julia, I still find it unbelievable how powerful the language is.

---

<div class="post-metadata">

**Author:** ![cgeoga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cgeoga/32/216186_2.png) [@cgeoga](https://discourse.julialang.org/u/cgeoga)\
**Post date:** [September 20, 2022, 5:12pm UTC](https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504/5 "2022-09-20T17:12:55Z")

</div>

Wow. That’s a very neat use of `foldl`. It’s even faster than using `TaylorSeries` like @baggepinnen mentioned:

```julia
using BenchmarkTools, ForwardDiff, TaylorSeries

function ddn(f, x, ::Val{N}) where {N}
  fn = foldl((f, _) -> x -> ForwardDiff.derivative(f, x),
             ntuple(_ -> nothing, Val(N)); init = f)
  fn(x)
end

# also type stable:
ddn_ts(f, x, N) = f(x+Taylor1(Float64, N))[N]*factorial(N)

# making const as well to be extra paranoid about type stuff.
const x = 1.1
const v = 5
const val_v = Val(v)

# simple f function, but trying to avoid things that are literally in the lookup
# tables for ForwardDiff:
f(x) = exp(cos(log(x+1.1)+1.1)+1.1)

@btime ddn(f, $x, $val_v); # 329 ns, 7 alloc: 336 bytes
@btime ddn_ts(f, $x, $v); # 389 ns 13 alloc: 1.36 KiB

```

Also, wow again about `ForwardDiff` being so hard to beat.

---

<div class="post-metadata">

**Author:** ![qwerty](https://avatars.discourse-cdn.com/v4/letter/q/4491bb/32.png) [@qwerty](https://discourse.julialang.org/u/qwerty)\
**Post date:** [September 20, 2022, 9:24pm UTC](https://discourse.julialang.org/t/nth-univariate-derivative-using-ad/87504/6 "2022-09-20T21:24:58Z")

</div>

OT: [not using AD]

If you want you can calculate the derivatives with Symbolics

```julia
using Symbolics

function der_symbolics(f, a::Int) # f is a callable julia function
    x = Symbolics.variable("x")
    der = (Differential(x)^a)(f(x)) |> expand_derivatives
    eval(build_function(der, x)) # this is a callable julia function
end

sin_third_deriv = der_symbolics(sin, 3) 
sin_third_deriv(0.0)

```

and sin\_third\_deriv is compatible with AD like ForwardDiff.  
der\_symbolics is not fast, however sin\_third\_deriv is fast.
