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