CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
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 
18 namespace CppAD {
19 namespace cg {
20 
21 /***************************************************************************
22  * Methods related with loop insertion into the operation graph
23  **************************************************************************/
24 
25 template<class Base>
26 std::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 
133 template<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
STL namespace.
virtual std::vector< CGBase > prepareForward0WithLoops(CodeHandler< Base > &handler, const std::vector< CGBase > &x)