diff --git a/docs/userDocs/source/index.rst b/docs/userDocs/source/index.rst index 8d41a0135..69da583e3 100644 --- a/docs/userDocs/source/index.rst +++ b/docs/userDocs/source/index.rst @@ -90,6 +90,7 @@ The User Guide user/tutorials user/UsingEnzymeWithinClad user/UsingVectorMode.rst + user/UsingImmediateMode user/FAQ user/DevelopersDocumentation user/IntroductionToClangForCladContributors diff --git a/docs/userDocs/source/user/UsingImmediateMode.rst b/docs/userDocs/source/user/UsingImmediateMode.rst new file mode 100644 index 000000000..e350958b2 --- /dev/null +++ b/docs/userDocs/source/user/UsingImmediateMode.rst @@ -0,0 +1,71 @@ +Using Clad-generated derivatives in an immediate context +********************************************************** + +The derivatives that Clad generates are valid C++ code, which could in theory +be executed at compile-time (or in an immediate context as the C++ standard +calls it). When a function is differentiated all specifiers, such as +`constexpr` and `consteval` are kept, but it is important to understand the +interface that Clad provides for those derivatives to the user. + +When Clad differentiates a function (e.g. with `clad::differentiate`) the user +receives a `CladFunction`, which contains a function pointer to the generated +derivative, among many other things. Unfortunately due to how the C++ standard +is written handling function pointers in an immediate context is very +restricted and care needs to be taken to not violate the rules or the compiler +won't be able to evaluate our `constexpr`/`consteval` functions during +translation. + +Currently to get a `CladFunction` that is usable in immediate mode the user has +to pass `clad::immediate_mode` to the differentiation function and that removes +the ability to dump the generated derivative, but it may be possible to add +support for that in the future. + +Usage of Clad's immediate mode +================================================ + +The following code snippet shows how one can request Clad to use the immediate +mode for differentiation:: + + #include "clad/Differentiator/Differentiator.h" + + constexpr double fn(double x, double y) { + return (x + y) / 2; + } + + constexpr double fn_test() { + auto dx = clad::differentiate(fn, "x"); + + return dx.execute(4, 7); + } + + int main(){ + constexpr double fn_result = fn_test(); + + printf("%.2f\n", fn_result); + } + +It is neccessary both to pass the `clad::immediate_mode` option to +`clad::differentiate` and to keep both the call to `clad::differentiate` and +all it's `.execute(...)` calls in the same immediate context, as the C++ +standard forbids having a function pointer to an immediate function outside of +an immediate context. (It is not possible to do the differentiation and +executions in main as `dx` would contain such a pointer, but `main` is not and +can not be immediate) + +When using `constexpr` there is no easy way to tell whether the functions are +actually being evaluated during translation, so it is a good idea to use either +`consteval` or an `if consteval` (in C++23 and newer) to check if the immediate +contexts are behaving as expected or assign the results to a variable marked +`constexpr` as that would fail if the expression that is being assigned isn't +immediate. + +Use cases supported by Clad's immediate mode +================================================ + +Currently Clad's immediate mode is primarily meant to be used in the forward +mode (`clad::differentiate`) as internal data structures that Clad needs for +differentiating loops, etc. are not yet usable in an immediate context. + +Both `constexpr` and `consteval` are supported as Clad doesn't actually rely on +these specific keywords for its support, but instead uses clang's API to +determine if the functions are immediate and should be differentiated eariler.