inline std::string LanguageC<Base>::linearIndexPattern2String(const LinearIndexPattern& lip, const IndexDclrOperationNode<Base>& index) { long dy = lip.getLinearSlopeDy(); long dx = lip.getLinearSlopeDx(); long b = lip.getLinearConstantTerm(); long xOffset = lip.getXOffset(); std::stringstream ss; if (dy != 0) { if (xOffset != 0) { ss << "("; } ss << (*index.getName()); if (xOffset != 0) { ss << " - " << xOffset << ")"; } if (dx != 1) { ss << " / " << dx; } if (dy != 1) { ss << " * " << dy; } } else if (b == 0) { ss << "0"; // when dy == 0 and b == 0 } if (b != 0) { if (dy != 0) ss << " + "; ss << b; } return ss.str(); }
static inline Plane2DIndexPattern* detectPlane2D(const std::map<size_t, std::map<size_t, size_t> >& x2y2z) { /** * try to fit a combination of two patterns: * z = fStart(x) + flit(y); */ if (x2y2z.size() == 1) { // only one x -> fit z to y const std::map<size_t, size_t>& y2z = x2y2z.begin()->second; return new Plane2DIndexPattern(nullptr, IndexPattern::detect(y2z)); } // perhaps there is always only one y size_t y = x2y2z.begin()->second.begin()->first; std::map<size_t, size_t> x2z; std::map<size_t, std::map<size_t, size_t> >::const_iterator itx2y2z; for (itx2y2z = x2y2z.begin(); itx2y2z != x2y2z.end(); ++itx2y2z) { size_t x = itx2y2z->first; const std::map<size_t, size_t>& y2z = itx2y2z->second; if (y2z.size() != 1 || y != y2z.begin()->first) { x2z.clear(); // not always the same y break; } size_t z = y2z.begin()->second; x2z[x] = z; } if (!x2z.empty()) { return new Plane2DIndexPattern(IndexPattern::detect(x2z), nullptr); } /** * try to fit a combination of two patterns: * z = fStart(x) + flit(y); */ std::map<size_t, size_t> x2zStart; std::map<size_t, size_t> y2zOffset; for (itx2y2z = x2y2z.begin(); itx2y2z != x2y2z.end(); ++itx2y2z) { size_t x = itx2y2z->first; const std::map<size_t, size_t>& y2z = itx2y2z->second; size_t zFirst = y2z.begin()->second; x2zStart[x] = zFirst; std::map<size_t, size_t>::const_iterator ity2z; for (ity2z = y2z.begin(); ity2z != y2z.end(); ++ity2z) { size_t y = ity2z->first; size_t offset = ity2z->second - zFirst; std::map<size_t, size_t>::const_iterator itY2zOffset = y2zOffset.find(y); if (itY2zOffset == y2zOffset.end()) { y2zOffset[y] = offset; } else if (itY2zOffset->second != offset) { return nullptr; // does not fit the pattern } } } /** * try to detect a pattern for the initial iteration index based on x */ std::unique_ptr<IndexPattern> fx; std::map<size_t, IndexPattern*> startSections = SectionedIndexPattern::detectLinearSections(x2zStart, 2); if (startSections.empty()) { return nullptr; // does not fit the pattern } // detected a pattern for the first z based on x if (startSections.size() == 1) { fx = std::unique_ptr<IndexPattern> (startSections.begin()->second); } else { fx = std::unique_ptr<IndexPattern> (new SectionedIndexPattern(startSections)); } /** * try to detect a pattern for the following iterations * based on the local loop index (local index != model index) */ std::map<size_t, IndexPattern*> sections = SectionedIndexPattern::detectLinearSections(y2zOffset, 2); if (sections.empty()) { return nullptr; // does not fit the pattern } // detected a pattern for the z offset based on y std::unique_ptr<IndexPattern> fy; if (sections.size() == 1) { fy = std::unique_ptr<IndexPattern> (sections.begin()->second); } else { fy = std::unique_ptr<IndexPattern> (new SectionedIndexPattern(sections)); } // simplify when both patterns are constant if (fx->getType() == IndexPatternType::Linear && fy->getType() == IndexPatternType::Linear) { LinearIndexPattern* ipx = static_cast<LinearIndexPattern*> (fx.get()); LinearIndexPattern* ipy = static_cast<LinearIndexPattern*> (fy.get()); if (ipx->getLinearSlopeDy() == 0 && ipy->getLinearSlopeDy() == 0) { /** * only need to keep one */ ipx->setLinearConstantTerm(ipx->getLinearConstantTerm() + ipy->getLinearConstantTerm()); fy.reset(); } } return new Plane2DIndexPattern(fx.release(), fy.release()); }