Skip to content

Commit

Permalink
Remove .size() from error estimation.
Browse files Browse the repository at this point in the history
  • Loading branch information
PetroZarytskyi authored and vgvassilev committed Feb 15, 2024
1 parent d1595dc commit d339638
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 38 deletions.
8 changes: 8 additions & 0 deletions include/clad/Differentiator/ErrorEstimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class ErrorEstimationHandler : public ExternalRMVSource {
clang::Expr* m_IdxExpr;
/// A set of declRefExprs for parameter value replacements.
std::unordered_map<const clang::VarDecl*, clang::Expr*> m_ParamRepls;
/// A map from var decls to their size variables (e.g. `var_size`).
std::unordered_map<const clang::VarDecl*, clang::Expr*> m_ArrSizes;
/// An expression to match nested function call errors with their
/// assignee (if any exists).
clang::Expr* m_NestedFuncError = nullptr;
Expand Down Expand Up @@ -244,6 +246,11 @@ class ErrorEstimationHandler : public ExternalRMVSource {
/// loop.
void EmitDeclErrorStmts(VarDeclDiff VDDiff, bool isInsideLoop);

/// This function returns the size expression for a given variable
/// (`var.size()` for clad::array/clad::array_ref
/// or `var_size` for array/pointer types)
clang::Expr* getSizeExpr(const clang::VarDecl* VD);

void InitialiseRMV(ReverseModeVisitor& RMV) override;
void ForgetRMV() override;
void ActBeforeCreatingDerivedFnParamTypes(unsigned&) override;
Expand All @@ -255,6 +262,7 @@ class ErrorEstimationHandler : public ExternalRMVSource {
void ActOnEndOfDerivedFnBody() override;
void ActBeforeDifferentiatingStmtInVisitCompoundStmt() override;
void ActAfterProcessingStmtInVisitCompoundStmt() override;
void ActAfterProcessingArraySubscriptExpr(const clang::Expr* revArrSub) override;
void ActBeforeDifferentiatingSingleStmtBranchInVisitIfStmt() override;
void ActBeforeFinalisingVisitBranchSingleStmtInIfVisitStmt() override;
void ActBeforeDifferentiatingLoopInitStmt() override;
Expand Down
3 changes: 3 additions & 0 deletions include/clad/Differentiator/ExternalRMVSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class ExternalRMVSource {
virtual void ActAfterParsingDiffArgs(const DiffRequest& request,
DiffParams& args) {}

/// This is called after processing array subscript expressions.
virtual void ActAfterProcessingArraySubscriptExpr(const clang::Expr* revArrSub) {}

/// This is called just before creating derived function parameter types.
virtual void ActBeforeCreatingDerivedFnParamTypes(unsigned& numExtraParam) {}

Expand Down
1 change: 1 addition & 0 deletions include/clad/Differentiator/MultiplexExternalRMVSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class MultiplexExternalRMVSource : public ExternalRMVSource {
void ActOnEndOfDerive() override;
void ActAfterParsingDiffArgs(const DiffRequest& request,
DiffParams& args) override;
void ActAfterProcessingArraySubscriptExpr(const clang::Expr* revArrSub) override;
void ActBeforeCreatingDerivedFnParamTypes(unsigned& numExtraParams) override;
void ActAfterCreatingDerivedFnParamTypes(
llvm::SmallVectorImpl<clang::QualType>& paramTypes) override;
Expand Down
76 changes: 66 additions & 10 deletions lib/Differentiator/ErrorEstimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,14 @@ void ErrorEstimationHandler::SaveParamValue(DeclRefExpr* paramRef) {
std::string name = "_EERepl_" + paramDecl->getNameAsString();
VarDecl* savedDecl;
if (utils::isArrayOrPointerType(paramType)) {
auto diffVar = m_RMV->m_Variables[paramDecl];
Expr* size = getSizeExpr(paramDecl);
auto QType = m_RMV->GetCladArrayOfType(
getUnderlyingArrayType(paramType, m_RMV->m_Context));
savedDecl = m_RMV->BuildVarDecl(
QType, name, m_RMV->BuildArrayRefSizeExpr(diffVar),
QType, name, size,
/*DirectInit=*/false,
/*TSI=*/nullptr, VarDecl::InitializationStyle::CallInit);
size = m_RMV->Clone(size);
m_RMV->AddToGlobalBlock(m_RMV->BuildDeclStmt(savedDecl));
ReverseModeVisitor::Stmts loopBody;
// Get iter variable.
Expand All @@ -205,7 +206,7 @@ void ErrorEstimationHandler::SaveParamValue(DeclRefExpr* paramRef) {
getArraySubscriptExpr(paramRef, currIdx,
/*isCladSpType=*/false)));
Expr* conditionExpr =
m_RMV->BuildOp(BO_LT, currIdx, m_RMV->BuildArrayRefSizeExpr(diffVar));
m_RMV->BuildOp(BO_LT, currIdx, size);
Expr* incExpr = m_RMV->BuildOp(UO_PostInc, currIdx);
// Make for loop.
Stmt* ArrayParamLoop = new (m_RMV->m_Context) ForStmt(
Expand All @@ -227,10 +228,14 @@ Expr* ErrorEstimationHandler::RegisterVariable(VarDecl* VD,
// The type of the _delta_ value should be customisable.
QualType QType;
Expr* deltaVar = nullptr;
auto diffVar = m_RMV->m_Variables[VD];
if (m_RMV->isCladArrayType(diffVar->getType())) {
if (utils::isArrayOrPointerType(VDType)) {
VarDecl* EstVD;
auto sizeExpr = m_RMV->BuildArrayRefSizeExpr(diffVar);
auto diffVar = m_RMV->m_Variables[VD];
Expr* sizeExpr = nullptr;
if (m_RMV->isCladArrayType(diffVar->getType()))
sizeExpr = m_RMV->BuildArrayRefSizeExpr(diffVar);
else
sizeExpr = getSizeExpr(VD);
QType = m_RMV->GetCladArrayOfType(
getUnderlyingArrayType(VDType, m_RMV->m_Context));
EstVD = m_RMV->BuildVarDecl(
Expand All @@ -243,8 +248,7 @@ Expr* ErrorEstimationHandler::RegisterVariable(VarDecl* VD,
m_RMV->addToCurrentBlock(m_RMV->BuildDeclStmt(EstVD), direction::forward);
deltaVar = m_RMV->BuildDeclRef(EstVD);
} else {
QType = utils::isArrayOrPointerType(VDType) ? VDType
: m_RMV->m_Context.DoubleTy;
QType = m_RMV->m_Context.DoubleTy;
init = init ? init : m_RMV->getZeroInit(QType);
// Store the "_delta_*" value.
if (!toCurrentScope) {
Expand Down Expand Up @@ -355,6 +359,7 @@ void ErrorEstimationHandler::EmitFinalErrorStmts(
m_RMV->BuildOp(BO_AddAssign, deltaVar, errorExpr));
} else {
auto LdiffExpr = m_RMV->m_Variables[decl];
Expr* size = getSizeExpr(decl);
VarDecl* idxExprDecl = nullptr;
// Save our index expression so it can be used later.
if (!m_IdxExpr) {
Expand Down Expand Up @@ -384,7 +389,7 @@ void ErrorEstimationHandler::EmitFinalErrorStmts(
loopBody.push_back(deltaAssignExpr);
loopBody.push_back(finalAssignExpr);
Expr* conditionExpr = m_RMV->BuildOp(
BO_LT, m_IdxExpr, m_RMV->BuildArrayRefSizeExpr(LdiffExpr));
BO_LT, m_IdxExpr, size);
Expr* incExpr = m_RMV->BuildOp(UO_PostInc, m_IdxExpr);
Stmt* ArrayParamLoop = new (m_RMV->m_Context)
ForStmt(m_RMV->m_Context, nullptr, conditionExpr, nullptr, incExpr,
Expand Down Expand Up @@ -421,7 +426,7 @@ void ErrorEstimationHandler::EmitUnaryOpErrorStmts(StmtDiff var,
// It is nice to save the pop value.
// We do not know how many times the user will use dx,
// hence we should pop values beforehand to avoid unequal pushes
// and and pops.
// and pops.
Expr* popVal =
m_RMV->StoreAndRef(savedVar.getExpr_dx(), direction::reverse);
savedVar = {savedVar.getExpr(), popVal};
Expand Down Expand Up @@ -562,6 +567,57 @@ void ErrorEstimationHandler::ActAfterProcessingStmtInVisitCompoundStmt() {
EmitErrorEstimationStmts(direction::reverse);
}

void ErrorEstimationHandler::ActAfterProcessingArraySubscriptExpr(const Expr* revArrSub) {
if (const auto* ASE = dyn_cast<ArraySubscriptExpr>(revArrSub)) {
if (const auto* DRE = dyn_cast<DeclRefExpr>(ASE->getBase()->IgnoreImplicit())) {
const auto* VD = cast<VarDecl>(DRE->getDecl());
Expr* VDdiff = m_RMV->m_Variables[VD];
// We only need to track sizes for arrays and pointers.
if (!utils::isArrayOrPointerType(VDdiff->getType()))
return;
// Here, we're essentially constructing `var_size = max(var_size, idx);`.
// However, due to the fact that `max` is not a standard function,
// we achieve the same with `var_size = (var_size >= idx) ? var_size : idx;`
Expr* size = getSizeExpr(VD);
Expr* idx = m_RMV->Clone(ASE->getIdx());
Expr* compareSizeAndIdx = m_RMV->BuildOp(BO_GE, size, idx);
compareSizeAndIdx = utils::BuildParenExpr(m_RMV->m_Sema, compareSizeAndIdx);
size = m_RMV->Clone(size);
idx = m_RMV->Clone(idx);
Expr* extendedSize = m_RMV->m_Sema.ActOnConditionalOp(noLoc,
noLoc,
compareSizeAndIdx,
size, idx).get();
size = m_RMV->Clone(size);
Stmt* updateSize = m_RMV->BuildOp(BO_Assign, size, extendedSize);
m_RMV->addToCurrentBlock(updateSize, direction::reverse);
}
}
}

Expr* ErrorEstimationHandler::getSizeExpr(const VarDecl* VD) {
auto diffVar = m_RMV->m_Variables[VD];
// Use `.size()` for clad::array.
if (m_RMV->isCladArrayType(diffVar->getType()))
return m_RMV->BuildArrayRefSizeExpr(diffVar);

// For every array/pointer variable `arr`
// we create `arr_size` to track the size.
auto foundSize = m_ArrSizes.find(VD);
// If the size variable is already generated, just clone the decl ref.
if (foundSize!=m_ArrSizes.end()) {
return m_RMV->Clone(foundSize->second);
}
// If the size variable is not generated yet,
// generate it now.
QualType intTy = m_RMV->m_Context.getSizeType();
VarDecl* sizeVD = m_RMV->BuildGlobalVarDecl(intTy, VD->getNameAsString() + "_size", m_RMV->getZeroInit(intTy));
m_RMV->AddToGlobalBlock(m_RMV->BuildDeclStmt(sizeVD));
Expr* size = m_RMV->BuildDeclRef(sizeVD);
m_ArrSizes[VD] = size;
return size;
}

void ErrorEstimationHandler::
ActBeforeDifferentiatingSingleStmtBranchInVisitIfStmt() {
m_ShouldEmit.push(true);
Expand Down
7 changes: 7 additions & 0 deletions lib/Differentiator/MultiplexExternalRMVSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ void MultiplexExternalRMVSource::ActAfterParsingDiffArgs(
}
}

void MultiplexExternalRMVSource::ActAfterProcessingArraySubscriptExpr(
const clang::Expr* revArrSub){
for (auto source : m_Sources) {
source->ActAfterProcessingArraySubscriptExpr(revArrSub);
}
}

void MultiplexExternalRMVSource::ActBeforeCreatingDerivedFnParamTypes(
unsigned& numExtraParams) {
for (auto source : m_Sources) {
Expand Down
2 changes: 2 additions & 0 deletions lib/Differentiator/ReverseModeVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,8 @@ Expr* getArraySizeExpr(const ArrayType* AT, ASTContext& context,
// Add it to the body statements.
addToCurrentBlock(add_assign, direction::reverse);
}
if (m_ExternalSource)
m_ExternalSource->ActAfterProcessingArraySubscriptExpr(valueForRevSweep);
return StmtDiff(cloned, result, forwSweepDerivative, valueForRevSweep);
}

Expand Down
64 changes: 46 additions & 18 deletions test/ErrorEstimation/LoopsAndArrays.C
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ float func(float* p, int n) {
//CHECK-NEXT: int _d_i = 0;
//CHECK-NEXT: int i = 0;
//CHECK-NEXT: clad::tape<float> _t1 = {};
//CHECK-NEXT: unsigned long p_size = 0;
//CHECK-NEXT: clad::tape<float> _EERepl_sum1 = {};
//CHECK-NEXT: float sum = 0;
//CHECK-NEXT: _EERepl_sum0 = sum;
Expand All @@ -41,14 +42,15 @@ float func(float* p, int n) {
//CHECK-NEXT: sum = clad::pop(_t1);
//CHECK-NEXT: float _r_d0 = _d_sum;
//CHECK-NEXT: _d_p[i] += _r_d0;
//CHECK-NEXT: p_size = (p_size >= i) ? p_size : i;
//CHECK-NEXT: float _r0 = clad::pop(_EERepl_sum1);
//CHECK-NEXT: _delta_sum += std::abs(_r_d0 * _r0 * {{.+}});
//CHECK-NEXT: }
//CHECK-NEXT: }
//CHECK-NEXT: _delta_sum += std::abs(_d_sum * _EERepl_sum0 * {{.+}});
//CHECK-NEXT: clad::array<float> _delta_p(_d_p.size());
//CHECK-NEXT: clad::array<float> _delta_p(p_size);
//CHECK-NEXT: int i0 = 0;
//CHECK-NEXT: for (; i0 < _d_p.size(); i0++) {
//CHECK-NEXT: for (; i0 < p_size; i0++) {
//CHECK-NEXT: double _t2 = std::abs(_d_p[i0] * p[i0] * {{.+}});
//CHECK-NEXT: _delta_p[i0] += _t2;
//CHECK-NEXT: _final_error += _t2;
Expand Down Expand Up @@ -173,8 +175,8 @@ float func3(float x, float y) {
//CHECK-NEXT: arr[0] = _t0;
//CHECK-NEXT: double _r_d0 = _d_arr[0];
//CHECK-NEXT: _d_arr[0] -= _r_d0;
//CHECK-NEXT: * _d_x += _r_d0;
//CHECK-NEXT: * _d_y += _r_d0;
//CHECK-NEXT: *_d_x += _r_d0;
//CHECK-NEXT: *_d_y += _r_d0;
//CHECK-NEXT: _delta_arr[0] += std::abs(_r_d0 * _EERepl_arr0 * {{.+}});
//CHECK-NEXT: _final_error += _delta_arr[0];
//CHECK-NEXT: _d_arr[0];
Expand Down Expand Up @@ -202,12 +204,14 @@ float func4(float x[10], float y[10]) {
//CHECK-NEXT: unsigned long _t0;
//CHECK-NEXT: int _d_i = 0;
//CHECK-NEXT: int i = 0;
//CHECK-NEXT: unsigned long x_size = 0;
//CHECK-NEXT: clad::tape<float> _t1 = {};
//CHECK-NEXT: clad::array<float> _delta_x(_d_x.size());
//CHECK-NEXT: clad::array<float> _EERepl_x0(_d_x.size());
//CHECK-NEXT: for (int i0 = 0; i0 < _d_x.size(); i0++) {
//CHECK-NEXT: clad::array<float> _delta_x(x_size);
//CHECK-NEXT: clad::array<float> _EERepl_x0(x_size);
//CHECK-NEXT: for (int i0 = 0; i0 < x_size; i0++) {
//CHECK-NEXT: _EERepl_x0[i0] = x[i0];
//CHECK-NEXT: }
//CHECK-NEXT: unsigned long y_size = 0;
//CHECK-NEXT: clad::tape<float> _EERepl_x1 = {};
//CHECK-NEXT: clad::tape<float> _t2 = {};
//CHECK-NEXT: clad::tape<float> _EERepl_sum1 = {};
Expand All @@ -232,28 +236,31 @@ float func4(float x[10], float y[10]) {
//CHECK-NEXT: sum = clad::pop(_t2);
//CHECK-NEXT: float _r_d1 = _d_sum;
//CHECK-NEXT: _d_x[i] += _r_d1;
//CHECK-NEXT: x_size = (x_size >= i) ? x_size : i;
//CHECK-NEXT: float _r1 = clad::pop(_EERepl_sum1);
//CHECK-NEXT: _delta_sum += std::abs(_r_d1 * _r1 * {{.+}});
//CHECK-NEXT: }
//CHECK-NEXT: {
//CHECK-NEXT: x[i] = clad::pop(_t1);
//CHECK-NEXT: float _r_d0 = _d_x[i];
//CHECK-NEXT: _d_y[i] += _r_d0;
//CHECK-NEXT: y_size = (y_size >= i) ? y_size : i;
//CHECK-NEXT: float _r0 = clad::pop(_EERepl_x1);
//CHECK-NEXT: _delta_x[i] += std::abs(_r_d0 * _r0 * {{.+}});
//CHECK-NEXT: _final_error += _delta_x[i];
//CHECK-NEXT: x_size = (x_size >= i) ? x_size : i;
//CHECK-NEXT: }
//CHECK-NEXT: }
//CHECK-NEXT: _delta_sum += std::abs(_d_sum * _EERepl_sum0 * {{.+}});
//CHECK-NEXT: int i0 = 0;
//CHECK-NEXT: for (; i0 < _d_x.size(); i0++) {
//CHECK-NEXT: for (; i0 < x_size; i0++) {
//CHECK-NEXT: double _t3 = std::abs(_d_x[i0] * _EERepl_x0[i0] * {{.+}});
//CHECK-NEXT: _delta_x[i0] += _t3;
//CHECK-NEXT: _final_error += _t3;
//CHECK-NEXT: }
//CHECK-NEXT: clad::array<float> _delta_y(_d_y.size());
//CHECK-NEXT: clad::array<float> _delta_y(y_size);
//CHECK-NEXT: i0 = 0;
//CHECK-NEXT: for (; i0 < _d_y.size(); i0++) {
//CHECK-NEXT: for (; i0 < y_size; i0++) {
//CHECK-NEXT: double _t4 = std::abs(_d_y[i0] * y[i0] * {{.+}});
//CHECK-NEXT: _delta_y[i0] += _t4;
//CHECK-NEXT: _final_error += _t4;
Expand All @@ -270,12 +277,15 @@ double func5(double* x, double* y, double* output) {
}

//CHECK: void func5_grad(double *x, double *y, double *output, double *_d_x, double *_d_y, double *_d_output, double &_final_error) {
//CHECK-NEXT: unsigned long output_size = 0;
//CHECK-NEXT: double _t0;
//CHECK-NEXT: clad::array<double> _delta_output(_d_output.size());
//CHECK-NEXT: clad::array<double> _EERepl_output0(_d_output.size());
//CHECK-NEXT: for (int i = 0; i < _d_output.size(); i++) {
//CHECK-NEXT: clad::array<double> _delta_output(output_size);
//CHECK-NEXT: clad::array<double> _EERepl_output0(output_size);
//CHECK-NEXT: for (int i = 0; i < output_size; i++) {
//CHECK-NEXT: _EERepl_output0[i] = output[i];
//CHECK-NEXT: }
//CHECK-NEXT: unsigned long x_size = 0;
//CHECK-NEXT: unsigned long y_size = 0;
//CHECK-NEXT: double _EERepl_output1;
//CHECK-NEXT: double _t1;
//CHECK-NEXT: double _EERepl_output2;
Expand All @@ -296,58 +306,76 @@ double func5(double* x, double* y, double* output) {
//CHECK-NEXT: _label0:
//CHECK-NEXT: {
//CHECK-NEXT: _d_output[0] += 1;
//CHECK-NEXT: output_size = (output_size >= 0) ? output_size : 0;
//CHECK-NEXT: _d_output[1] += 1;
//CHECK-NEXT: output_size = (output_size >= 1) ? output_size : 1;
//CHECK-NEXT: _d_output[2] += 1;
//CHECK-NEXT: output_size = (output_size >= 2) ? output_size : 2;
//CHECK-NEXT: }
//CHECK-NEXT: {
//CHECK-NEXT: output[2] = _t2;
//CHECK-NEXT: double _r_d2 = _d_output[2];
//CHECK-NEXT: _d_output[2] -= _r_d2;
//CHECK-NEXT: _d_x[0] += _r_d2 * y[1];
//CHECK-NEXT: x_size = (x_size >= 0) ? x_size : 0;
//CHECK-NEXT: _d_y[1] += x[0] * _r_d2;
//CHECK-NEXT: y_size = (y_size >= 1) ? y_size : 1;
//CHECK-NEXT: _d_y[0] += -_r_d2 * x[1];
//CHECK-NEXT: y_size = (y_size >= 0) ? y_size : 0;
//CHECK-NEXT: _d_x[1] += y[0] * -_r_d2;
//CHECK-NEXT: x_size = (x_size >= 1) ? x_size : 1;
//CHECK-NEXT: _delta_output[2] += std::abs(_r_d2 * _EERepl_output3 * {{.+}});
//CHECK-NEXT: _final_error += _delta_output[2];
//CHECK-NEXT: output_size = (output_size >= 2) ? output_size : 2;
//CHECK-NEXT: }
//CHECK-NEXT: {
//CHECK-NEXT: output[1] = _t1;
//CHECK-NEXT: double _r_d1 = _d_output[1];
//CHECK-NEXT: _d_output[1] -= _r_d1;
//CHECK-NEXT: _d_x[2] += _r_d1 * y[0];
//CHECK-NEXT: x_size = (x_size >= 2) ? x_size : 2;
//CHECK-NEXT: _d_y[0] += x[2] * _r_d1;
//CHECK-NEXT: y_size = (y_size >= 0) ? y_size : 0;
//CHECK-NEXT: _d_x[0] += -_r_d1 * y[2];
//CHECK-NEXT: x_size = (x_size >= 0) ? x_size : 0;
//CHECK-NEXT: _d_y[2] += x[0] * -_r_d1;
//CHECK-NEXT: y_size = (y_size >= 2) ? y_size : 2;
//CHECK-NEXT: _delta_output[1] += std::abs(_r_d1 * _EERepl_output2 * {{.+}});
//CHECK-NEXT: _final_error += _delta_output[1];
//CHECK-NEXT: output_size = (output_size >= 1) ? output_size : 1;
//CHECK-NEXT: }
//CHECK-NEXT: {
//CHECK-NEXT: output[0] = _t0;
//CHECK-NEXT: double _r_d0 = _d_output[0];
//CHECK-NEXT: _d_output[0] -= _r_d0;
//CHECK-NEXT: _d_x[1] += _r_d0 * y[2];
//CHECK-NEXT: x_size = (x_size >= 1) ? x_size : 1;
//CHECK-NEXT: _d_y[2] += x[1] * _r_d0;
//CHECK-NEXT: y_size = (y_size >= 2) ? y_size : 2;
//CHECK-NEXT: _d_x[2] += -_r_d0 * y[1];
//CHECK-NEXT: x_size = (x_size >= 2) ? x_size : 2;
//CHECK-NEXT: _d_y[1] += x[2] * -_r_d0;
//CHECK-NEXT: y_size = (y_size >= 1) ? y_size : 1;
//CHECK-NEXT: _delta_output[0] += std::abs(_r_d0 * _EERepl_output1 * {{.+}});
//CHECK-NEXT: _final_error += _delta_output[0];
//CHECK-NEXT: output_size = (output_size >= 0) ? output_size : 0;
//CHECK-NEXT: }
//CHECK-NEXT: clad::array<double> _delta_x(_d_x.size());
//CHECK-NEXT: clad::array<double> _delta_x(x_size);
//CHECK-NEXT: int i = 0;
//CHECK-NEXT: for (; i < _d_x.size(); i++) {
//CHECK-NEXT: for (; i < x_size; i++) {
//CHECK-NEXT: double _t3 = std::abs(_d_x[i] * x[i] * {{.+}});
//CHECK-NEXT: _delta_x[i] += _t3;
//CHECK-NEXT: _final_error += _t3;
//CHECK-NEXT: }
//CHECK-NEXT: clad::array<double> _delta_y(_d_y.size());
//CHECK-NEXT: clad::array<double> _delta_y(y_size);
//CHECK-NEXT: i = 0;
//CHECK-NEXT: for (; i < _d_y.size(); i++) {
//CHECK-NEXT: for (; i < y_size; i++) {
//CHECK-NEXT: double _t4 = std::abs(_d_y[i] * y[i] * {{.+}});
//CHECK-NEXT: _delta_y[i] += _t4;
//CHECK-NEXT: _final_error += _t4;
//CHECK-NEXT: }
//CHECK-NEXT: i = 0;
//CHECK-NEXT: for (; i < _d_output.size(); i++) {
//CHECK-NEXT: for (; i < output_size; i++) {
//CHECK-NEXT: double _t5 = std::abs(_d_output[i] * _EERepl_output0[i] * {{.+}});
//CHECK-NEXT: _delta_output[i] += _t5;
//CHECK-NEXT: _final_error += _t5;
Expand Down
Loading

0 comments on commit d339638

Please sign in to comment.