1 #ifndef CPPAD_CG_LANGUAGE_C_INDEX_PATTERNS_INCLUDED
2 #define CPPAD_CG_LANGUAGE_C_INDEX_PATTERNS_INCLUDED
23 inline void LanguageC<Base>::generateNames4RandomIndexPatterns(
const std::set<RandomIndexPattern*>& randomPatterns) {
24 std::ostringstream os;
26 std::set<std::string> usedNames;
30 for (RandomIndexPattern* ip : randomPatterns) {
31 if (!ip->getName().empty()) {
32 usedNames.insert(ip->getName());
38 for (RandomIndexPattern* ip : randomPatterns) {
39 if (ip->getName().empty()) {
43 os << _C_STATIC_INDEX_ARRAY << c;
47 }
while (usedNames.find(name) != usedNames.end());
57 const std::string& indentation,
58 const std::set<RandomIndexPattern*>& randomPatterns) {
60 if (ip->getType() == IndexPatternType::Random1D) {
65 const std::map<size_t, size_t>& x2y = ip1->getValues();
67 std::vector<size_t> y(x2y.rbegin()->first + 1);
68 for (
const auto& p : x2y)
69 y[p.first] = p.second;
72 printStaticIndexArray(os, ip->getName(), y);
74 CPPADCG_ASSERT_UNKNOWN(ip->getType() == IndexPatternType::Random2D)
80 printStaticIndexMatrix(os, ip->getName(), ip2->getValues());
90 if (_info->indexes.empty())
93 std::set<const OperationNode<Base>*> funcArgs(_funcArgIndexes.begin(), _funcArgIndexes.end());
97 printRandomIndexPatternDeclaration(_ss, _spaces, _info->indexRandomPatterns);
99 _ss << _spaces << U_INDEX_TYPE;
102 if (funcArgs.find(iti) == funcArgs.end()) {
103 if (first) first =
false;
106 _ss <<
" " << (*iti->
getName());
114 void LanguageC<Base>::printStaticIndexArray(std::ostringstream& os,
115 const std::string& name,
116 const std::vector<size_t>& values) {
117 os <<
"static " << U_INDEX_TYPE <<
" const " << name <<
"[" << values.size() <<
"] = {";
118 if (!values.empty()) {
120 for (
size_t i = 1; i < values.size(); i++) {
121 os <<
"," << values[i];
128 void LanguageC<Base>::printStaticIndexMatrix(std::ostringstream& os,
129 const std::string& name,
130 const std::map<
size_t, std::map<size_t, size_t> >& values) {
134 std::map<size_t, std::map<size_t, size_t> >::const_iterator it;
135 std::map<size_t, size_t>::const_iterator ity2z;
137 if (!values.empty()) {
138 m = values.rbegin()->first + 1;
140 for (it = values.begin(); it != values.end(); ++it) {
141 if (!it->second.empty())
142 n = std::max<size_t>(n, it->second.rbegin()->first + 1);
146 os <<
"static " << U_INDEX_TYPE <<
" const " << name <<
"[" << m <<
"][" << n <<
"] = {";
148 for (it = values.begin(); it != values.end(); ++it) {
149 if (it->first != x) {
150 while (it->first != x) {
159 for (ity2z = it->second.begin(); ity2z != it->second.end(); ++ity2z) {
160 if (ity2z->first != y) {
161 while (ity2z->first != y) {
168 if (ity2z->first != it->second.rbegin()->first) os <<
",";
174 if (it->first != values.rbegin()->first) os <<
",";
182 inline std::string LanguageC<Base>::indexPattern2String(
const IndexPattern& ip,
183 const OperationNode<Base>& index) {
184 return indexPattern2String(ip,{index.getName()});
188 inline std::string LanguageC<Base>::indexPattern2String(
const IndexPattern& ip,
189 const std::string& index) {
190 return indexPattern2String(ip,{&index});
194 inline std::string LanguageC<Base>::indexPattern2String(
const IndexPattern& ip,
195 const std::vector<
const OperationNode<Base>*>& indexes) {
196 std::vector<const std::string*> indexStr(indexes.size());
197 for (
size_t i = 0; i < indexes.size(); ++i)
198 indexStr[i] = indexes[i]->getName();
199 return indexPattern2String(ip, indexStr);
203 inline std::string LanguageC<Base>::indexPattern2String(
const IndexPattern& ip,
204 const std::vector<const std::string*>& indexes) {
205 std::stringstream ss;
206 switch (ip.getType()) {
207 case IndexPatternType::Linear:
209 CPPADCG_ASSERT_KNOWN(indexes.size() == 1,
"Invalid number of indexes")
210 const auto& lip = static_cast<const LinearIndexPattern&> (ip);
211 return linearIndexPattern2String(lip, *indexes[0]);
213 case IndexPatternType::Sectioned:
215 CPPADCG_ASSERT_KNOWN(indexes.size() == 1,
"Invalid number of indexes")
216 const auto* lip = static_cast<const SectionedIndexPattern*> (&ip);
217 const std::map<
size_t, IndexPattern*>& sections = lip->getLinearSections();
218 size_t sSize = sections.size();
219 CPPADCG_ASSERT_UNKNOWN(sSize > 1)
221 auto its = sections.begin();
222 for (
size_t s = 0; s < sSize - 1; s++) {
223 const IndexPattern* lp = its->second;
225 size_t xStart = its->first;
227 ss <<
"(" << (*indexes[0]) <<
"<" << xStart <<
")? "
228 << indexPattern2String(*lp, *indexes[0]) <<
": ";
230 ss << indexPattern2String(*its->second, *indexes[0]);
235 case IndexPatternType::Plane2D:
237 CPPADCG_ASSERT_KNOWN(!indexes.empty(),
"Invalid number of indexes")
238 std::
string indexExpr;
239 const auto& pip = static_cast<const Plane2DIndexPattern&> (ip);
240 bool useParens = pip.getPattern1() !=
nullptr && pip.getPattern2() !=
nullptr;
242 if (useParens) indexExpr += "(";
244 if (pip.getPattern1() !=
nullptr)
245 indexExpr += indexPattern2String(*pip.getPattern1(), *indexes[0]);
247 if (useParens) indexExpr += ") + (";
249 if (pip.getPattern2() !=
nullptr)
250 indexExpr += indexPattern2String(*pip.getPattern2(), *indexes.back());
252 if (useParens) indexExpr += ")";
256 case IndexPatternType::Random1D:
258 CPPADCG_ASSERT_KNOWN(indexes.size() == 1,
"Invalid number of indexes")
259 const auto& rip = static_cast<const Random1DIndexPattern&> (ip);
260 CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array")
261 return rip.getName() + "[" + (*indexes[0]) + "]";
263 case IndexPatternType::Random2D:
265 CPPADCG_ASSERT_KNOWN(indexes.size() == 2,
"Invalid number of indexes")
266 const auto& rip = static_cast<const Random2DIndexPattern&> (ip);
267 CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array")
268 return rip.getName() + "[" + (*indexes[0]) + "][" + (*indexes[1]) + "]";
271 CPPADCG_ASSERT_UNKNOWN(false);
277 inline std::
string LanguageC<Base>::linearIndexPattern2String(const LinearIndexPattern& lip,
278 const OperationNode<Base>& index) {
279 return linearIndexPattern2String(lip, *index.getName());
283 inline std::string LanguageC<Base>::linearIndexPattern2String(
const LinearIndexPattern& lip,
284 const std::string& index) {
285 long dy = lip.getLinearSlopeDy();
286 long dx = lip.getLinearSlopeDx();
287 long b = lip.getLinearConstantTerm();
288 long xOffset = lip.getXOffset();
290 std::stringstream ss;
297 ss <<
" - " << xOffset <<
")";
319 bool LanguageC<Base>::isOffsetBy(
const IndexPattern* ip,
320 const IndexPattern* refIp,
323 if (ip->getType() == IndexPatternType::Linear) {
324 const auto* lIp =
dynamic_cast<const LinearIndexPattern*
> (ip);
325 assert(lIp !=
nullptr);
327 if (refIp->getType() != IndexPatternType::Linear)
329 const auto* refLIp =
dynamic_cast<const LinearIndexPattern*
> (refIp);
330 assert(refLIp !=
nullptr);
332 return isOffsetBy(*lIp, *refLIp, offset);
334 }
else if (ip->getType() == IndexPatternType::Sectioned) {
335 const auto* sIp =
dynamic_cast<const SectionedIndexPattern*
> (ip);
336 assert(sIp !=
nullptr);
338 if (refIp->getType() != IndexPatternType::Sectioned)
340 const auto* refSecp =
dynamic_cast<const SectionedIndexPattern*
> (refIp);
341 assert(refSecp !=
nullptr);
343 return isOffsetBy(*sIp, *refSecp, offset);
352 bool LanguageC<Base>::isOffsetBy(
const LinearIndexPattern* lIp,
353 const LinearIndexPattern* refLIp,
356 if (lIp ==
nullptr || refLIp ==
nullptr)
359 return isOffsetBy(*lIp, *refLIp, offset);
363 bool LanguageC<Base>::isOffsetBy(
const LinearIndexPattern& lIp,
364 const LinearIndexPattern& refLIp,
366 return refLIp.getLinearSlopeDx() == lIp.getLinearSlopeDx() &&
367 refLIp.getLinearSlopeDy() == lIp.getLinearSlopeDy() &&
368 refLIp.getXOffset() == lIp.getXOffset() &&
369 refLIp.getLinearConstantTerm() + offset == lIp.getLinearConstantTerm();
373 bool LanguageC<Base>::isOffsetBy(
const SectionedIndexPattern* sIp,
374 const SectionedIndexPattern* refSecp,
376 if (refSecp ==
nullptr || sIp ==
nullptr)
379 return isOffsetBy(*sIp, *refSecp, offset);
383 bool LanguageC<Base>::isOffsetBy(
const SectionedIndexPattern& sIp,
384 const SectionedIndexPattern& refSecp,
387 if (refSecp.getLinearSections().size() != sIp.getLinearSections().size())
390 auto itRef = refSecp.getLinearSections().begin();
391 for (
const auto& section : sIp.getLinearSections()) {
393 if (itRef->first != section.first) {
395 }
else if (itRef->second->getType() != IndexPatternType::Linear || section.second->getType() != IndexPatternType::Linear) {
399 auto* refSecLIp =
static_cast<LinearIndexPattern*
> (itRef->second);
400 auto* secLIp =
static_cast<LinearIndexPattern*
> (section.second);
402 if (!isOffsetBy(secLIp, refSecLIp, offset)) {
413 Plane2DIndexPattern* LanguageC<Base>::encapsulateIndexPattern(
const LinearIndexPattern& refLIp,
415 std::unique_ptr<IndexPattern> ip2;
417 auto* lip2 =
new LinearIndexPattern(refLIp);
419 lip2->setLinearConstantTerm(lip2->getLinearConstantTerm() - starti);
421 return new Plane2DIndexPattern(ip2.release(),
new LinearIndexPattern(0, 1, 1, 0));
425 Plane2DIndexPattern* LanguageC<Base>::encapsulateIndexPattern(
const SectionedIndexPattern& refSecp,
427 std::unique_ptr<IndexPattern> ip2;
429 std::map<size_t, IndexPattern*> sections;
430 for (
const auto& section : refSecp.getLinearSections()) {
431 auto* lip2 =
new LinearIndexPattern(*
static_cast<LinearIndexPattern*
> (section.second));
432 lip2->setLinearConstantTerm(lip2->getLinearConstantTerm() - starti);
433 sections[section.first] = lip2;
435 ip2.reset(
new SectionedIndexPattern(sections));
437 return new Plane2DIndexPattern(ip2.release(),
new LinearIndexPattern(0, 1, 1, 0));
static void printRandomIndexPatternDeclaration(std::ostringstream &os, const std::string &identation, const std::set< RandomIndexPattern * > &randomPatterns)
const std::string * getName() const