Class DSCompiler

This class implements the computation rules described in Dan Kalman's paper Doubly
Recursive Multivariate Automatic Differentiation, Mathematics Magazine, vol. 75,
no. 3, June 2002. However, in order to avoid performances bottlenecks, the recursive
rules are "compiled" once in an unfold form. This class does this recursion unrolling
and stores the computation rules as simple loops with pre-computed indirection arrays.

This class maps all derivative computation into single dimension arrays that hold the
value and partial derivatives. The class does not hold these arrays, which remains under
the responsibility of the caller. For each combination of number of free parameters and
derivation order, only one compiler is necessary, and this compiler will be used to
perform computations on all arrays provided to it, which can represent hundreds or
thousands of different parameters kept together with all theur partial derivatives.

The arrays on which compilers operate contain only the partial derivatives together
with the 0th derivative, i.e. the value. The partial derivatives are stored in
a compiler-specific order, which can be retrieved using methods getPartialDerivativeIndex and getPartialDerivativeOrders(int). The value is guaranteed to be stored as the first element
(i.e. the getPartialDerivativeIndex method returns
0 when called with 0 for all derivation orders and getPartialDerivativeOrders returns an array filled with 0 when called with 0 as the index).

Note that the ordering changes with number of parameters and derivation order. For example
given 2 parameters x and y, df/dy is stored at index 2 when derivation order is set to 1 (in
this case the array has three elements: f, df/dx and df/dy). If derivation order is set to
2, then df/dy will be stored at index 3 (in this case the array has six elements: f, df/dx,
df/dxdx, df/dy, df/dxdy and df/dydy).

Given this structure, users can perform some simple operations like adding, subtracting
or multiplying constants and negating the elements by themselves, knowing if they want to
mutate their array or create a new array. These simple operations are not provided by
the compiler. The compiler provides only the more complex operations between several arrays.

This class is mainly used as the engine for scalar variable DerivativeStructure.
It can also be used directly to hold several variables in arrays for more complex data
structures. User can for example store a vector of n variables depending on three x, y
and z free parameters in one array as follows:

getPartialDerivativeIndex

If all orders are set to 0, then the 0th order derivative
is returned, which is the value of the function.

The indices of derivatives are between 0 and getSize() - 1.
Their specific order is fixed for a given compiler, but otherwise not
publicly specified. There are however some simple cases which have guaranteed
indices:

the index of 0th order derivative is always 0

if there is only 1 free parameter, then the
derivatives are sorted in increasing derivation order (i.e. f at index 0, df/dp
at index 1, d2f/dp2 at index 2 ...
dkf/dpk at index k),

if the derivation order is 1, then the derivatives
are sorted in increasing free parameter order (i.e. f at index 0, df/dx1
at index 1, df/dx2 at index 2 ... df/dxk at index k),