diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 9bda570c1..da7f6a249 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -27,7 +27,7 @@ jobs: id: review with: build_dir: build - exclude: "test/*,benchmark/*" + exclude: "test/*,benchmark/*,demos/*" split_workflow: true cmake_command: > pip install cmake lit && diff --git a/demos/VectorForwardMode.cpp b/demos/VectorForwardMode.cpp new file mode 100644 index 000000000..28661f0ac --- /dev/null +++ b/demos/VectorForwardMode.cpp @@ -0,0 +1,52 @@ +//--------------------------------------------------------------------*- C++ -*- +// clad - The C++ Clang-based Automatic Differentiator +// +// A demo, describing how to use vector forward mode AD to differentiation +// a function with respect to multiple parameters. +//----------------------------------------------------------------------------// + +// To run the demo please type: +// path/to/clang++ -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang \ +// path/to/libclad.so -I../include/ -x c++ -std=c++11 VectorForwardMode.cpp +// +// A typical invocation would be: +// ../../../../obj/Debug+Asserts/bin/clang++ -Xclang -add-plugin -Xclang clad \ +// -Xclang -load -Xclang ../../../../obj/Debug+Asserts/lib/libclad.dylib \ +// -I../include/ -x c++ -std=c++11 VectorForwardMode.cpp + +// Necessary for clad to work include +#include "clad/Differentiator/Differentiator.h" + +// A function for weighted sum of array elements. +double weighted_sum(double* arr, double* weights, int n) { + double res = 0; + for (int i = 0; i < n; ++i) { + res += weights[i] * arr[i]; + } + return res; +} + +int main() { + auto weighted_sum_grad = + clad::differentiate(weighted_sum, "arr,weights"); + + // Initialize array and weights. + double arr[3] = {3.0, 4.0, 5.0}; + double weights[3] = {0.5, 0.7, 0.9}; + + // Allocate memory for derivatives. + double d_arr[3] = {0.0, 0.0, 0.0}; + double d_weights[3] = {0.0, 0.0, 0.0}; + clad::array_ref d_arr_ref(d_arr, 3); + clad::array_ref d_weights_ref(d_weights, 3); + + // Calculate gradient. + weighted_sum_grad.execute(arr, weights, 3, d_arr_ref, d_weights_ref); + printf("Vector forward mode w.r.t. all:\n darr = {%.2g, %.2g, %.2g}\n " + "dweights = " + "{%.2g, %.2g, %.2g}\n", + d_arr[0], d_arr[1], d_arr[2], d_weights[0], d_weights[1], + d_weights[2]); + + return 0; +} diff --git a/lib/Differentiator/VectorForwardModeVisitor.cpp b/lib/Differentiator/VectorForwardModeVisitor.cpp index 039c6c083..f5b72d087 100644 --- a/lib/Differentiator/VectorForwardModeVisitor.cpp +++ b/lib/Differentiator/VectorForwardModeVisitor.cpp @@ -146,8 +146,8 @@ VectorForwardModeVisitor::DeriveVectorMode(const FunctionDecl* FD, // Create an identity matrix for the parameter, // with number of rows equal to the size of the array, // and number of columns equal to the number of independent variables - llvm::SmallVector args = {getSize, m_IndVarCountExpr, - offsetExpr}; + llvm::SmallVector args = {getSize, m_IndVarCountExpr, + offsetExpr}; dVectorParam = BuildCallExprToCladFunction("identity_matrix", args, {dParamType}, loc); @@ -160,7 +160,7 @@ VectorForwardModeVisitor::DeriveVectorMode(const FunctionDecl* FD, } } else { // Create a one hot vector for the parameter. - llvm::SmallVector args = {m_IndVarCountExpr, offsetExpr}; + llvm::SmallVector args = {m_IndVarCountExpr, offsetExpr}; dVectorParam = BuildCallExprToCladFunction("one_hot_vector", args, {dParamType}, loc); ++nonArrayIndVarCount; @@ -444,21 +444,21 @@ StmtDiff VectorForwardModeVisitor::VisitArraySubscriptExpr( std::transform(std::begin(Indices), std::end(Indices), std::begin(clonedIndices), [this](const Expr* E) { return Clone(E); }); - auto cloned = BuildArraySubscript(clonedBase, clonedIndices); + auto* cloned = BuildArraySubscript(clonedBase, clonedIndices); QualType ExprTy = ASE->getType(); if (ExprTy->isPointerType()) ExprTy = ExprTy->getPointeeType(); - auto zero = ConstantFolder::synthesizeLiteral(ExprTy, m_Context, 0); + auto* zero = ConstantFolder::synthesizeLiteral(ExprTy, m_Context, 0); Expr* diffExpr = zero; Expr* target = BaseDiff.getExpr_dx(); if (target) { - diffExpr = - m_Sema - .ActOnArraySubscriptExpr(getCurrentScope(), target, - target->getExprLoc(), clonedIndices, noLoc) - .get(); + diffExpr = m_Sema + .ActOnArraySubscriptExpr(getCurrentScope(), target, + target->getExprLoc(), + clonedIndices.front(), noLoc) + .get(); } return StmtDiff(cloned, diffExpr); } @@ -515,7 +515,7 @@ StmtDiff VectorForwardModeVisitor::VisitReturnStmt(const ReturnStmt* RS) { Expr* getSize = BuildArrayRefSizeExpr(dParam); // Create an expression to fetch slice of the return vector. - llvm::SmallVector args = {offsetExpr, getSize}; + llvm::SmallVector args = {offsetExpr, getSize}; dParamValue = BuildArrayRefSliceExpr(dVectorRef, args); // Update the array independent expression. diff --git a/test/Misc/RunDemos.C b/test/Misc/RunDemos.C index 6e000b119..4eb001176 100644 --- a/test/Misc/RunDemos.C +++ b/test/Misc/RunDemos.C @@ -311,3 +311,33 @@ // CHECK_ARRAYS_EXEC: {0, 0, 0} // CHECK_ARRAYS_EXEC: {0, 0, 0} // CHECK_ARRAYS_EXEC: {0, 0, 0} + +//-----------------------------------------------------------------------------/ +// Demo: VectorForwardMode.cpp +//-----------------------------------------------------------------------------/ +// RUN: %cladclang %S/../../demos/VectorForwardMode.cpp -I%S/../../include -oVectorForwardMode.out 2>&1 | FileCheck -check-prefix CHECK_VECTOR_FORWARD_MODE %s +// CHECK_VECTOR_FORWARD_MODE: void weighted_sum_dvec_0_1(double *arr, double *weights, int n, clad::array_ref _d_arr, clad::array_ref _d_weights) { +// CHECK_VECTOR_FORWARD_MODE-NEXT unsigned long indepVarCount = _d_arr.size() + _d_weights.size(); +// CHECK_VECTOR_FORWARD_MODE-NEXT clad::matrix _d_vector_arr = clad::identity_matrix(_d_arr.size(), indepVarCount, 0UL); +// CHECK_VECTOR_FORWARD_MODE-NEXT clad::matrix _d_vector_weights = clad::identity_matrix(_d_weights.size(), indepVarCount, _d_arr.size()); +// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array _d_vector_n = clad::zero_vector(indepVarCount); +// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array _d_vector_res(clad::array(indepVarCount, 0)); +// CHECK_VECTOR_FORWARD_MODE-NEXT double res = 0; +// CHECK_VECTOR_FORWARD_MODE-NEXT { +// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array _d_vector_i(clad::array(indepVarCount, 0)); +// CHECK_VECTOR_FORWARD_MODE-NEXT for (int i = 0; i < n; ++i) { +// CHECK_VECTOR_FORWARD_MODE-NEXT _d_vector_res += (_d_vector_weights[i]) * arr[i] + weights[i] * (_d_vector_arr[i]); +// CHECK_VECTOR_FORWARD_MODE-NEXT res += weights[i] * arr[i]; +// CHECK_VECTOR_FORWARD_MODE-NEXT } +// CHECK_VECTOR_FORWARD_MODE-NEXT } +// CHECK_VECTOR_FORWARD_MODE-NEXT { +// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array _d_vector_return(clad::array(indepVarCount, _d_vector_res)); +// CHECK_VECTOR_FORWARD_MODE-NEXT _d_arr = _d_vector_return.slice(0UL, _d_arr.size()); +// CHECK_VECTOR_FORWARD_MODE-NEXT _d_weights = _d_vector_return.slice(_d_arr.size(), _d_weights.size()); +// CHECK_VECTOR_FORWARD_MODE-NEXT return; +// CHECK_VECTOR_FORWARD_MODE-NEXT } +// CHECK_VECTOR_FORWARD_MODE-NEXT } +// RUN: ./VectorForwardMode.out | FileCheck -check-prefix CHECK_VECTOR_FORWARD_MODE_EXEC %s +// CHECK_VECTOR_FORWARD_MODE_EXEC: Vector forward mode w.r.t. all: +// CHECK_VECTOR_FORWARD_MODE_EXEC: darr = {0.5, 0.7, 0.9} +// CHECK_VECTOR_FORWARD_MODE_EXEC: dweights = {3, 4, 5} \ No newline at end of file