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