CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
language_latex_index_patterns.hpp
1 #ifndef CPPAD_CG_LANGUAGE_LATEX_INDEX_PATTERNS_INCLUDED
2 #define CPPAD_CG_LANGUAGE_LATEX_INDEX_PATTERNS_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2014 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 LanguageLatex<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(name);
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 LanguageLatex<Base>::printStaticIndexArray(std::ostringstream& os,
87  const std::string& name,
88  const std::vector<size_t>& values) {
89  os << name << " = \\left\\{";
90  if (!values.empty()) {
91  os << values[0];
92  for (size_t i = 1; i < values.size(); i++) {
93  os << ", " << values[i];
94  }
95  }
96  os << "\\right\\}" << _endEq << " % size: " << values.size() << _endline;
97 }
98 
99 template<class Base>
100 void LanguageLatex<Base>::printStaticIndexMatrix(std::ostringstream& os,
101  const std::string& name,
102  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 << " = \\left\\{";
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 << "{},";
124  x++;
125  }
126  }
127 
128  os << "{";
129 
130  size_t y = 0;
131  for (ity2z = it->second.begin(); ity2z != it->second.end(); ++ity2z) {
132  if (ity2z->first != y) {
133  while (ity2z->first != y) {
134  os << "0,";
135  y++;
136  }
137  }
138 
139  os << ity2z->second;
140  if (ity2z->first != it->second.rbegin()->first) os << ",";
141 
142  y++;
143  }
144 
145  os << "}";
146  if (it->first != values.rbegin()->first) os << ",";
147 
148  x++;
149  }
150  os << "\\right\\}" << _endEq << "% size: " << m << " x " << n << _endline;
151 }
152 
153 template<class Base>
154 inline std::string LanguageLatex<Base>::indexPattern2String(const IndexPattern& ip,
155  const OperationNode<Base>& index) {
156  return indexPattern2String(ip,{&index});
157 }
158 
159 template<class Base>
160 inline std::string LanguageLatex<Base>::indexPattern2String(const IndexPattern& ip,
161  const std::vector<const OperationNode<Base>*>& indexes) {
162  std::stringstream ss;
163  switch (ip.getType()) {
164  case IndexPatternType::Linear: // y = x * a + b
165  {
166  CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes")
167  const auto& lip = static_cast<const LinearIndexPattern&> (ip);
168  return linearIndexPattern2String(lip, *indexes[0]);
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  ss << "\\left(" << (*indexes[0]->getName()) << "<" << xStart << "\\right)? "
185  << indexPattern2String(*lp, *indexes[0]) << ": ";
186  }
187  ss << indexPattern2String(*its->second, *indexes[0]);
188 
189  return ss.str();
190  }
191 
192  case IndexPatternType::Plane2D: // y = f(x) + f(z)
193  {
194  CPPADCG_ASSERT_KNOWN(indexes.size() >= 1, "Invalid number of indexes")
195  std::string indexExpr;
196  const auto& pip = static_cast<const Plane2DIndexPattern&> (ip);
197  bool useParens = pip.getPattern1() != nullptr && pip.getPattern2() != nullptr;
198 
199  if (useParens) indexExpr += "\\left(";
200 
201  if (pip.getPattern1() != nullptr)
202  indexExpr += indexPattern2String(*pip.getPattern1(), *indexes[0]);
203 
204  if (useParens) indexExpr += "\\right) + \\left(";
205 
206  if (pip.getPattern2() != nullptr)
207  indexExpr += indexPattern2String(*pip.getPattern2(), *indexes.back());
208 
209  if (useParens) indexExpr += "\\right)";
210 
211  return indexExpr;
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  return rip.getName() + "\\left[" + (*indexes[0]->getName()) + "\\right]";
219  }
220  case IndexPatternType::Random2D:
221  {
222  CPPADCG_ASSERT_KNOWN(indexes.size() == 2, "Invalid number of indexes")
223  const auto& rip = static_cast<const Random2DIndexPattern&> (ip);
224  CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array")
225  return rip.getName() + "\\left[" + (*indexes[0]->getName()) + "\\right]\\left[" + (*indexes[1]->getName()) + "\\right]";
226  }
227  default:
228  CPPADCG_ASSERT_UNKNOWN(false); // should never reach this
229  return "";
230  }
231 }
232 
233 template<class Base>
235  const OperationNode<Base>& index) {
236  long dy = lip.getLinearSlopeDy();
237  long dx = lip.getLinearSlopeDx();
238  long b = lip.getLinearConstantTerm();
239  long xOffset = lip.getXOffset();
240 
241  std::stringstream ss;
242  if (dy != 0) {
243  if (xOffset != 0) {
244  ss << "\\left(";
245  }
246  ss << (*index.getName());
247  if (xOffset != 0) {
248  ss << " - " << xOffset << "\\right)";
249  }
250 
251  if (dx != 1) {
252  ss << " / " << dx;
253  }
254  if (dy != 1) {
255  ss << " \\cdot " << dy;
256  }
257  } else if (b == 0) {
258  ss << "0"; // when dy == 0 and b == 0
259  }
260 
261  if (b != 0) {
262  if (dy != 0)
263  ss << " + ";
264  ss << b;
265  }
266  return ss.str();
267 }
268 
269 } // END cg namespace
270 } // END CppAD namespace
271 
272 #endif
const std::string * getName() const
void printRandomIndexPatternDeclaration(std::ostringstream &os, const std::string &identation, const std::set< RandomIndexPattern *> &randomPatterns)