# Introduction

FastDifferentiation (**FD**) is a package for generating efficient executables to evaluate derivatives of Julia functions. It can also generate efficient true symbolic derivatives for symbolic analysis. Unlike forward and reverse mode automatic differentiation **FD** automatically generates efficient derivatives for arbitrary function types: ℝ¹->ℝ¹, ℝ¹->ℝᵐ, ℝⁿ->ℝ¹, and ℝⁿ->ℝᵐ.

For f:ℝⁿ->ℝᵐ with n,m large **FD** may have better performance than conventional AD algorithms because the **FD** algorithm finds expressions shared between partials and computes them only once. In some cases **FD** derivatives can be as efficient as manually coded derivatives (see the Lagrangian dynamics example in the D* paper or the Benchmarks section of the documentation for another example).

**FD** may take much less time to compute symbolic derivatives than Symbolics.jl even in the ℝ¹->ℝ¹ case. The executables generated by **FD** may also be much faster (see Symbolic Processing).

As of version 0.4.0 **FD** allows you to create expressions with conditionals:

```
julia> @variables x y
y
julia> f = ifelse(x<y,x,y)
(ifelse (x < y) x y)
julia> a = make_function([f],[x,y])
julia> a(1.0,2.0)
1-element Vector{Float64}:
1.0
julia> a(2.0,1.0)
1-element Vector{Float64}:
2.0
```

Howver, you cannot yet compute derivatives of expressions that contain conditionals:

```
julia> jacobian([f],[x,y])
ERROR: Your expression contained ifelse. FastDifferentiation does not yet support differentiation through ifelse or any of these conditionals (max, min, copysign, &, |, xor, <, >, <=, >=, !=, ==, signbit, isreal, iszero, isfinite, isnan, isinf, isinteger, !)
```

This may be a breaking change for some users. In previous versions `x==y`

returned a `Bool`

whereas in 0.4.0 and up it returns an **FD** expression. Some data structures, such as `Dict`

use `==`

by default to determine if two entries are the same. This will no longer work since `x==y`

will not return a `Bool`

. Use an `IDict`

instead since this uses `===`

.

A future PR will add support for differentiating through conditionals.

You should consider using FastDifferentiation when you need:

- a fast executable for evaluating the derivative of a function and the overhead of the preprocessing/compilation time is swamped by evaluation time.
- to do additional symbolic processing on your derivative.
**FD**can generate a true symbolic derivative to be processed further in Symbolics.jl or another computer algebra system.

This is the **FD** feature set:

Dense Jacobian | Sparse Jacobian | Dense Hessian | Sparse Hessian | Higher order derivatives | Jᵀv | Hv | |
---|---|---|---|---|---|---|---|

Compiled function | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |

Symbolic expression | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |

Jᵀv and Jv compute the Jacobian transpose times a vector and the Jacobian times a vector, without explicitly forming the Jacobian matrix. For applications see this paper.

Hv computes the Hessian times a vector without explicitly forming the Hessian matrix. This can be useful when the Hessian matrix is large and sparse.

If you use FD in your work please share the functions you differentiate with me. I'll add them to the benchmarks. The more functions available to test the easier it is for others to determine if FD will help with their problem.

## Notes about special derivatives

The derivative of `|u|`

is `u/|u|`

which is NaN when `u==0`

. This is not a bug. The derivative of the absolute value function is undefined at 0 and the way **FD** signals this is by returning NaN.