CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
plane_2d_index_pattern.hpp
1#ifndef CPPAD_CG_PLANE_2D_INDEX_PATTERN_INCLUDED
2#define CPPAD_CG_PLANE_2D_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
29protected:
34 IndexPattern* pattern2_;
35public:
36
37 inline Plane2DIndexPattern(IndexPattern* pattern1,
38 IndexPattern* pattern2) :
39 pattern1_(pattern1),
40 pattern2_(pattern2) {
41 CPPADCG_ASSERT_UNKNOWN(pattern1_ != nullptr || pattern2_ != nullptr);
42 }
43
44 Plane2DIndexPattern(const Plane2DIndexPattern& orig) = delete;
45
46 inline const IndexPattern* getPattern1() const {
47 return pattern1_;
48 }
49
50 inline const IndexPattern* getPattern2() const {
51 return pattern2_;
52 }
53
54 inline IndexPatternType getType() const override {
55 return IndexPatternType::Plane2D;
56 }
57
58 inline void getSubIndexes(std::set<IndexPattern*>& indexes) const override {
59 if (pattern1_ != nullptr) {
60 indexes.insert(pattern1_);
61 pattern1_->getSubIndexes(indexes);
62 }
63 if (pattern2_ != nullptr) {
64 indexes.insert(pattern2_);
65 pattern2_->getSubIndexes(indexes);
66 }
67 }
68
69 inline virtual ~Plane2DIndexPattern() {
70 delete pattern1_;
71 delete pattern2_;
72 }
73
74 /***********************************************************************
75 * static methods
76 **********************************************************************/
77
78 static inline Plane2DIndexPattern* detectPlane2D(const std::map<size_t, std::map<size_t, size_t> >& x2y2z) {
84 if (x2y2z.size() == 1) {
85 // only one x -> fit z to y
86 const std::map<size_t, size_t>& y2z = x2y2z.begin()->second;
87 return new Plane2DIndexPattern(nullptr, IndexPattern::detect(y2z));
88 }
89
90 // perhaps there is always only one y
91 size_t y = x2y2z.begin()->second.begin()->first;
92 std::map<size_t, size_t> x2z;
93 std::map<size_t, std::map<size_t, size_t> >::const_iterator itx2y2z;
94 for (itx2y2z = x2y2z.begin(); itx2y2z != x2y2z.end(); ++itx2y2z) {
95 size_t x = itx2y2z->first;
96 const std::map<size_t, size_t>& y2z = itx2y2z->second;
97
98 if (y2z.size() != 1 ||
99 y != y2z.begin()->first) {
100 x2z.clear(); // not always the same y
101 break;
102 }
103
104 size_t z = y2z.begin()->second;
105 x2z[x] = z;
106 }
107
108 if (!x2z.empty()) {
109 return new Plane2DIndexPattern(IndexPattern::detect(x2z), nullptr);
110 }
111
116 std::map<size_t, size_t> x2zStart;
117 std::map<size_t, size_t> y2zOffset;
118
119 for (itx2y2z = x2y2z.begin(); itx2y2z != x2y2z.end(); ++itx2y2z) {
120 size_t x = itx2y2z->first;
121 const std::map<size_t, size_t>& y2z = itx2y2z->second;
122
123 size_t zFirst = y2z.begin()->second;
124 x2zStart[x] = zFirst;
125
126 std::map<size_t, size_t>::const_iterator ity2z;
127
128 for (ity2z = y2z.begin(); ity2z != y2z.end(); ++ity2z) {
129 size_t y = ity2z->first;
130 size_t offset = ity2z->second - zFirst;
131 std::map<size_t, size_t>::const_iterator itY2zOffset = y2zOffset.find(y);
132 if (itY2zOffset == y2zOffset.end()) {
133 y2zOffset[y] = offset;
134 } else if (itY2zOffset->second != offset) {
135 return nullptr; // does not fit the pattern
136 }
137 }
138 }
139
143 std::unique_ptr<IndexPattern> fx;
144
145 std::map<size_t, IndexPattern*> startSections = SectionedIndexPattern::detectLinearSections(x2zStart, 2);
146 if (startSections.empty()) {
147 return nullptr; // does not fit the pattern
148 }
149
150 // detected a pattern for the first z based on x
151 if (startSections.size() == 1) {
152 fx = std::unique_ptr<IndexPattern> (startSections.begin()->second);
153 } else {
154 fx = std::unique_ptr<IndexPattern> (new SectionedIndexPattern(startSections));
155 }
156
161 std::map<size_t, IndexPattern*> sections = SectionedIndexPattern::detectLinearSections(y2zOffset, 2);
162 if (sections.empty()) {
163 return nullptr; // does not fit the pattern
164 }
165
166 // detected a pattern for the z offset based on y
167 std::unique_ptr<IndexPattern> fy;
168 if (sections.size() == 1) {
169 fy = std::unique_ptr<IndexPattern> (sections.begin()->second);
170 } else {
171 fy = std::unique_ptr<IndexPattern> (new SectionedIndexPattern(sections));
172 }
173
174 // simplify when both patterns are constant
175 if (fx->getType() == IndexPatternType::Linear && fy->getType() == IndexPatternType::Linear) {
176 LinearIndexPattern* ipx = static_cast<LinearIndexPattern*> (fx.get());
177 LinearIndexPattern* ipy = static_cast<LinearIndexPattern*> (fy.get());
178
179 if (ipx->getLinearSlopeDy() == 0 && ipy->getLinearSlopeDy() == 0) {
183 ipx->setLinearConstantTerm(ipx->getLinearConstantTerm() + ipy->getLinearConstantTerm());
184 fy.reset();
185 }
186 }
187
188 return new Plane2DIndexPattern(fx.release(), fy.release());
189 }
190
191};
192
193} // END cg namespace
194} // END CppAD namespace
195
196#endif
static IndexPattern * detect(const VectorSizeT &x2y)
static Plane2DIndexPattern * detectPlane2D(const std::map< size_t, std::map< size_t, size_t > > &x2y2z)