API reference¶
-
class CladFunction¶
Provides an interface to easily access, call and print the differentiated function.
Every entry point below –
differentiate(),gradient(),hessian(),jacobian()andestimate_error()– returns one of these. It is a small wrapper around a pointer to the generated derivative, which Clad fills in while compiling the call.-
template<class ...Args>
return_type_t<F> execute(Args&&... args) const¶ Calls the generated derivative. The arguments are the ones the original function takes, followed by the ones the derivative adds – a pointer or reference per differentiated parameter in reverse mode, the result matrix in Hessian and Jacobian mode. Each mode’s entry below shows its signature.
For the derivative of a member function, the object to call it on comes first, unless
setObject()has already supplied one.
-
template<class ...Args>
auto operator()(Args&&... args) const¶ Same as
execute(), so aCladFunctioncan be passed wherever a callable is expected.
-
const char *getCode() const¶
Returns the source code of the generated derivative, which Clad stores in the object as a string literal while compiling.
-
CladFunctionType getFunctionPtr() const¶
Returns a pointer to the generated derivative, for code that needs the plain function pointer rather than the wrapper.
-
void setObject(FunctorType *functor)¶
-
void setObject(FunctorType &functor)¶
Remembers an object for the derivative of a member function or a functor, so later
execute()calls need not pass one.
-
void clearObject()¶
Forgets the object set by
setObject().
-
template<class ...Args>
return_type_t<F> execute_kernel(dim3 grid, dim3 block, Args&&... args)¶ Launches the derivative of a CUDA kernel with the given grid and block dimensions. Only available when compiling CUDA code, and the only way to call the derivative of a
__global__function –execute()refuses it. See CUDA support.
-
template<class ...Args>
- template<class Fn>
CladFunction differentiate(Fn fn, const char *args)¶Differentiates
fnwith respect to the one parameter named inargs, using forward mode. The generated function has the signature offnand returns the derivative in place of the value. Ifargsis omitted, the first parameter is used.One call gives the derivative with respect to one parameter, so forward mode suits a function with more outputs than inputs. Reverse mode is the choice when there are many inputs; Core concepts explains why.
#include "clad/Differentiator/Differentiator.h" #include <cstdio> double func(double x, double y) { return x * x * y + y * y; } int main() { // fn_dx is a CladFunction, a tiny wrapper over the derived function pointer. // It differentiates 'func' with respect to 'x'. auto fn_dx = clad::differentiate(func, "x"); // Call it at (x, y) = (5, 3). double func1stOrderDerivative = fn_dx.execute(5, 3); printf("Result is %g\n", func1stOrderDerivative); // prints: Result is 30 }
- template<class Fn>
CladFunction gradient(Fn fn, const char *args)¶Differentiates
fnwith respect to every parameter named inargs, using reverse mode, or with respect to all of them ifargsis omitted. The generated function returns nothing and takes one extra pointer per differentiated parameter, which it accumulates into, so the caller allocates them and sets them to zero.One call gives every derivative at once, which is why reverse mode suits a function with many inputs and few outputs – the usual case for a cost or a likelihood.
#include "clad/Differentiator/Differentiator.h" #include <cstdio> double func(double i, double j) { return 5 * i * i + 2 * j; } int main() { auto fn_grad = clad::gradient(func); double d_i = 0, d_j = 0; fn_grad.execute(3, 5, &d_i, &d_j); printf("Result is %g, %g\n", d_i, d_j); // prints: Result is 30, 2 }
- template<class Fn>
CladFunction hessian(Fn fn, const char *args)¶This function generates a function that can be used to compute hessian matrix of the provided function (
fn) with respect to all the arguments specified inargs.#include "clad/Differentiator/Differentiator.h" #include <cstdio> double func(double i, double j) { double a = i * j; double b = 4 * a; return b * i; } int main() { auto fn_hesn = clad::hessian(func); // Two independent variables, so the hessian needs 2 * 2 elements. double matrix[4] = {0}; fn_hesn.execute(8, 2, matrix); printf("Result is %g, %g, %g, %g\n", matrix[0], matrix[1], matrix[2], matrix[3]); // prints: Result is 16, 64, 64, 0 }
- template<class Fn>
CladFunction jacobian(Fn fn, const char *args)¶This function generates a function that can be used to compute jacobian matrix of the provided function (
fn) with respect to all the arguments specified inargs. If no explicitargsargument is specified, then the jacobian is computed with respect to all the input parameters. The matrix has one row per element of the output and one column per independent scalar, counting the elements of the output array itself. For two scalar parameters and an output array of three elements that is \(3 \times 5\).#include "clad/Differentiator/Differentiator.h" #include <cstdio> void func(double i, double j, double result[]) { result[0] = i * i * j; result[1] = j * j * i; result[2] = j * i; } int main() { auto fn_jcbn = clad::jacobian(func); // One row per element of result, one column per independent scalar: i, j and // the three elements of result itself. clad::matrix<double> d_res(3, 5); double res[3] = {0}; fn_jcbn.execute(8, 2, res, &d_res); printf("Result is\n %g %g\n %g %g\n %g %g\n", d_res[0][0], d_res[0][1], d_res[1][0], d_res[1][1], d_res[2][0], d_res[2][1]); // prints: Result is // prints: 32 64 // prints: 4 32 // prints: 2 8 }
- template<class Fn>
CladFunction estimate_error(Fn fn, const char *args)¶This function generates a function that computes the gradient of
fnand, along the way, an estimate of the floating-point error committed while evaluating it. The estimate comes from the same reverse sweep: the adjoint of a value says how strongly the result depends on it, so multiplying it by the rounding error of that value and summing over the program gives the error in the result.The generated function has the signature
clad::gradient(fn)would produce, with one more parameter at the end, of typedouble&, which receives the total estimated error.#include "clad/Differentiator/Differentiator.h" #include <cstdio> double func(double x, double y) { double z = x * y; return z + x; } int main() { auto fn_err = clad::estimate_error(func); double d_x = 0, d_y = 0, error = 0; fn_err.execute(3, 5, &d_x, &d_y, error); printf("Result is %g, %g with an error of %.2e\n", d_x, d_y, error); // prints: Result is 6, 3 with an error of 7.87e-06 }By default the error of each value is estimated with a Taylor approximation model. A different model can be supplied instead; see Floating-point error estimation.
Numerical differentiation is not an entry point of its own: Clad falls back to
it while differentiating, and reports through -fprint-num-diff-errors.
-DCLAD_NO_NUM_DIFF turns the fallback off. The two standalone interfaces,
forward_central_difference and central_difference, are described in
Numerical Differentiation.