CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
range.hpp
1#ifndef CPPAD_CG_RANGE_INCLUDED
2#define CPPAD_CG_RANGE_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
27inline void combineNonOverlapingIterationRanges(std::vector<size_t>& iterRegions,
28 const std::vector<size_t>& newIterRegions) {
29 if (iterRegions.empty()) {
30 iterRegions = newIterRegions;
31 return;
32 } else if (newIterRegions.empty()) {
33 return;
34 }
35
39 std::vector<size_t>::iterator itPos = iterRegions.begin();
40 std::vector<size_t>::const_iterator itNew;
41 for (itNew = newIterRegions.begin(); itNew != newIterRegions.end(); ++itNew) {
42 size_t pos = *itNew;
43 itPos = std::lower_bound(itPos, iterRegions.end(), pos);
44 if (itPos == iterRegions.end()) {
45 iterRegions.insert(iterRegions.end(), itNew, newIterRegions.end());
46 break; // done
47 } else if (*itPos == pos) {
48 // same value -> must merge
49 itPos = iterRegions.erase(itPos);
50 } else {
51 itPos = iterRegions.insert(itPos, pos);
52 }
53 }
54 CPPADCG_ASSERT_UNKNOWN(iterRegions.size() % 2 == 0);
55}
56
63inline void combineOverlapingIterationRanges(std::vector<size_t>& iterRegions,
64 const std::vector<size_t>& newIterRegions) {
65 if (iterRegions.empty()) {
66 iterRegions = newIterRegions;
67 return;
68 } else if (newIterRegions.empty()) {
69 return;
70 }
71
72 std::vector<std::pair<size_t, size_t> > sorted;
73 for (size_t i = 0; i < iterRegions.size(); i += 2) {
74 sorted.insert(sorted.end(), std::make_pair(iterRegions[i], iterRegions[i + 1]));
75 }
76
77 std::vector<std::pair<size_t, size_t> >::iterator begin = sorted.begin();
78 for (size_t i = 0; i < newIterRegions.size(); i += 2) {
79 std::pair<size_t, size_t> p(newIterRegions[i], newIterRegions[i + 1]);
80 begin = std::lower_bound(begin, sorted.end(), p);
81 begin = sorted.insert(begin, p);
82 begin++;
83 }
84
85 std::vector<std::pair<size_t, size_t> > result;
86 result.reserve(sorted.size());
87 result.push_back(sorted[0]);
88 for (size_t i = 1; i < sorted.size(); i++) {
89 const std::pair<size_t, size_t>& curr = sorted[i]; // interval to be added
90 std::pair<size_t, size_t>& top = result.back();
91
92 if (top.second == (std::numeric_limits<size_t>::max)()) // avoid overflow
93 break; // done, nothing can be added
94
95 // if current interval is not overlapping with stack top,
96 // push it to the stack
97 if (top.second + 1 < curr.first) {
98 result.push_back(curr);
99 } else if (top.second < curr.second) {
100 // Otherwise update the ending time of top if ending of current
101 // interval is more
102 top.second = curr.second;
103 }
104 }
105
106 iterRegions.resize(result.size() * 2);
107 for (size_t i = 0; i < result.size(); i++) {
108 iterRegions[2 * i] = result[i].first;
109 iterRegions[2 * i + 1] = result[i].second;
110 }
111}
112
122inline std::vector<size_t> invertIterationRanges(const std::vector<size_t>& iterRegions) {
123 std::vector<size_t> inverted;
124 if (iterRegions.empty()) {
125 inverted.resize(2);
126 inverted[1] = (std::numeric_limits<size_t>::max)();
127 return inverted;
128 }
129
130 CPPADCG_ASSERT_UNKNOWN(iterRegions.size() % 2 == 0);
131 inverted.reserve(iterRegions.size() + 4);
132
133 if (iterRegions[0] != 0) {
134 inverted.push_back(0);
135 inverted.push_back(iterRegions[0] - 1);
136 }
137
138 for (size_t i = 2; i < iterRegions.size(); i += 2) {
139 CPPADCG_ASSERT_UNKNOWN(iterRegions[i - 1] < iterRegions[i]);
140 inverted.push_back(iterRegions[i - 1] + 1);
141 inverted.push_back(iterRegions[i] - 1);
142 }
143
144 if (iterRegions.back() != (std::numeric_limits<size_t>::max)()) {
145 inverted.push_back(iterRegions.back() + 1);
146 inverted.push_back((std::numeric_limits<size_t>::max)());
147 }
148
149 return inverted;
150}
151
160template<class Base>
161inline std::vector<size_t> ifBranchIterationRanges(const OperationNode<Base>* bScope,
162 IndexOperationNode<Base>*& iterationIndexOp) {
163 CGOpCode bOp = bScope->getOperationType();
164
165 if (bOp == CGOpCode::StartIf || bOp == CGOpCode::ElseIf) {
166 OperationNode<Base>* cond = bScope->getArguments()[bOp == CGOpCode::StartIf ? 0 : 1].getOperation();
167 CPPADCG_ASSERT_UNKNOWN(cond->getOperationType() == CGOpCode::IndexCondExpr);
168 CPPADCG_ASSERT_UNKNOWN(cond->getArguments().size() == 1);
169 CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation() != nullptr);
170 CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation()->getOperationType() == CGOpCode::Index);
171 iterationIndexOp = static_cast<IndexOperationNode<Base>*> (cond->getArguments()[0].getOperation());
172 return cond->getInfo();
173
174 } else {
175 // else
176 CPPADCG_ASSERT_UNKNOWN(bOp == CGOpCode::Else);
177
178 std::vector<size_t> nonIterationRegions;
179 OperationNode<Base>* ifBranch = bScope->getArguments()[0].getOperation();
180 do {
181 CGOpCode bbOp = ifBranch->getOperationType();
182 OperationNode<Base>* cond = ifBranch->getArguments()[bbOp == CGOpCode::StartIf ? 0 : 1].getOperation();
183 CPPADCG_ASSERT_UNKNOWN(cond->getOperationType() == CGOpCode::IndexCondExpr);
184 CPPADCG_ASSERT_UNKNOWN(cond->getArguments().size() == 1);
185 CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation() != nullptr);
186 CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation()->getOperationType() == CGOpCode::Index);
187 IndexOperationNode<Base>* indexOp = static_cast<IndexOperationNode<Base>*> (cond->getArguments()[0].getOperation());
188 CPPADCG_ASSERT_UNKNOWN(iterationIndexOp == nullptr || iterationIndexOp == indexOp);
189 iterationIndexOp = indexOp;
190
191 combineOverlapingIterationRanges(nonIterationRegions, cond->getInfo());
192
193 ifBranch = ifBranch->getArguments()[0].getOperation();
194 } while (ifBranch->getOperationType() == CGOpCode::ElseIf);
195
196 CPPADCG_ASSERT_UNKNOWN(iterationIndexOp != nullptr);
197
198 // invert
199 return invertIterationRanges(nonIterationRegions);
200 }
201
202}
203
204} // END cg namespace
205} // END CppAD namespace
206
207#endif