CppADCodeGen  HEAD
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  * 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 
19 namespace CppAD {
20 namespace cg {
21 
22 template<class Base>
23 inline 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 
55 template<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 
85 template<class Base>
86 void 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 
96 template<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 
150 template<class Base>
151 inline void LanguageMathML<Base>::indexPattern2String(std::ostream& os,
152  const IndexPattern& ip,
153  const OperationNode<Base>& index) {
154  indexPattern2String(os, ip,{&index});
155 }
156 
157 template<class Base>
158 inline 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 
237 template<class Base>
238 inline 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)
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)