From 87885742b5481e543f3ac63c535e58bf328b3139 Mon Sep 17 00:00:00 2001 From: Vaibhav Thakkar Date: Wed, 3 Apr 2024 03:14:33 +0200 Subject: [PATCH] Fix hessian with new schedule plan and add tests --- demos/Arrays.cpp | 7 +- lib/Differentiator/BaseForwardModeVisitor.cpp | 263 +++++++++--------- lib/Differentiator/HessianModeVisitor.cpp | 14 +- lib/Differentiator/ReverseModeVisitor.cpp | 92 +++--- .../FunctionCallsWithResults.C | 27 ++ test/Hessian/BuiltinDerivatives.C | 240 ++++++++-------- test/Hessian/Hessians.C | 148 +++++----- test/Hessian/NestedFunctionCalls.C | 43 ++- test/Hessian/Pointers.C | 26 +- test/Misc/RunDemos.C | 10 +- 10 files changed, 478 insertions(+), 392 deletions(-) diff --git a/demos/Arrays.cpp b/demos/Arrays.cpp index e6bd1b6f6..e1462bd8c 100644 --- a/demos/Arrays.cpp +++ b/demos/Arrays.cpp @@ -70,10 +70,10 @@ int main() { // the indexes of the array by using the format arr[0:] auto hessian_all = clad::hessian(weighted_avg, "arr[0:2], weights[0:2]"); // Generates the Hessian matrix for weighted_avg w.r.t. to arr. - // auto hessian_arr = clad::hessian(weighted_avg, "arr[0:2]"); + auto hessian_arr = clad::hessian(weighted_avg, "arr[0:2]"); double matrix_all[36] = {0}; - // double matrix_arr[9] = {0}; + double matrix_arr[9] = {0}; hessian_all.execute(arr, weights, matrix_all); printf("Hessian Mode w.r.t. to all:\n matrix =\n" @@ -93,7 +93,7 @@ int main() { matrix_all[28], matrix_all[29], matrix_all[30], matrix_all[31], matrix_all[32], matrix_all[33], matrix_all[34], matrix_all[35]); - /*hessian_arr.execute(arr, weights, matrix_arr); + hessian_arr.execute(arr, weights, matrix_arr); printf("Hessian Mode w.r.t. to arr:\n matrix =\n" " {%.2g, %.2g, %.2g}\n" " {%.2g, %.2g, %.2g}\n" @@ -101,5 +101,4 @@ int main() { matrix_arr[0], matrix_arr[1], matrix_arr[2], matrix_arr[3], matrix_arr[4], matrix_arr[5], matrix_arr[6], matrix_arr[7], matrix_arr[8]); - */ } diff --git a/lib/Differentiator/BaseForwardModeVisitor.cpp b/lib/Differentiator/BaseForwardModeVisitor.cpp index e3e4d5172..c27c1dbf5 100644 --- a/lib/Differentiator/BaseForwardModeVisitor.cpp +++ b/lib/Differentiator/BaseForwardModeVisitor.cpp @@ -212,143 +212,150 @@ BaseForwardModeVisitor::Derive(const FunctionDecl* FD, derivedFD->setParams(paramsRef); derivedFD->setBody(nullptr); - // Function body scope - beginScope(Scope::FnScope | Scope::DeclScope); - m_DerivativeFnScope = getCurrentScope(); - beginBlock(); - // For each function parameter variable, store its derivative value. - for (auto param : params) { - // We cannot create derivatives of reference type since seed value is - // always a constant (r-value). We assume that all the arguments have no - // relation among them, thus it is safe (correct) to use the corresponding - // non-reference type for creating the derivatives. - QualType dParamType = param->getType().getNonReferenceType(); - // We do not create derived variable for array/pointer parameters. - if (!BaseForwardModeVisitor::IsDifferentiableType(dParamType) || - utils::isArrayOrPointerType(dParamType)) - continue; - Expr* dParam = nullptr; - if (dParamType->isRealType()) { - // If param is independent variable, its derivative is 1, otherwise 0. - int dValue = (param == m_IndependentVar); - dParam = - ConstantFolder::synthesizeLiteral(m_Context.IntTy, m_Context, dValue); - } - // For each function arg, create a variable _d_arg to store derivatives - // of potential reassignments, e.g.: - // double f_darg0(double x, double y) { - // double _d_x = 1; - // double _d_y = 0; - // ... - auto dParamDecl = - BuildVarDecl(dParamType, "_d_" + param->getNameAsString(), dParam); - addToCurrentBlock(BuildDeclStmt(dParamDecl)); - dParam = BuildDeclRef(dParamDecl); - if (dParamType->isRecordType() && param == m_IndependentVar) { - llvm::SmallVector ref(diffVarInfo.fields.begin(), - diffVarInfo.fields.end()); - Expr* memRef = - utils::BuildMemberExpr(m_Sema, getCurrentScope(), dParam, ref); - assert(memRef->getType()->isRealType() && - "Forward mode can only differentiate w.r.t builtin scalar " - "numerical types."); - addToCurrentBlock(BuildOp( - BinaryOperatorKind::BO_Assign, memRef, - ConstantFolder::synthesizeLiteral(m_Context.IntTy, m_Context, 1))); - } - // Memorize the derivative of param, i.e. whenever the param is visited - // in the future, it's derivative dParam is found (unless reassigned with - // something new). - m_Variables[param] = dParam; - } - - if (auto MD = dyn_cast(FD)) { - // We cannot create derivative of lambda yet because lambdas default - // constructor is deleted. - if (MD->isInstance() && !MD->getParent()->isLambda()) { - QualType thisObjectType = - clad_compat::CXXMethodDecl_GetThisObjectType(m_Sema, MD); - QualType thisType = MD->getThisType(); - // Here we are effectively doing: - // ``` - // Class _d_this_obj; - // Class* _d_this = &_d_this_obj; - // ``` - // We are not creating `this` expression derivative using `new` because - // then we would be responsible for freeing the memory as well and its - // more convenient to let compiler handle the object lifecycle. - VarDecl* derivativeVD = BuildVarDecl(thisObjectType, "_d_this_obj"); - DeclRefExpr* derivativeE = BuildDeclRef(derivativeVD); - VarDecl* thisExprDerivativeVD = - BuildVarDecl(thisType, "_d_this", - BuildOp(UnaryOperatorKind::UO_AddrOf, derivativeE)); - addToCurrentBlock(BuildDeclStmt(derivativeVD)); - addToCurrentBlock(BuildDeclStmt(thisExprDerivativeVD)); - m_ThisExprDerivative = BuildDeclRef(thisExprDerivativeVD); + if (!request.DeclarationOnly) { + // Function body scope + beginScope(Scope::FnScope | Scope::DeclScope); + m_DerivativeFnScope = getCurrentScope(); + beginBlock(); + // For each function parameter variable, store its derivative value. + for (auto* param : params) { + // We cannot create derivatives of reference type since seed value is + // always a constant (r-value). We assume that all the arguments have no + // relation among them, thus it is safe (correct) to use the corresponding + // non-reference type for creating the derivatives. + QualType dParamType = param->getType().getNonReferenceType(); + // We do not create derived variable for array/pointer parameters. + if (!BaseForwardModeVisitor::IsDifferentiableType(dParamType) || + utils::isArrayOrPointerType(dParamType)) + continue; + Expr* dParam = nullptr; + if (dParamType->isRealType()) { + // If param is independent variable, its derivative is 1, otherwise 0. + int dValue = (param == m_IndependentVar); + dParam = ConstantFolder::synthesizeLiteral(m_Context.IntTy, m_Context, + dValue); + } + // For each function arg, create a variable _d_arg to store derivatives + // of potential reassignments, e.g.: + // double f_darg0(double x, double y) { + // double _d_x = 1; + // double _d_y = 0; + // ... + auto* dParamDecl = + BuildVarDecl(dParamType, "_d_" + param->getNameAsString(), dParam); + addToCurrentBlock(BuildDeclStmt(dParamDecl)); + dParam = BuildDeclRef(dParamDecl); + if (dParamType->isRecordType() && param == m_IndependentVar) { + llvm::SmallVector ref(diffVarInfo.fields.begin(), + diffVarInfo.fields.end()); + Expr* memRef = + utils::BuildMemberExpr(m_Sema, getCurrentScope(), dParam, ref); + assert(memRef->getType()->isRealType() && + "Forward mode can only differentiate w.r.t builtin scalar " + "numerical types."); + addToCurrentBlock(BuildOp( + BinaryOperatorKind::BO_Assign, memRef, + ConstantFolder::synthesizeLiteral(m_Context.IntTy, m_Context, 1))); + } + // Memorize the derivative of param, i.e. whenever the param is visited + // in the future, it's derivative dParam is found (unless reassigned with + // something new). + m_Variables[param] = dParam; } - } - // Create derived variable for each member variable if we are - // differentiating a call operator. - if (m_Functor) { - for (FieldDecl* fieldDecl : m_Functor->fields()) { - Expr* dInitializer = nullptr; - QualType fieldType = fieldDecl->getType(); - - if (auto arrType = dyn_cast(fieldType.getTypePtr())) { - if (!arrType->getElementType()->isRealType()) - continue; - - auto arrSize = arrType->getSize().getZExtValue(); - std::vector dArrVal; - - // Create an initializer list to initialize derived variable created - // for array member variable. - // For example, if we are differentiating wrt arr[3], then - // ``` - // double arr[7]; - // ``` - // will get differentiated to, - // + if (const auto* MD = dyn_cast(FD)) { + // We cannot create derivative of lambda yet because lambdas default + // constructor is deleted. + if (MD->isInstance() && !MD->getParent()->isLambda()) { + QualType thisObjectType = + clad_compat::CXXMethodDecl_GetThisObjectType(m_Sema, MD); + QualType thisType = MD->getThisType(); + // Here we are effectively doing: // ``` - // double _d_arr[7] = {0, 0, 0, 1, 0, 0, 0}; + // Class _d_this_obj; + // Class* _d_this = &_d_this_obj; // ``` - for (size_t i = 0; i < arrSize; ++i) { - int dValue = - (fieldDecl == m_IndependentVar && i == m_IndependentVarIndex); - auto dValueLiteral = ConstantFolder::synthesizeLiteral( - m_Context.IntTy, m_Context, dValue); - dArrVal.push_back(dValueLiteral); + // We are not creating `this` expression derivative using `new` because + // then we would be responsible for freeing the memory as well and its + // more convenient to let compiler handle the object lifecycle. + VarDecl* derivativeVD = BuildVarDecl(thisObjectType, "_d_this_obj"); + DeclRefExpr* derivativeE = BuildDeclRef(derivativeVD); + VarDecl* thisExprDerivativeVD = + BuildVarDecl(thisType, "_d_this", + BuildOp(UnaryOperatorKind::UO_AddrOf, derivativeE)); + addToCurrentBlock(BuildDeclStmt(derivativeVD)); + addToCurrentBlock(BuildDeclStmt(thisExprDerivativeVD)); + m_ThisExprDerivative = BuildDeclRef(thisExprDerivativeVD); + } + } + + // Create derived variable for each member variable if we are + // differentiating a call operator. + if (m_Functor) { + for (FieldDecl* fieldDecl : m_Functor->fields()) { + Expr* dInitializer = nullptr; + QualType fieldType = fieldDecl->getType(); + + if (const auto* arrType = + dyn_cast(fieldType.getTypePtr())) { + if (!arrType->getElementType()->isRealType()) + continue; + + auto arrSize = arrType->getSize().getZExtValue(); + std::vector dArrVal; + + // Create an initializer list to initialize derived variable created + // for array member variable. + // For example, if we are differentiating wrt arr[3], then + // ``` + // double arr[7]; + // ``` + // will get differentiated to, + // + // ``` + // double _d_arr[7] = {0, 0, 0, 1, 0, 0, 0}; + // ``` + for (size_t i = 0; i < arrSize; ++i) { + int dValue = + (fieldDecl == m_IndependentVar && i == m_IndependentVarIndex); + auto* dValueLiteral = ConstantFolder::synthesizeLiteral( + m_Context.IntTy, m_Context, dValue); + dArrVal.push_back(dValueLiteral); + } + dInitializer = m_Sema.ActOnInitList(noLoc, dArrVal, noLoc).get(); + } else if (const auto* ptrType = + dyn_cast(fieldType.getTypePtr())) { + if (!ptrType->getPointeeType()->isRealType()) + continue; + // Pointer member variables should be initialised by `nullptr`. + dInitializer = m_Sema.ActOnCXXNullPtrLiteral(noLoc).get(); + } else { + int dValue = (fieldDecl == m_IndependentVar); + dInitializer = ConstantFolder::synthesizeLiteral(m_Context.IntTy, + m_Context, dValue); } - dInitializer = m_Sema.ActOnInitList(noLoc, dArrVal, noLoc).get(); - } else if (auto ptrType = dyn_cast(fieldType.getTypePtr())) { - if (!ptrType->getPointeeType()->isRealType()) - continue; - // Pointer member variables should be initialised by `nullptr`. - dInitializer = m_Sema.ActOnCXXNullPtrLiteral(noLoc).get(); - } else { - int dValue = (fieldDecl == m_IndependentVar); - dInitializer = ConstantFolder::synthesizeLiteral(m_Context.IntTy, - m_Context, dValue); + VarDecl* derivedFieldDecl = + BuildVarDecl(fieldType.getNonReferenceType(), + "_d_" + fieldDecl->getNameAsString(), dInitializer); + addToCurrentBlock(BuildDeclStmt(derivedFieldDecl)); + m_Variables.emplace(fieldDecl, BuildDeclRef(derivedFieldDecl)); } - VarDecl* derivedFieldDecl = - BuildVarDecl(fieldType.getNonReferenceType(), - "_d_" + fieldDecl->getNameAsString(), dInitializer); - addToCurrentBlock(BuildDeclStmt(derivedFieldDecl)); - m_Variables.emplace(fieldDecl, BuildDeclRef(derivedFieldDecl)); } - } - Stmt* BodyDiff = Visit(FD->getBody()).getStmt(); - if (auto CS = dyn_cast(BodyDiff)) - for (Stmt* S : CS->body()) - addToCurrentBlock(S); - else - addToCurrentBlock(BodyDiff); - Stmt* derivativeBody = endBlock(); - derivedFD->setBody(derivativeBody); + Stmt* BodyDiff = Visit(FD->getBody()).getStmt(); + if (auto* CS = dyn_cast(BodyDiff)) + for (Stmt* S : CS->body()) + addToCurrentBlock(S); + else + addToCurrentBlock(BodyDiff); + Stmt* derivativeBody = endBlock(); + derivedFD->setBody(derivativeBody); - endScope(); // Function body scope + endScope(); // Function body scope + + if (request.DerivedFDPrototype) + m_Derivative->setPreviousDeclaration(request.DerivedFDPrototype); + } m_Sema.PopFunctionScopeInfo(); m_Sema.PopDeclContext(); endScope(); // Function decl scope diff --git a/lib/Differentiator/HessianModeVisitor.cpp b/lib/Differentiator/HessianModeVisitor.cpp index f44443341..7ddc3f730 100644 --- a/lib/Differentiator/HessianModeVisitor.cpp +++ b/lib/Differentiator/HessianModeVisitor.cpp @@ -67,9 +67,18 @@ namespace clad { IndependentArgRequest.Args = ReverseModeArgs; IndependentArgRequest.BaseFunctionName = firstDerivative->getNameAsString(); IndependentArgRequest.UpdateDiffParamsInfo(SemaRef); + + // Derive declaration of the the forward mode derivative. + IndependentArgRequest.DeclarationOnly = true; FunctionDecl* secondDerivative = plugin::ProcessDiffRequest(CP, IndependentArgRequest); + // Add the request to derive the definition of the forward mode derivative + // to the schedule. + IndependentArgRequest.DeclarationOnly = false; + IndependentArgRequest.DerivedFDPrototype = secondDerivative; + plugin::AddRequestToSchedule(CP, IndependentArgRequest); + return secondDerivative; } @@ -99,8 +108,9 @@ namespace clad { std::string hessianFuncName = request.BaseFunctionName + "_hessian"; // To be consistent with older tests, nothing is appended to 'f_hessian' if // we differentiate w.r.t. all the parameters at once. - if (!std::equal(m_Function->param_begin(), m_Function->param_end(), - std::begin(args))) { + if (args.size() != FD->getNumParams() || + !std::equal(m_Function->param_begin(), m_Function->param_end(), + args.begin())) { for (auto arg : args) { auto it = std::find(m_Function->param_begin(), m_Function->param_end(), arg); diff --git a/lib/Differentiator/ReverseModeVisitor.cpp b/lib/Differentiator/ReverseModeVisitor.cpp index e50a0ea80..d9283efa3 100644 --- a/lib/Differentiator/ReverseModeVisitor.cpp +++ b/lib/Differentiator/ReverseModeVisitor.cpp @@ -339,6 +339,9 @@ Expr* getArraySizeExpr(const ArrayType* AT, ASTContext& context, // added by the plugins yet. if (!isVectorValued && numExtraParam == 0) shouldCreateOverload = true; + if (request.DerivedFDPrototype) + // If the overload is already created, we don't need to create it again. + shouldCreateOverload = false; const auto* originalFnType = dyn_cast(m_Function->getType()); @@ -386,57 +389,62 @@ Expr* getArraySizeExpr(const ArrayType* AT, ASTContext& context, gradientFD->setParams(paramsRef); gradientFD->setBody(nullptr); - if (isVectorValued) { - // Reference to the output parameter. - m_Result = BuildDeclRef(params.back()); - numParams = args.size(); + if (!request.DeclarationOnly) { + if (isVectorValued) { + // Reference to the output parameter. + m_Result = BuildDeclRef(params.back()); + numParams = args.size(); - // Creates the ArraySubscriptExprs for the independent variables - size_t idx = 0; - for (const auto* arg : args) { - // FIXME: fix when adding array inputs, now we are just skipping all - // array/pointer inputs (not treating them as independent variables). - if (utils::isArrayOrPointerType(arg->getType())) { - if (arg->getName() == "p") - m_Variables[arg] = m_Result; + // Creates the ArraySubscriptExprs for the independent variables + size_t idx = 0; + for (const auto* arg : args) { + // FIXME: fix when adding array inputs, now we are just skipping all + // array/pointer inputs (not treating them as independent variables). + if (utils::isArrayOrPointerType(arg->getType())) { + if (arg->getName() == "p") + m_Variables[arg] = m_Result; + idx += 1; + continue; + } + auto size_type = m_Context.getSizeType(); + unsigned size_type_bits = m_Context.getIntWidth(size_type); + // Create the idx literal. + auto* i = IntegerLiteral::Create( + m_Context, llvm::APInt(size_type_bits, idx), size_type, noLoc); + // Create the jacobianMatrix[idx] expression. + auto* result_at_i = + m_Sema.CreateBuiltinArraySubscriptExpr(m_Result, noLoc, i, noLoc) + .get(); + m_Variables[arg] = result_at_i; idx += 1; - continue; + m_IndependentVars.push_back(arg); } - auto size_type = m_Context.getSizeType(); - unsigned size_type_bits = m_Context.getIntWidth(size_type); - // Create the idx literal. - auto* i = IntegerLiteral::Create( - m_Context, llvm::APInt(size_type_bits, idx), size_type, noLoc); - // Create the jacobianMatrix[idx] expression. - auto* result_at_i = - m_Sema.CreateBuiltinArraySubscriptExpr(m_Result, noLoc, i, noLoc) - .get(); - m_Variables[arg] = result_at_i; - idx += 1; - m_IndependentVars.push_back(arg); } - } - if (m_ExternalSource) - m_ExternalSource->ActBeforeCreatingDerivedFnBodyScope(); + if (m_ExternalSource) + m_ExternalSource->ActBeforeCreatingDerivedFnBodyScope(); - // Function body scope. - beginScope(Scope::FnScope | Scope::DeclScope); - m_DerivativeFnScope = getCurrentScope(); - beginBlock(); - if (m_ExternalSource) - m_ExternalSource->ActOnStartOfDerivedFnBody(request); + // Function body scope. + beginScope(Scope::FnScope | Scope::DeclScope); + m_DerivativeFnScope = getCurrentScope(); + beginBlock(); + if (m_ExternalSource) + m_ExternalSource->ActOnStartOfDerivedFnBody(request); - Stmt* gradientBody = nullptr; + Stmt* gradientBody = nullptr; - if (!use_enzyme) - DifferentiateWithClad(); - else - DifferentiateWithEnzyme(); + if (!use_enzyme) + DifferentiateWithClad(); + else + DifferentiateWithEnzyme(); - gradientBody = endBlock(); - m_Derivative->setBody(gradientBody); - endScope(); // Function body scope + gradientBody = endBlock(); + m_Derivative->setBody(gradientBody); + endScope(); // Function body scope + + if (request.DerivedFDPrototype) + m_Derivative->setPreviousDeclaration(request.DerivedFDPrototype); + } m_Sema.PopFunctionScopeInfo(); m_Sema.PopDeclContext(); endScope(); // Function decl scope diff --git a/test/FirstDerivative/FunctionCallsWithResults.C b/test/FirstDerivative/FunctionCallsWithResults.C index 0323f84d6..1eef5b388 100644 --- a/test/FirstDerivative/FunctionCallsWithResults.C +++ b/test/FirstDerivative/FunctionCallsWithResults.C @@ -268,6 +268,27 @@ double fn8(double i, double j) { // CHECK-NEXT: return _t1.pushforward * _t3 + _t2 * 0; // CHECK-NEXT: } +double g (double x) { return x; } + +// CHECK: clad::ValueAndPushforward g_pushforward(double x, double _d_x); + +double fn9 (double i, double j) { + const int k = 1; + return g(i) * g(j); +} + +// CHECK: double fn9_darg0(double i, double j) { +// CHECK-NEXT: double _d_i = 1; +// CHECK-NEXT: double _d_j = 0; +// CHECK-NEXT: const int _d_k = 0; +// CHECK-NEXT: const int k = 1; +// CHECK-NEXT: clad::ValueAndPushforward _t0 = g_pushforward(i, _d_i); +// CHECK-NEXT: clad::ValueAndPushforward _t1 = g_pushforward(j, _d_j); +// CHECK-NEXT: double &_t2 = _t0.value; +// CHECK-NEXT: double &_t3 = _t1.value; +// CHECK-NEXT: return _t0.pushforward * _t3 + _t2 * _t1.pushforward; +// CHECK-NEXT: } + float test_1_darg0(float x); float test_2_darg0(float x); float test_4_darg0(float x); @@ -296,6 +317,7 @@ int main () { INIT(fn6, "i"); INIT(fn7, "i"); INIT(fn8, "i"); + INIT(fn9, "i"); TEST(fn1, 3, 5); // CHECK-EXEC: {12.00} TEST(fn2, 3, 5); // CHECK-EXEC: {181.00} @@ -305,6 +327,7 @@ int main () { TEST(fn6, 3, 5, 7); // CHECK-EXEC: {3.00} TEST(fn7, 3, 5); // CHECK-EXEC: {8.00} TEST(fn8, 3, 5); // CHECK-EXEC: {19.04} + TEST(fn9, 3, 5); // CHECK-EXEC: {5.00} return 0; // CHECK: clad::ValueAndPushforward sum_of_squares_pushforward(double u, double v, double _d_u, double _d_v) { @@ -377,4 +400,8 @@ int main () { // CHECK-NEXT: return {x, _d_x}; // CHECK-NEXT: return {1, 0}; // CHECK-NEXT: } + +// CHECK: clad::ValueAndPushforward g_pushforward(double x, double _d_x) { +// CHECK-NEXT: return {x, _d_x}; +// CHECK-NEXT: } } diff --git a/test/Hessian/BuiltinDerivatives.C b/test/Hessian/BuiltinDerivatives.C index e10ab3ae2..15ca77e67 100644 --- a/test/Hessian/BuiltinDerivatives.C +++ b/test/Hessian/BuiltinDerivatives.C @@ -20,6 +20,133 @@ float f1(float x) { // CHECK-NEXT: return _t0.pushforward + _t1.pushforward; // CHECK-NEXT: } +// CHECK: void f1_darg0_grad(float x, float *_d_x); + +// CHECK: void f1_hessian(float x, float *hessianMatrix) { +// CHECK-NEXT: f1_darg0_grad(x, hessianMatrix + {{0U|0UL}}); +// CHECK-NEXT: } + +float f2(float x) { + return exp(x); +} + +// CHECK: float f2_darg0(float x) { +// CHECK-NEXT: float _d_x = 1; +// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::exp_pushforward(x, _d_x); +// CHECK-NEXT: return _t0.pushforward; +// CHECK-NEXT: } + +// CHECK: void f2_darg0_grad(float x, float *_d_x); + +// CHECK: void f2_hessian(float x, float *hessianMatrix) { +// CHECK-NEXT: f2_darg0_grad(x, hessianMatrix + {{0U|0UL}}); +// CHECK-NEXT: } + + +float f3(float x) { + return log(x); +} + +// CHECK: float f3_darg0(float x) { +// CHECK-NEXT: float _d_x = 1; +// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::log_pushforward(x, _d_x); +// CHECK-NEXT: return _t0.pushforward; +// CHECK-NEXT: } + +// CHECK: void f3_darg0_grad(float x, float *_d_x); + +// CHECK: void f3_hessian(float x, float *hessianMatrix) { +// CHECK-NEXT: f3_darg0_grad(x, hessianMatrix + {{0U|0UL}}); +// CHECK-NEXT: } + + +float f4(float x) { + return pow(x, 4.0F); +} + +// CHECK: float f4_darg0(float x) { +// CHECK-NEXT: float _d_x = 1; +// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(x, 4.F, _d_x, 0.F); +// CHECK-NEXT: return _t0.pushforward; +// CHECK-NEXT: } + +// CHECK: void f4_darg0_grad(float x, float *_d_x); + +// CHECK: void f4_hessian(float x, float *hessianMatrix) { +// CHECK-NEXT: f4_darg0_grad(x, hessianMatrix + {{0U|0UL}}); +// CHECK-NEXT: } + + +float f5(float x) { + return pow(2.0F, x); +} + +// CHECK: float f5_darg0(float x) { +// CHECK-NEXT: float _d_x = 1; +// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(2.F, x, 0.F, _d_x); +// CHECK-NEXT: return _t0.pushforward; +// CHECK-NEXT: } + +// CHECK: void f5_darg0_grad(float x, float *_d_x); + +// CHECK: void f5_hessian(float x, float *hessianMatrix) { +// CHECK-NEXT: f5_darg0_grad(x, hessianMatrix + {{0U|0UL}}); +// CHECK-NEXT: } + + +float f6(float x, float y) { + return pow(x, y); +} + +// CHECK: float f6_darg0(float x, float y) { +// CHECK-NEXT: float _d_x = 1; +// CHECK-NEXT: float _d_y = 0; +// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(x, y, _d_x, _d_y); +// CHECK-NEXT: return _t0.pushforward; +// CHECK-NEXT: } + +// CHECK: void f6_darg0_grad(float x, float y, float *_d_x, float *_d_y); + +// CHECK: float f6_darg1(float x, float y) { +// CHECK-NEXT: float _d_x = 0; +// CHECK-NEXT: float _d_y = 1; +// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(x, y, _d_x, _d_y); +// CHECK-NEXT: return _t0.pushforward; +// CHECK-NEXT: } + +// CHECK: void f6_darg1_grad(float x, float y, float *_d_x, float *_d_y); + +// CHECK: void f6_hessian(float x, float y, float *hessianMatrix) { +// CHECK-NEXT: f6_darg0_grad(x, y, hessianMatrix + {{0U|0UL}}, hessianMatrix + {{1U|1UL}}); +// CHECK-NEXT: f6_darg1_grad(x, y, hessianMatrix + {{2U|2UL}}, hessianMatrix + {{3U|3UL}}); +// CHECK-NEXT: } + + +#define TEST1(F, x) { \ + result[0] = 0; \ + auto h = clad::hessian(F); \ + h.execute(x, result); \ + printf("Result is = {%.2f}\n", result[0]); \ +} + +#define TEST2(F, x, y) { \ + result[0] = result[1] = result[2] = result[3] = 0; \ + auto h = clad::hessian(F); \ + h.execute(x, y, result); \ + printf("Result is = {%.2f, %.2f, %.2f, %.2f}\n", \ + result[0], result[1], result[2], result[3]);\ +} + +int main() { + float result[4]; + + TEST1(f1, 0); // CHECK-EXEC: Result is = {-1.00} + TEST1(f2, 1); // CHECK-EXEC: Result is = {2.72} + TEST1(f3, 1); // CHECK-EXEC: Result is = {-1.00} + TEST1(f4, 3); // CHECK-EXEC: Result is = {108.00} + TEST1(f5, 3); // CHECK-EXEC: Result is = {3.84} + TEST2(f6, 3, 4); // CHECK-EXEC: Result is = {108.00, 145.65, 145.65, 97.76} + // CHECK: void sin_pushforward_pullback(float x, float d_x, ValueAndPushforward _d_y, float *_d_x, float *_d_d_x) { // CHECK-NEXT: float _t0; // CHECK-NEXT: _t0 = ::std::cos(x); @@ -81,20 +208,6 @@ float f1(float x) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: void f1_hessian(float x, float *hessianMatrix) { -// CHECK-NEXT: f1_darg0_grad(x, hessianMatrix + {{0U|0UL}}); -// CHECK-NEXT: } - -float f2(float x) { - return exp(x); -} - -// CHECK: float f2_darg0(float x) { -// CHECK-NEXT: float _d_x = 1; -// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::exp_pushforward(x, _d_x); -// CHECK-NEXT: return _t0.pushforward; -// CHECK-NEXT: } - // CHECK: void exp_pushforward_pullback(float x, float d_x, ValueAndPushforward _d_y, float *_d_x, float *_d_d_x) { // CHECK-NEXT: float _t0; // CHECK-NEXT: _t0 = ::std::exp(x); @@ -128,21 +241,6 @@ float f2(float x) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: void f2_hessian(float x, float *hessianMatrix) { -// CHECK-NEXT: f2_darg0_grad(x, hessianMatrix + {{0U|0UL}}); -// CHECK-NEXT: } - - -float f3(float x) { - return log(x); -} - -// CHECK: float f3_darg0(float x) { -// CHECK-NEXT: float _d_x = 1; -// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::log_pushforward(x, _d_x); -// CHECK-NEXT: return _t0.pushforward; -// CHECK-NEXT: } - // CHECK: void log_pushforward_pullback(float x, float d_x, ValueAndPushforward _d_y, float *_d_x, float *_d_d_x) { // CHECK-NEXT: goto _label0; // CHECK-NEXT: _label0: @@ -173,21 +271,6 @@ float f3(float x) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: void f3_hessian(float x, float *hessianMatrix) { -// CHECK-NEXT: f3_darg0_grad(x, hessianMatrix + {{0U|0UL}}); -// CHECK-NEXT: } - - -float f4(float x) { - return pow(x, 4.0F); -} - -// CHECK: float f4_darg0(float x) { -// CHECK-NEXT: float _d_x = 1; -// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(x, 4.F, _d_x, 0.F); -// CHECK-NEXT: return _t0.pushforward; -// CHECK-NEXT: } - // CHECK: void pow_pushforward_pullback(float x, float exponent, float d_x, float d_exponent, ValueAndPushforward _d_y, float *_d_x, float *_d_exponent, float *_d_d_x, float *_d_d_exponent) { // CHECK-NEXT: float _d_val = 0; // CHECK-NEXT: float _t0; @@ -262,21 +345,6 @@ float f4(float x) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: void f4_hessian(float x, float *hessianMatrix) { -// CHECK-NEXT: f4_darg0_grad(x, hessianMatrix + {{0U|0UL}}); -// CHECK-NEXT: } - - -float f5(float x) { - return pow(2.0F, x); -} - -// CHECK: float f5_darg0(float x) { -// CHECK-NEXT: float _d_x = 1; -// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(2.F, x, 0.F, _d_x); -// CHECK-NEXT: return _t0.pushforward; -// CHECK-NEXT: } - // CHECK: void f5_darg0_grad(float x, float *_d_x) { // CHECK-NEXT: float _d__d_x = 0; // CHECK-NEXT: ValueAndPushforward _d__t0 = {}; @@ -296,22 +364,6 @@ float f5(float x) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: void f5_hessian(float x, float *hessianMatrix) { -// CHECK-NEXT: f5_darg0_grad(x, hessianMatrix + {{0U|0UL}}); -// CHECK-NEXT: } - - -float f6(float x, float y) { - return pow(x, y); -} - -// CHECK: float f6_darg0(float x, float y) { -// CHECK-NEXT: float _d_x = 1; -// CHECK-NEXT: float _d_y = 0; -// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(x, y, _d_x, _d_y); -// CHECK-NEXT: return _t0.pushforward; -// CHECK-NEXT: } - // CHECK: void f6_darg0_grad(float x, float y, float *_d_x, float *_d_y) { // CHECK-NEXT: float _d__d_x = 0; // CHECK-NEXT: float _d__d_y = 0; @@ -335,13 +387,6 @@ float f6(float x, float y) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: float f6_darg1(float x, float y) { -// CHECK-NEXT: float _d_x = 0; -// CHECK-NEXT: float _d_y = 1; -// CHECK-NEXT: ValueAndPushforward _t0 = clad::custom_derivatives{{(::std)?}}::pow_pushforward(x, y, _d_x, _d_y); -// CHECK-NEXT: return _t0.pushforward; -// CHECK-NEXT: } - // CHECK: void f6_darg1_grad(float x, float y, float *_d_x, float *_d_y) { // CHECK-NEXT: float _d__d_x = 0; // CHECK-NEXT: float _d__d_y = 0; @@ -364,35 +409,4 @@ float f6(float x, float y) { // CHECK-NEXT: _d__d_y += _r3; // CHECK-NEXT: } // CHECK-NEXT: } - -// CHECK: void f6_hessian(float x, float y, float *hessianMatrix) { -// CHECK-NEXT: f6_darg0_grad(x, y, hessianMatrix + {{0U|0UL}}, hessianMatrix + {{1U|1UL}}); -// CHECK-NEXT: f6_darg1_grad(x, y, hessianMatrix + {{2U|2UL}}, hessianMatrix + {{3U|3UL}}); -// CHECK-NEXT: } - - -#define TEST1(F, x) { \ - result[0] = 0; \ - auto h = clad::hessian(F); \ - h.execute(x, result); \ - printf("Result is = {%.2f}\n", result[0]); \ -} - -#define TEST2(F, x, y) { \ - result[0] = result[1] = result[2] = result[3] = 0; \ - auto h = clad::hessian(F); \ - h.execute(x, y, result); \ - printf("Result is = {%.2f, %.2f, %.2f, %.2f}\n", \ - result[0], result[1], result[2], result[3]);\ -} - -int main() { - float result[4]; - - TEST1(f1, 0); // CHECK-EXEC: Result is = {-1.00} - TEST1(f2, 1); // CHECK-EXEC: Result is = {2.72} - TEST1(f3, 1); // CHECK-EXEC: Result is = {-1.00} - TEST1(f4, 3); // CHECK-EXEC: Result is = {108.00} - TEST1(f5, 3); // CHECK-EXEC: Result is = {3.84} - TEST2(f6, 3, 4); // CHECK-EXEC: Result is = {108.00, 145.65, 145.65, 97.76} } diff --git a/test/Hessian/Hessians.C b/test/Hessian/Hessians.C index de90a68d5..a854bb9de 100644 --- a/test/Hessian/Hessians.C +++ b/test/Hessian/Hessians.C @@ -19,80 +19,10 @@ __attribute__((always_inline)) double f_cubed_add1(double a, double b) { //CHECK-NEXT:} void f_cubed_add1_darg0_grad(double a, double b, double *_d_a, double *_d_b); -//CHECK:{{[__attribute__((always_inline)) ]*}}void f_cubed_add1_darg0_grad(double a, double b, double *_d_a, double *_d_b){{[ __attribute__((always_inline))]*}} { -//CHECK-NEXT: double _d__d_a = 0; -//CHECK-NEXT: double _d__d_b = 0; -//CHECK-NEXT: double _d__t0 = 0; -//CHECK-NEXT: double _d__t1 = 0; -//CHECK-NEXT: double _d_a0 = 1; -//CHECK-NEXT: double _d_b0 = 0; -//CHECK-NEXT: double _t00 = a * a; -//CHECK-NEXT: double _t10 = b * b; -//CHECK-NEXT: goto _label0; -//CHECK-NEXT: _label0: -//CHECK-NEXT: { -//CHECK-NEXT: _d__d_a += 1 * a * a; -//CHECK-NEXT: *_d_a += _d_a0 * 1 * a; -//CHECK-NEXT: *_d_a += 1 * a * _d_a0; -//CHECK-NEXT: _d__d_a += a * 1 * a; -//CHECK-NEXT: *_d_a += (_d_a0 * a + a * _d_a0) * 1; -//CHECK-NEXT: _d__t0 += 1 * _d_a0; -//CHECK-NEXT: _d__d_a += _t00 * 1; -//CHECK-NEXT: _d__d_b += 1 * b * b; -//CHECK-NEXT: *_d_b += _d_b0 * 1 * b; -//CHECK-NEXT: *_d_b += 1 * b * _d_b0; -//CHECK-NEXT: _d__d_b += b * 1 * b; -//CHECK-NEXT: *_d_b += (_d_b0 * b + b * _d_b0) * 1; -//CHECK-NEXT: _d__t1 += 1 * _d_b0; -//CHECK-NEXT: _d__d_b += _t10 * 1; -//CHECK-NEXT: } -//CHECK-NEXT: { -//CHECK-NEXT: *_d_b += _d__t1 * b; -//CHECK-NEXT: *_d_b += b * _d__t1; -//CHECK-NEXT: } -//CHECK-NEXT: { -//CHECK-NEXT: *_d_a += _d__t0 * a; -//CHECK-NEXT: *_d_a += a * _d__t0; -//CHECK-NEXT: } -//CHECK-NEXT:} +//CHECK:{{[__attribute__((always_inline)) ]*}}void f_cubed_add1_darg0_grad(double a, double b, double *_d_a, double *_d_b){{[ __attribute__((always_inline))]*}}; void f_cubed_add1_darg1_grad(double a, double b, double *_d_a, double *_d_b); -//CHECK:{{[__attribute__((always_inline)) ]*}}void f_cubed_add1_darg1_grad(double a, double b, double *_d_a, double *_d_b){{[ __attribute__((always_inline))]*}} { -//CHECK-NEXT: double _d__d_a = 0; -//CHECK-NEXT: double _d__d_b = 0; -//CHECK-NEXT: double _d__t0 = 0; -//CHECK-NEXT: double _d__t1 = 0; -//CHECK-NEXT: double _d_a0 = 0; -//CHECK-NEXT: double _d_b0 = 1; -//CHECK-NEXT: double _t00 = a * a; -//CHECK-NEXT: double _t10 = b * b; -//CHECK-NEXT: goto _label0; -//CHECK-NEXT: _label0: -//CHECK-NEXT: { -//CHECK-NEXT: _d__d_a += 1 * a * a; -//CHECK-NEXT: *_d_a += _d_a0 * 1 * a; -//CHECK-NEXT: *_d_a += 1 * a * _d_a0; -//CHECK-NEXT: _d__d_a += a * 1 * a; -//CHECK-NEXT: *_d_a += (_d_a0 * a + a * _d_a0) * 1; -//CHECK-NEXT: _d__t0 += 1 * _d_a0; -//CHECK-NEXT: _d__d_a += _t00 * 1; -//CHECK-NEXT: _d__d_b += 1 * b * b; -//CHECK-NEXT: *_d_b += _d_b0 * 1 * b; -//CHECK-NEXT: *_d_b += 1 * b * _d_b0; -//CHECK-NEXT: _d__d_b += b * 1 * b; -//CHECK-NEXT: *_d_b += (_d_b0 * b + b * _d_b0) * 1; -//CHECK-NEXT: _d__t1 += 1 * _d_b0; -//CHECK-NEXT: _d__d_b += _t10 * 1; -//CHECK-NEXT: } -//CHECK-NEXT: { -//CHECK-NEXT: *_d_b += _d__t1 * b; -//CHECK-NEXT: *_d_b += b * _d__t1; -//CHECK-NEXT: } -//CHECK-NEXT: { -//CHECK-NEXT: *_d_a += _d__t0 * a; -//CHECK-NEXT: *_d_a += a * _d__t0; -//CHECK-NEXT: } -//CHECK-NEXT:} +//CHECK:{{[__attribute__((always_inline)) ]*}}void f_cubed_add1_darg1_grad(double a, double b, double *_d_a, double *_d_b){{[ __attribute__((always_inline))]*}}; void f_cubed_add1_hessian(double a, double b, double *hessianMatrix); //CHECK:{{[__attribute__((always_inline)) ]*}}void f_cubed_add1_hessian(double a, double b, double *hessianMatrix){{[ __attribute__((always_inline))]*}} { @@ -281,4 +211,78 @@ int main() { TEST3(&Widget::memFn_1, W, 7, 9); // CHECK-EXEC: Result is = {0.00, 15.00, 15.00, 0.00} TEST3(&Widget::memFn_2, W, 7, 9); // CHECK-EXEC: Result is = {5400.00, 4200.00, 4200.00, 0.00} TEST2(fn_def_arg, 3, 5); // CHECK-EXEC: Result is = {0.00, 2.00, 2.00, 0.00} + +//CHECK:{{[__attribute__((always_inline)) ]*}}void f_cubed_add1_darg0_grad(double a, double b, double *_d_a, double *_d_b){{[ __attribute__((always_inline))]*}} { +//CHECK-NEXT: double _d__d_a = 0; +//CHECK-NEXT: double _d__d_b = 0; +//CHECK-NEXT: double _d__t0 = 0; +//CHECK-NEXT: double _d__t1 = 0; +//CHECK-NEXT: double _d_a0 = 1; +//CHECK-NEXT: double _d_b0 = 0; +//CHECK-NEXT: double _t00 = a * a; +//CHECK-NEXT: double _t10 = b * b; +//CHECK-NEXT: goto _label0; +//CHECK-NEXT: _label0: +//CHECK-NEXT: { +//CHECK-NEXT: _d__d_a += 1 * a * a; +//CHECK-NEXT: *_d_a += _d_a0 * 1 * a; +//CHECK-NEXT: *_d_a += 1 * a * _d_a0; +//CHECK-NEXT: _d__d_a += a * 1 * a; +//CHECK-NEXT: *_d_a += (_d_a0 * a + a * _d_a0) * 1; +//CHECK-NEXT: _d__t0 += 1 * _d_a0; +//CHECK-NEXT: _d__d_a += _t00 * 1; +//CHECK-NEXT: _d__d_b += 1 * b * b; +//CHECK-NEXT: *_d_b += _d_b0 * 1 * b; +//CHECK-NEXT: *_d_b += 1 * b * _d_b0; +//CHECK-NEXT: _d__d_b += b * 1 * b; +//CHECK-NEXT: *_d_b += (_d_b0 * b + b * _d_b0) * 1; +//CHECK-NEXT: _d__t1 += 1 * _d_b0; +//CHECK-NEXT: _d__d_b += _t10 * 1; +//CHECK-NEXT: } +//CHECK-NEXT: { +//CHECK-NEXT: *_d_b += _d__t1 * b; +//CHECK-NEXT: *_d_b += b * _d__t1; +//CHECK-NEXT: } +//CHECK-NEXT: { +//CHECK-NEXT: *_d_a += _d__t0 * a; +//CHECK-NEXT: *_d_a += a * _d__t0; +//CHECK-NEXT: } +//CHECK-NEXT:} + +//CHECK:{{[__attribute__((always_inline)) ]*}}void f_cubed_add1_darg1_grad(double a, double b, double *_d_a, double *_d_b){{[ __attribute__((always_inline))]*}} { +//CHECK-NEXT: double _d__d_a = 0; +//CHECK-NEXT: double _d__d_b = 0; +//CHECK-NEXT: double _d__t0 = 0; +//CHECK-NEXT: double _d__t1 = 0; +//CHECK-NEXT: double _d_a0 = 0; +//CHECK-NEXT: double _d_b0 = 1; +//CHECK-NEXT: double _t00 = a * a; +//CHECK-NEXT: double _t10 = b * b; +//CHECK-NEXT: goto _label0; +//CHECK-NEXT: _label0: +//CHECK-NEXT: { +//CHECK-NEXT: _d__d_a += 1 * a * a; +//CHECK-NEXT: *_d_a += _d_a0 * 1 * a; +//CHECK-NEXT: *_d_a += 1 * a * _d_a0; +//CHECK-NEXT: _d__d_a += a * 1 * a; +//CHECK-NEXT: *_d_a += (_d_a0 * a + a * _d_a0) * 1; +//CHECK-NEXT: _d__t0 += 1 * _d_a0; +//CHECK-NEXT: _d__d_a += _t00 * 1; +//CHECK-NEXT: _d__d_b += 1 * b * b; +//CHECK-NEXT: *_d_b += _d_b0 * 1 * b; +//CHECK-NEXT: *_d_b += 1 * b * _d_b0; +//CHECK-NEXT: _d__d_b += b * 1 * b; +//CHECK-NEXT: *_d_b += (_d_b0 * b + b * _d_b0) * 1; +//CHECK-NEXT: _d__t1 += 1 * _d_b0; +//CHECK-NEXT: _d__d_b += _t10 * 1; +//CHECK-NEXT: } +//CHECK-NEXT: { +//CHECK-NEXT: *_d_b += _d__t1 * b; +//CHECK-NEXT: *_d_b += b * _d__t1; +//CHECK-NEXT: } +//CHECK-NEXT: { +//CHECK-NEXT: *_d_a += _d__t0 * a; +//CHECK-NEXT: *_d_a += a * _d__t0; +//CHECK-NEXT: } +//CHECK-NEXT:} } diff --git a/test/Hessian/NestedFunctionCalls.C b/test/Hessian/NestedFunctionCalls.C index 5774fcb0b..2bf974b3f 100644 --- a/test/Hessian/NestedFunctionCalls.C +++ b/test/Hessian/NestedFunctionCalls.C @@ -17,9 +17,7 @@ double f2(double x, double y){ return ans; } -// CHECK: clad::ValueAndPushforward f_pushforward(double x, double y, double _d_x, double _d_y) { -// CHECK-NEXT: return {x * x + y * y, _d_x * x + x * _d_x + _d_y * y + y * _d_y}; -// CHECK-NEXT: } +// CHECK: clad::ValueAndPushforward f_pushforward(double x, double y, double _d_x, double _d_y); // CHECK: double f2_darg0(double x, double y) { // CHECK-NEXT: double _d_x = 1; @@ -30,6 +28,32 @@ double f2(double x, double y){ // CHECK-NEXT: return _d_ans; // CHECK-NEXT: } + +// CHECK: void f2_darg0_grad(double x, double y, double *_d_x, double *_d_y); + + +// CHECK: double f2_darg1(double x, double y) { +// CHECK-NEXT: double _d_x = 0; +// CHECK-NEXT: double _d_y = 1; +// CHECK-NEXT: clad::ValueAndPushforward _t0 = f_pushforward(x, y, _d_x, _d_y); +// CHECK-NEXT: double _d_ans = _t0.pushforward; +// CHECK-NEXT: double ans = _t0.value; +// CHECK-NEXT: return _d_ans; +// CHECK-NEXT: } + +// CHECK: void f2_darg1_grad(double x, double y, double *_d_x, double *_d_y); + +// CHECK: void f2_hessian(double x, double y, double *hessianMatrix) { +// CHECK-NEXT: f2_darg0_grad(x, y, hessianMatrix + {{0U|0UL}}, hessianMatrix + {{1U|1UL}}); +// CHECK-NEXT: f2_darg1_grad(x, y, hessianMatrix + {{2U|2UL}}, hessianMatrix + {{3U|3UL}}); +// CHECK-NEXT: } + + +// CHECK: clad::ValueAndPushforward f_pushforward(double x, double y, double _d_x, double _d_y) { +// CHECK-NEXT: return {x * x + y * y, _d_x * x + x * _d_x + _d_y * y + y * _d_y}; +// CHECK-NEXT: } + + // CHECK: void f_pushforward_pullback(double x, double y, double _d_x, double _d_y, clad::ValueAndPushforward _d_y0, double *_d_x, double *_d_y, double *_d__d_x, double *_d__d_y) { // CHECK-NEXT: goto _label0; // CHECK-NEXT: _label0: @@ -78,14 +102,6 @@ double f2(double x, double y){ // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: double f2_darg1(double x, double y) { -// CHECK-NEXT: double _d_x = 0; -// CHECK-NEXT: double _d_y = 1; -// CHECK-NEXT: clad::ValueAndPushforward _t0 = f_pushforward(x, y, _d_x, _d_y); -// CHECK-NEXT: double _d_ans = _t0.pushforward; -// CHECK-NEXT: double ans = _t0.value; -// CHECK-NEXT: return _d_ans; -// CHECK-NEXT: } // CHECK: void f2_darg1_grad(double x, double y, double *_d_x, double *_d_y) { // CHECK-NEXT: double _d__d_x = 0; @@ -116,10 +132,7 @@ double f2(double x, double y){ // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: void f2_hessian(double x, double y, double *hessianMatrix) { -// CHECK-NEXT: f2_darg0_grad(x, y, hessianMatrix + {{0U|0UL}}, hessianMatrix + {{1U|1UL}}); -// CHECK-NEXT: f2_darg1_grad(x, y, hessianMatrix + {{2U|2UL}}, hessianMatrix + {{3U|3UL}}); -// CHECK-NEXT: } + int main() { auto f_hess = clad::hessian(f2); diff --git a/test/Hessian/Pointers.C b/test/Hessian/Pointers.C index bc8439ed4..06ffe91c8 100644 --- a/test/Hessian/Pointers.C +++ b/test/Hessian/Pointers.C @@ -16,6 +16,21 @@ double nonMemFn(double i, double j) { // CHECK-NEXT: return _d_i * j + i * _d_j; // CHECK-NEXT: } +// CHECK: void nonMemFn_darg0_grad(double i, double j, double *_d_i, double *_d_j); + +// CHECK: double nonMemFn_darg1(double i, double j) { +// CHECK-NEXT: double _d_i = 0; +// CHECK-NEXT: double _d_j = 1; +// CHECK-NEXT: return _d_i * j + i * _d_j; +// CHECK-NEXT: } + +// CHECK: void nonMemFn_darg1_grad(double i, double j, double *_d_i, double *_d_j); + +// CHECK: void nonMemFn_hessian(double i, double j, double *hessianMatrix) { +// CHECK-NEXT: nonMemFn_darg0_grad(i, j, hessianMatrix + {{0U|0UL}}, hessianMatrix + {{1U|1UL}}); +// CHECK-NEXT: nonMemFn_darg1_grad(i, j, hessianMatrix + {{2U|2UL}}, hessianMatrix + {{3U|3UL}}); +// CHECK-NEXT: } + // CHECK: void nonMemFn_darg0_grad(double i, double j, double *_d_i, double *_d_j) { // CHECK-NEXT: double _d__d_i = 0; // CHECK-NEXT: double _d__d_j = 0; @@ -31,12 +46,6 @@ double nonMemFn(double i, double j) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: double nonMemFn_darg1(double i, double j) { -// CHECK-NEXT: double _d_i = 0; -// CHECK-NEXT: double _d_j = 1; -// CHECK-NEXT: return _d_i * j + i * _d_j; -// CHECK-NEXT: } - // CHECK: void nonMemFn_darg1_grad(double i, double j, double *_d_i, double *_d_j) { // CHECK-NEXT: double _d__d_i = 0; // CHECK-NEXT: double _d__d_j = 0; @@ -52,11 +61,6 @@ double nonMemFn(double i, double j) { // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: void nonMemFn_hessian(double i, double j, double *hessianMatrix) { -// CHECK-NEXT: nonMemFn_darg0_grad(i, j, hessianMatrix + {{0U|0UL}}, hessianMatrix + {{1U|1UL}}); -// CHECK-NEXT: nonMemFn_darg1_grad(i, j, hessianMatrix + {{2U|2UL}}, hessianMatrix + {{3U|3UL}}); -// CHECK-NEXT: } - #define NON_MEM_FN_TEST(var)\ res[0]=res[1]=res[2]=res[3]=0;\ var.execute(3, 4, res);\ diff --git a/test/Misc/RunDemos.C b/test/Misc/RunDemos.C index 8f2bfe370..e9779ee8f 100644 --- a/test/Misc/RunDemos.C +++ b/test/Misc/RunDemos.C @@ -273,11 +273,11 @@ // CHECK_ARRAYS_EXEC: {0.33, 0, 0, 0, 0, 0} // CHECK_ARRAYS_EXEC: {0, 0.33, 0, 0, 0, 0} // CHECK_ARRAYS_EXEC: {0, 0, 0.33, 0, 0, 0} -// CHECK_ARRAYS_EXEC-FAIL: Hessian Mode w.r.t. to arr: -// CHECK_ARRAYS_EXEC-FAIL: matrix = -// CHECK_ARRAYS_EXEC-FAIL: {0, 0, 0} -// CHECK_ARRAYS_EXEC-FAIL: {0, 0, 0} -// CHECK_ARRAYS_EXEC-FAIL: {0, 0, 0} +// CHECK_ARRAYS_EXEC: Hessian Mode w.r.t. to arr: +// CHECK_ARRAYS_EXEC: matrix = +// CHECK_ARRAYS_EXEC: {0, 0, 0} +// CHECK_ARRAYS_EXEC: {0, 0, 0} +// CHECK_ARRAYS_EXEC: {0, 0, 0} //-----------------------------------------------------------------------------/ // Demo: VectorForwardMode.cpp