CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
language_mathml_index_patterns.hpp
1#ifndef CPPAD_CG_LANGUAGE_MATHML_INDEX_PATTERNS_INCLUDED
2#define CPPAD_CG_LANGUAGE_MATHML_INDEX_PATTERNS_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2015 Ciengis
6 * Copyright (C) 2019 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
22template<class Base>
23inline void LanguageMathML<Base>::generateNames4RandomIndexPatterns(const std::set<RandomIndexPattern*>& randomPatterns) {
24 std::ostringstream os;
25
26 std::set<std::string> usedNames;
27
28 // save existing names so that they are not to overridden
29 // (independent variable names might have already used them)
30 for (RandomIndexPattern* ip : randomPatterns) {
31 if (!ip->getName().empty()) {
32 usedNames.insert(ip->getName());
33 }
34 }
35
36 // create new names for the index pattern arrays without a name
37 size_t c = 0;
38 for (RandomIndexPattern* ip : randomPatterns) {
39 if (ip->getName().empty()) {
40 // new name required
41 std::string name;
42 do {
43 os << _C_STATIC_INDEX_ARRAY << c;
44 name = os.str();
45 os.str("");
46 c++;
47 } while (usedNames.find(name) != usedNames.end());
48
49 ip->setName("<mi>" + name + "</mi>");
50 }
51 }
52
53}
54
55template<class Base>
57 const std::string& indentation,
58 const std::set<RandomIndexPattern*>& randomPatterns) {
59 for (RandomIndexPattern* ip : randomPatterns) {
60 if (ip->getType() == IndexPatternType::Random1D) {
64 auto* ip1 = static_cast<Random1DIndexPattern*> (ip);
65 const std::map<size_t, size_t>& x2y = ip1->getValues();
66
67 std::vector<size_t> y(x2y.rbegin()->first + 1);
68 for (const auto& p : x2y)
69 y[p.first] = p.second;
70
71 os << indentation;
72 printStaticIndexArray(os, ip->getName(), y);
73 } else {
74 CPPADCG_ASSERT_UNKNOWN(ip->getType() == IndexPatternType::Random2D);
78 auto* ip2 = static_cast<Random2DIndexPattern*> (ip);
79 os << indentation;
80 printStaticIndexMatrix(os, ip->getName(), ip2->getValues());
81 }
82 }
83}
84
85template<class Base>
86void LanguageMathML<Base>::printStaticIndexArray(std::ostringstream& os,
87 const std::string& name,
88 const std::vector<size_t>& values) {
89 os << name << " <mo>=</mo> <mfenced open='[' close=']' separators=','>";
90 for (size_t i = 0; i < values.size(); i++) {
91 os << "<mn>" << values[i] << "</mn>";
92 }
93 os << "</mfenced>" << _endEq << " <!-- size: " << values.size() << " -->" << _endline;
94}
95
96template<class Base>
98 const std::string& name,
99 const std::map<size_t, std::map<size_t, size_t> >& values) {
103 size_t m = 0;
104 size_t n = 0;
105
106 std::map<size_t, std::map<size_t, size_t> >::const_iterator it;
107 std::map<size_t, size_t>::const_iterator ity2z;
108
109 if (!values.empty()) {
110 m = values.rbegin()->first + 1;
111
112 for (it = values.begin(); it != values.end(); ++it) {
113 if (!it->second.empty())
114 n = std::max<size_t>(n, it->second.rbegin()->first + 1);
115 }
116 }
117
118 os << name << "<mo>=</mo><mtable>";
119 size_t x = 0;
120 for (it = values.begin(); it != values.end(); ++it) {
121 if (it->first != x) {
122 while (it->first != x) {
123 os << "<mtr><mtd/></mtr>";
124 x++;
125 }
126 }
127
128 os << "<mtr>";
129 size_t y = 0;
130 for (ity2z = it->second.begin(); ity2z != it->second.end(); ++ity2z) {
131 if (ity2z->first != y) {
132 while (ity2z->first != y) {
133 os << "<mtd><mn>0</mn></mtd>";
134 y++;
135 }
136 }
137
138 os << "<mtd><mn>" << ity2z->second << "</mn></mtd>";
139
140
141 y++;
142 }
143 os << "</mtr>";
144
145 x++;
146 }
147 os << "</mtable>" << _endEq << "<!-- size: " << m << " x " << n << " -->" << _endline;
148}
149
150template<class Base>
151inline void LanguageMathML<Base>::indexPattern2String(std::ostream& os,
152 const IndexPattern& ip,
153 const OperationNode<Base>& index) {
154 indexPattern2String(os, ip,{&index});
155}
156
157template<class Base>
158inline void LanguageMathML<Base>::indexPattern2String(std::ostream& os,
159 const IndexPattern& ip,
160 const std::vector<const OperationNode<Base>*>& indexes) {
161 std::stringstream ss;
162 switch (ip.getType()) {
163 case IndexPatternType::Linear: // y = x * a + b
164 {
165 CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes")
166 const auto& lip = static_cast<const LinearIndexPattern&> (ip);
167 linearIndexPattern2String(os, lip, *indexes[0]);
168 return;
169 }
170 case IndexPatternType::Sectioned:
171 {
172 CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes")
173 const auto* lip = static_cast<const SectionedIndexPattern*> (&ip);
174 const std::map<size_t, IndexPattern*>& sections = lip->getLinearSections();
175 size_t sSize = sections.size();
176 CPPADCG_ASSERT_UNKNOWN(sSize > 1);
177
178 auto its = sections.begin();
179 for (size_t s = 0; s < sSize - 1; s++) {
180 const IndexPattern* lp = its->second;
181 ++its;
182 size_t xStart = its->first;
183
184 os << "<mfenced><mrow><mi class='index'>" << (*indexes[0]->getName()) << "</mi> <mo>&lt;</mo> <mn>" << xStart << "</mn></mrow></mfenced><mo>?</mo> ";
185 indexPattern2String(os, *lp, *indexes[0]);
186 os << "<mo>:</mo> ";
187 }
188 indexPattern2String(os, *its->second, *indexes[0]);
189
190 return;
191 }
192
193 case IndexPatternType::Plane2D: // y = f(x) + f(z)
194 {
195 CPPADCG_ASSERT_KNOWN(indexes.size() >= 1, "Invalid number of indexes")
196 const auto& pip = static_cast<const Plane2DIndexPattern&> (ip);
197 bool useParens = pip.getPattern1() != nullptr && pip.getPattern2() != nullptr;
198
199 if (useParens) os << "<mfenced><mrow>";
200
201 if (pip.getPattern1() != nullptr)
202 indexPattern2String(os, *pip.getPattern1(), *indexes[0]);
203
204 if (useParens) os << "</mrow></mfenced> <mo>+</mo> <mfenced><mrow>";
205
206 if (pip.getPattern2() != nullptr)
207 indexPattern2String(os, *pip.getPattern2(), *indexes.back());
208
209 if (useParens) os << "</mrow></mfenced>";
210
211 return;
212 }
213 case IndexPatternType::Random1D:
214 {
215 CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes")
216 const auto& rip = static_cast<const Random1DIndexPattern&> (ip);
217 CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array")
218 os << rip.getName() << "<mfenced open='[' close=']'><mi>" << (*indexes[0]->getName()) << "</mi></mfenced>";
219 return;
220 }
221 case IndexPatternType::Random2D:
222 {
223 CPPADCG_ASSERT_KNOWN(indexes.size() == 2, "Invalid number of indexes")
224 const auto& rip = static_cast<const Random2DIndexPattern&> (ip);
225 CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array")
226 os << rip.getName() <<
227 "<mfenced open='[' close=']'><mrow><mi>" << (*indexes[0]->getName()) << "</mi></mrow></mfenced>"
228 "<mfenced open='[' close=']'><mrow><mi>" << (*indexes[1]->getName()) << "</mi></mrow></mfenced>";
229 return;
230 }
231 default:
232 CPPADCG_ASSERT_UNKNOWN(false); // should never reach this
233 return;
234 }
235}
236
237template<class Base>
238inline void LanguageMathML<Base>::linearIndexPattern2String(std::ostream& os,
239 const LinearIndexPattern& lip,
240 const OperationNode<Base>& index) {
241 long dy = lip.getLinearSlopeDy();
242 long dx = lip.getLinearSlopeDx();
243 long b = lip.getLinearConstantTerm();
244 long xOffset = lip.getXOffset();
245
246 if (dy != 0) {
247 if (xOffset != 0) {
248 os << "<mfenced><mrow>";
249 }
250 os << "<mi class='index'>" << (*index.getName()) << "</mi>";
251 if (xOffset != 0) {
252 os << " <mo>-</mo><mn>" << xOffset << "</mn></mrow></mfenced>";
253 }
254
255 if (dx != 1) {
256 os << "<mo>/</mo><mn>" << dx << "</mn>";
257 }
258 if (dy != 1) {
259 os << "<mo>&sdot;</mo><mn>" << dy << "</mn>"; // TODO: use _multOpStr
260 }
261 } else if (b == 0) {
262 os << "<mn>0</mn>"; // when dy == 0 and b == 0
263 }
264
265 if (b != 0) {
266 if (dy != 0)
267 os << "<mo>+</mo>";
268 os << "<mn>" << b << "</mn>";
269 }
270
271}
272
273} // END cg namespace
274} // END CppAD namespace
275
276#endif
void printRandomIndexPatternDeclaration(std::ostringstream &os, const std::string &identation, const std::set< RandomIndexPattern * > &randomPatterns)
void printStaticIndexMatrix(std::ostringstream &os, const std::string &name, const std::map< size_t, std::map< size_t, size_t > > &values)