From 38f708f4139465bdd58c7ee38835b16a64807c76 Mon Sep 17 00:00:00 2001 From: Mihail Mihov Date: Tue, 29 Oct 2024 15:21:28 +0100 Subject: [PATCH] Add page to documentation explaining `clad::immediate_mode` --- docs/userDocs/source/index.rst | 1 + .../source/user/UsingImmediateMode.rst | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 docs/userDocs/source/user/UsingImmediateMode.rst 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..efc80125a --- /dev/null +++ b/docs/userDocs/source/user/UsingImmediateMode.rst @@ -0,0 +1,70 @@ +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 attributes, 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 it's support, but instead uses clang's API to determine if the functions +are immediate and should be differentiated eariler.