CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
model_c_source_gen_loops_for0.hpp
1#ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_FOR0_INCLUDED
2#define CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_FOR0_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2013 Ciengis
6 *
7 * CppADCodeGen is distributed under multiple licenses:
8 *
9 * - Eclipse Public License Version 1.0 (EPL1), and
10 * - GNU General Public License Version 3 (GPL3).
11 *
12 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14 * ----------------------------------------------------------------------------
15 * Author: Joao Leal
16 */
17
18namespace CppAD {
19namespace cg {
20
21/***************************************************************************
22 * Methods related with loop insertion into the operation graph
23 **************************************************************************/
24
25template<class Base>
26std::vector<CG<Base> > prepareGraphForward0WithLoops(CodeHandler<Base>& handler,
27 size_t m,
28 const std::vector<CG<Base>>& x,
29 LoopFreeModel<Base>* funNoLoops,
30 const std::set<LoopModel<Base>*>& loopTapes) {
31 using namespace std;
32 using namespace loops;
33
34 using CGBase = CG<Base>;
35
36 std::vector<CGBase> y(m);
37
38 // temporaries
39 std::vector<CGBase> tmps;
40
44 if (funNoLoops != nullptr) {
45 const std::vector<size_t>& origEq = funNoLoops->getOrigDependentIndexes();
46
47 std::vector<CGBase> depNL = funNoLoops->getTape().Forward(0, x);
48
49 // original equations
50 for (size_t e = 0; e < origEq.size(); e++) {
51 y[origEq[e]] = depNL[e];
52 }
53
54 tmps.resize(depNL.size() - origEq.size());
55 for (size_t i = origEq.size(); i < depNL.size(); i++)
56 tmps[i - origEq.size()] = depNL[i];
57 }
58
62 OperationNode<Base>* iterationIndexDcl = handler.makeIndexDclrNode(LoopModel<Base>::ITERATION_INDEX_NAME);
63
64 for (LoopModel<Base>* itl : loopTapes) {
65 LoopModel<Base>& lModel = *itl;
66 size_t nIterations = lModel.getIterationCount();
67 const std::vector<std::vector<LoopPosition> >& dependents = lModel.getDependentIndexes();
68
72 LoopStartOperationNode<Base>* loopStart = handler.makeLoopStartNode(*iterationIndexDcl, nIterations);
73
74 IndexOperationNode<Base>* iterationIndexOp = handler.makeIndexNode(*loopStart);
75 std::set<IndexOperationNode<Base>*> indexesOps;
76 indexesOps.insert(iterationIndexOp);
77
78 std::vector<IfElseInfo<Base> > ifElses;
79
83 std::vector<CGBase> indexedIndeps = createIndexedIndependents(handler, lModel, *iterationIndexOp);
84 std::vector<CGBase> xl = createLoopIndependentVector(handler, lModel, indexedIndeps, x, tmps);
85 if (xl.size() == 0) {
86 xl.resize(1); // does not depend on any variable but CppAD requires at least one
87 xl[0] = Base(0);
88 }
89 std::vector<CGBase> yl = lModel.getTape().Forward(0, xl);
90
94 size_t assignOrAdd = 0;
95
96 const std::vector<IndexPattern*>& depPatterns = lModel.getDependentIndexPatterns();
97 std::vector<std::pair<CGBase, IndexPattern*> > indexedLoopResults(yl.size());
98 for (size_t i = 0; i < yl.size(); i++) {
99 std::map<size_t, size_t> locationsIter2Pos;
100
101 for (size_t it = 0; it < nIterations; it++) {
102 if (dependents[i][it].original < m) {
103 locationsIter2Pos[it] = dependents[i][it].original;
104 }
105 }
106
107 indexedLoopResults[i] = createLoopResult(handler, locationsIter2Pos, nIterations,
108 yl[i], depPatterns[i], assignOrAdd,
109 *iterationIndexOp, ifElses);
110 }
111
112 LoopEndOperationNode<Base>* loopEnd = createLoopEnd(handler, *loopStart, indexedLoopResults, indexesOps, assignOrAdd);
113
114 for (size_t i = 0; i < dependents.size(); i++) {
115 for (size_t it = 0; it < nIterations; it++) {
116 // an additional alias variable is required so that each dependent variable can have its own ID
117 size_t e = dependents[i][it].original;
118 if (e < m) { // some equations are not present in all iteration
119 y[e] = handler.createCG(*handler.makeNode(CGOpCode::DependentRefRhs,{e}, {*loopEnd}));
120 }
121 }
122 }
123
127 moveNonIndexedOutsideLoop(handler, *loopStart, *loopEnd);
128 }
129
130 return y;
131}
132
133template<class Base>
135 const std::vector<CGBase>& x) {
136 return prepareGraphForward0WithLoops(handler, _fun.Range(), x, _funNoLoops, _loopTapes);
137}
138
139} // END cg namespace
140} // END CppAD namespace
141
142#endif
virtual std::vector< CGBase > prepareForward0WithLoops(CodeHandler< Base > &handler, const std::vector< CGBase > &x)