CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
sectioned_index_pattern.hpp
1#ifndef CPPAD_CG_SECTIONED_INDEX_PATTERN_INCLUDED
2#define CPPAD_CG_SECTIONED_INDEX_PATTERN_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2013 Ciengis
6 * Copyright (C) 2018 Joao Leal
7 *
8 * CppADCodeGen is distributed under multiple licenses:
9 *
10 * - Eclipse Public License Version 1.0 (EPL1), and
11 * - GNU General Public License Version 3 (GPL3).
12 *
13 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15 * ----------------------------------------------------------------------------
16 * Author: Joao Leal
17 */
18
19namespace CppAD {
20namespace cg {
21
26protected:
30 std::map<size_t, IndexPattern*> sections_;
31public:
32
33 inline SectionedIndexPattern(const std::map<size_t, IndexPattern*>& sections) :
34 sections_(sections) {
35 }
36
37 inline const std::map<size_t, IndexPattern*>& getLinearSections() const {
38 return sections_;
39 }
40
41 inline IndexPatternType getType() const override {
42 return IndexPatternType::Sectioned;
43 }
44
45 inline void getSubIndexes(std::set<IndexPattern*>& indexes) const override {
46 for (const auto& it : sections_) {
47 indexes.insert(it.second);
48 it.second->getSubIndexes(indexes);
49 }
50 }
51
52 inline virtual ~SectionedIndexPattern() {
53 deleteIndexPatterns(sections_);
54 }
55
56 /***********************************************************************
57 * static methods
58 **********************************************************************/
59
60 template<class VectorSizeT>
61 static inline std::map<size_t, IndexPattern*> detectLinearSections(const VectorSizeT& indexes,
62 size_t maxCount = 0) {
63 CPPADCG_ASSERT_UNKNOWN(indexes.size() > 0);
64
65 long dx = 1;
66 long xOffset = 0;
67
68 LinearIndexPattern* prevPattern = nullptr;
69 size_t prevXStart = 0;
70
71 SmartMapValuePointer<size_t, IndexPattern> linearSections;
72 size_t xStart = 0;
73 while (xStart != indexes.size()) {
74 long dy, b;
75 size_t lastLinear;
76 if (xStart + 1 == indexes.size()) {
77 dy = 0;
78 b = indexes[xStart];
79 lastLinear = xStart + 1;
80 } else {
81 dy = long(indexes[xStart + 1]) - indexes[xStart];
82 b = long(indexes[xStart]) - dy * xStart;
83 lastLinear = indexes.size();
84 for (size_t x = xStart + 2; x < indexes.size(); x++) {
85 if (indexes[x] != dy * x + b) {
86 lastLinear = x;
87 break;
88 }
89 }
90 }
91
92 LinearIndexPattern* p = new LinearIndexPattern(xOffset, dy, dx, b);
93 if (dy == 0 && prevPattern != nullptr) { // constant
94 // can we take the last element out of the previous section?
95 while (xStart > 0 && prevPattern->evaluate(xStart - 1) == b) {
96 // yes
97 xStart--;
98 if (prevXStart + 1 == xStart) {
99 // it has only one element -> make it a constant section
100 size_t bb = prevPattern->evaluate(prevXStart);
101 prevPattern->setLinearSlopeDy(0);
102 prevPattern->setLinearConstantTerm(bb);
103 }
104 }
105 }
106 linearSections[xStart] = p;
107
108 prevXStart = xStart;
109 prevPattern = p;
110 xStart = lastLinear;
111
112 if (linearSections.size() == maxCount && xStart != indexes.size()) {
113 // over the limit -> stop
114 return std::map<size_t, IndexPattern*>(); // empty
115 }
116 }
117
118 return linearSections.release();
119 }
120
121 static inline std::map<size_t, IndexPattern*> detectLinearSections(const std::map<size_t, size_t>& x2y,
122 size_t maxCount = 0) {
123 using c_iter = std::map<size_t, size_t>::const_iterator;
124
125 SmartMapValuePointer<size_t, IndexPattern> linearSections;
126
127 LinearIndexPattern* prevPattern = nullptr;
128 c_iter prevStart = x2y.begin();
129
130 c_iter pStart = x2y.begin();
131 while (pStart != x2y.end()) {
132 c_iter pNextSection = x2y.end();
133 c_iter p1 = pStart;
134 ++p1;
135
136 long xOffset, dy, dx, b;
137 if (p1 == x2y.end()) {
138 xOffset = 0;
139 dy = 0;
140 dx = 1;
141 b = pStart->second;
142 pNextSection = p1;
143
144 } else {
145 long x0 = pStart->first;
146 long y0 = pStart->second;
147
148 dy = long(p1->second) - y0;
149 if (dy != 0) {
150 dx = long(p1->first) - x0;
151 xOffset = x0 % dx;
152 // y = ((x - offset) / dx) * dy + b
153 b = y0 - ((x0 - xOffset) / dx) * dy;
154 } else {
155 dx = 1;
156 xOffset = 0;
157 b = y0;
158 }
159
160 for (std::map<size_t, size_t>::const_iterator itp = p1; itp != x2y.end(); ++itp) {
161 size_t x = itp->first;
162 size_t y = itp->second;
163
164 if (y != ((x - xOffset) / dx) * dy + b) {
165 pNextSection = itp;
166 break;
167 }
168 }
169 }
170
171 LinearIndexPattern* p = new LinearIndexPattern(xOffset, dy, dx, b);
172 size_t xStart = pStart->first;
173 if (dy == 0 && prevPattern != nullptr) { // constant
174 // can we take the last element from the previous section?
175
176 while (pStart != x2y.begin()) {
177 c_iter prevBack = pStart;
178 --prevBack; // the values at the end of the previous section
179 if (prevPattern->evaluate(prevBack->first) != b)
180 break; // no
181
182 // yes
183 --pStart;
184 xStart = pStart->first;
185 c_iter prevStartN = prevStart;
186 prevStartN++;
187 if (prevStartN == pStart) {
188 // it has only one element -> make it a constant section
189 size_t bb = prevPattern->evaluate(prevStart->first);
190 prevPattern->setLinearSlopeDy(0);
191 prevPattern->setLinearConstantTerm(bb);
192 }
193 }
194 }
195 linearSections[xStart] = p;
196
197 prevStart = pStart;
198 prevPattern = p;
199 pStart = pNextSection;
200
201 if (linearSections.size() == maxCount && pStart != x2y.end()) {
202 // over the limit -> stop
203 return std::map<size_t, IndexPattern*>(); // empty
204 }
205 }
206
207 return linearSections.release();
208 }
209
210private:
211
212 static inline void deleteIndexPatterns(std::map<size_t, IndexPattern*>& sections) {
213 for (const auto& it : sections) {
214 delete it.second;
215 }
216 sections.clear();
217 }
218};
219
220} // END cg namespace
221} // END CppAD namespace
222
223#endif
std::map< size_t, IndexPattern * > sections_