/** * Determines the iteration regions not present in the provided iteration * regions. * * @param iterRegions a vector filled with ordered and non-overlapping * iteration regions each defined with pairs of integers * (start1, end1, start2, end2, ...) * @return the iterations not present in iterRegions */ inline std::vector<size_t> invertIterationRanges(const std::vector<size_t>& iterRegions) { std::vector<size_t> inverted; if (iterRegions.empty()) { inverted.resize(2); inverted[1] = std::numeric_limits<size_t>::max(); return inverted; } CPPADCG_ASSERT_UNKNOWN(iterRegions.size() % 2 == 0); inverted.reserve(iterRegions.size() + 4); if (iterRegions[0] != 0) { inverted.push_back(0); inverted.push_back(iterRegions[0] - 1); } for (size_t i = 2; i < iterRegions.size(); i += 2) { CPPADCG_ASSERT_UNKNOWN(iterRegions[i - 1] < iterRegions[i]); inverted.push_back(iterRegions[i - 1] + 1); inverted.push_back(iterRegions[i] - 1); } if (iterRegions.back() != std::numeric_limits<size_t>::max()) { inverted.push_back(iterRegions.back() + 1); inverted.push_back(std::numeric_limits<size_t>::max()); } return inverted; }
inline void LanguageC<Base>::printRandomIndexPatternDeclaration(std::ostringstream& os, const std::string& indentation, const std::set<RandomIndexPattern*>& randomPatterns) { for (RandomIndexPattern* ip : randomPatterns) { if (ip->getType() == IndexPatternType::Random1D) { /** * 1D */ Random1DIndexPattern* ip1 = static_cast<Random1DIndexPattern*> (ip); const std::map<size_t, size_t>& x2y = ip1->getValues(); std::vector<size_t> y(x2y.rbegin()->first + 1); for (const std::pair<size_t, size_t>& p : x2y) y[p.first] = p.second; os << indentation; printStaticIndexArray(os, ip->getName(), y); } else { CPPADCG_ASSERT_UNKNOWN(ip->getType() == IndexPatternType::Random2D); /** * 2D */ Random2DIndexPattern* ip2 = static_cast<Random2DIndexPattern*> (ip); os << indentation; printStaticIndexMatrix(os, ip->getName(), ip2->getValues()); } } }
/** * Combines ordered and non-overlapping regions of iteration indexes. * * @param iterRegions the existing iteration regions * @param newIterRegions the iteration regions to be added */ inline void combineNonOverlapingIterationRanges(std::vector<size_t>& iterRegions, const std::vector<size_t>& newIterRegions) { if (iterRegions.empty()) { iterRegions = newIterRegions; return; } else if (newIterRegions.empty()) { return; } /** * regions are assumed to be ordered and non-overlapping */ std::vector<size_t>::iterator itPos = iterRegions.begin(); std::vector<size_t>::const_iterator itNew; for (itNew = newIterRegions.begin(); itNew != newIterRegions.end(); ++itNew) { size_t pos = *itNew; itPos = std::lower_bound(itPos, iterRegions.end(), pos); if (itPos == iterRegions.end()) { iterRegions.insert(iterRegions.end(), itNew, newIterRegions.end()); break; // done } else if (*itPos == pos) { // same value -> must merge itPos = iterRegions.erase(itPos); } else { itPos = iterRegions.insert(itPos, pos); } } CPPADCG_ASSERT_UNKNOWN(iterRegions.size() % 2 == 0); }
inline CG<Base>& CG<Base>::operator-=(const CG<Base> &right) { if (isParameter() && right.isParameter()) { *value_ -= *right.value_; } else { CodeHandler<Base>* handler; if (isParameter()) { handler = right.getCodeHandler(); } else if (right.isParameter()) { if (right.isIdenticalZero()) { return *this; // nothing to do } handler = getCodeHandler(); } else { CPPADCG_ASSERT_UNKNOWN(getCodeHandler() == right.getCodeHandler()); handler = getCodeHandler(); } std::unique_ptr<Base> value; if (isValueDefined() && right.isValueDefined()) { value.reset(new Base(getValue() - right.getValue())); } makeVariable(*handler, new OperationNode<Base>(CGOpCode::Sub,{argument(), right.argument()}), value); } return *this; }
inline void addFreeArraySpace(const OperationNode<Base>& released) { size_t arrayStart = _varId[released] - 1; const size_t arraySize = released.getArguments().size(); if (arraySize == 0) return; // nothing to do (no free space) size_t arrayEnd = arrayStart + arraySize - 1; std::map<size_t, size_t>::iterator it; if (arrayStart > 0) { // try to merge with previous free space it = _freeArrayEndSpace.find(arrayStart - 1); // previous if (it != _freeArrayEndSpace.end()) { arrayStart = it->second; // merge space _freeArrayEndSpace.erase(it); _freeArrayStartSpace.erase(arrayStart); } } // try to merge with the next free space it = _freeArrayStartSpace.find(arrayEnd + 1); // next if (it != _freeArrayStartSpace.end()) { arrayEnd = it->second; // merge space _freeArrayStartSpace.erase(it); _freeArrayEndSpace.erase(arrayEnd); } _freeArrayStartSpace[arrayStart] = arrayEnd; _freeArrayEndSpace[arrayEnd] = arrayStart; CPPADCG_ASSERT_UNKNOWN(_freeArrayStartSpace.size() == _freeArrayEndSpace.size()); }
/** * Creates a new model * * @param name The model name */ LinuxDynamicLibModel(LinuxDynamicLib<Base>* dynLib, const std::string& name) : FunctorGenericModel<Base>(name), _dynLib(dynLib) { CPPADCG_ASSERT_UNKNOWN(_dynLib != nullptr); this->init(); }
inline CG<Base>& CG<Base>::operator*=(const CG<Base> &right) { if (isParameter() && right.isParameter()) { *value_ *= *right.value_; } else { CodeHandler<Base>* handler; if (isParameter()) { if (isIdenticalZero()) { return *this; // nothing to do (does not consider that right might be infinity) } else if (isIdenticalOne()) { *this = right; return *this; } handler = right.getCodeHandler(); } else if (right.isParameter()) { if (right.isIdenticalZero()) { makeParameter(Base(0.0)); // does not consider that left might be infinity return *this; } else if (right.isIdenticalOne()) { return *this; // nothing to do } handler = getCodeHandler(); } else { CPPADCG_ASSERT_UNKNOWN(getCodeHandler() == right.getCodeHandler()); handler = getCodeHandler(); } std::unique_ptr<Base> value; if (isValueDefined() && right.isValueDefined()) { value.reset(new Base(getValue() * right.getValue())); } makeVariable(*handler, new OperationNode<Base>(CGOpCode::Mul,{argument(), right.argument()}), value); } return *this; }
inline std::string LanguageC<Base>::indexPattern2String(const IndexPattern& ip, const std::vector<const IndexDclrOperationNode<Base>*>& indexes) { std::stringstream ss; switch (ip.getType()) { case IndexPatternType::Linear: // y = x * a + b { CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes"); const LinearIndexPattern& lip = static_cast<const LinearIndexPattern&> (ip); return linearIndexPattern2String(lip, *indexes[0]); } case IndexPatternType::Sectioned: { CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes"); const SectionedIndexPattern* lip = static_cast<const SectionedIndexPattern*> (&ip); const std::map<size_t, IndexPattern*>& sections = lip->getLinearSections(); size_t sSize = sections.size(); CPPADCG_ASSERT_UNKNOWN(sSize > 1); std::map<size_t, IndexPattern*>::const_iterator its = sections.begin(); for (size_t s = 0; s < sSize - 1; s++) { const IndexPattern* lp = its->second; ++its; size_t xStart = its->first; ss << "(" << (*indexes[0]->getName()) << "<" << xStart << ")? " << indexPattern2String(*lp, *indexes[0]) << ": "; } ss << indexPattern2String(*its->second, *indexes[0]); return ss.str(); } case IndexPatternType::Plane2D: // y = f(x) + f(z) { CPPADCG_ASSERT_KNOWN(indexes.size() >= 1, "Invalid number of indexes"); std::string indexExpr; const Plane2DIndexPattern& pip = static_cast<const Plane2DIndexPattern&> (ip); bool useParens = pip.getPattern1() != nullptr && pip.getPattern2() != nullptr; if (useParens) indexExpr += "("; if (pip.getPattern1() != nullptr) indexExpr += indexPattern2String(*pip.getPattern1(), *indexes[0]); if (useParens) indexExpr += ") + ("; if (pip.getPattern2() != nullptr) indexExpr += indexPattern2String(*pip.getPattern2(), *indexes.back()); if (useParens) indexExpr += ")"; return indexExpr; } case IndexPatternType::Random1D: { CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes"); const Random1DIndexPattern& rip = static_cast<const Random1DIndexPattern&> (ip); CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array"); return rip.getName() + "[" + (*indexes[0]->getName()) + "]"; } case IndexPatternType::Random2D: { CPPADCG_ASSERT_KNOWN(indexes.size() == 2, "Invalid number of indexes"); const Random2DIndexPattern& rip = static_cast<const Random2DIndexPattern&> (ip); CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array"); return rip.getName() + "[" + (*indexes[0]->getName()) + "][" + (*indexes[1]->getName()) + "]"; } default: CPPADCG_ASSERT_UNKNOWN(false); // should never reach this return ""; } }
inline std::vector<size_t> ifBranchIterationRanges(const OperationNode<Base>* bScope, IndexOperationNode<Base>*& iterationIndexOp) { CGOpCode bOp = bScope->getOperationType(); if (bOp == CGOpCode::StartIf || bOp == CGOpCode::ElseIf) { OperationNode<Base>* cond = bScope->getArguments()[bOp == CGOpCode::StartIf ? 0 : 1].getOperation(); CPPADCG_ASSERT_UNKNOWN(cond->getOperationType() == CGOpCode::IndexCondExpr); CPPADCG_ASSERT_UNKNOWN(cond->getArguments().size() == 1); CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation() != nullptr); CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation()->getOperationType() == CGOpCode::Index); iterationIndexOp = static_cast<IndexOperationNode<Base>*> (cond->getArguments()[0].getOperation()); return cond->getInfo(); } else { // else CPPADCG_ASSERT_UNKNOWN(bOp == CGOpCode::Else); std::vector<size_t> nonIterationRegions; OperationNode<Base>* ifBranch = bScope->getArguments()[0].getOperation(); do { CGOpCode bbOp = ifBranch->getOperationType(); OperationNode<Base>* cond = ifBranch->getArguments()[bbOp == CGOpCode::StartIf ? 0 : 1].getOperation(); CPPADCG_ASSERT_UNKNOWN(cond->getOperationType() == CGOpCode::IndexCondExpr); CPPADCG_ASSERT_UNKNOWN(cond->getArguments().size() == 1); CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation() != nullptr); CPPADCG_ASSERT_UNKNOWN(cond->getArguments()[0].getOperation()->getOperationType() == CGOpCode::Index); IndexOperationNode<Base>* indexOp = static_cast<IndexOperationNode<Base>*> (cond->getArguments()[0].getOperation()); CPPADCG_ASSERT_UNKNOWN(iterationIndexOp == nullptr || iterationIndexOp == indexOp); iterationIndexOp = indexOp; combineOverlapingIterationRanges(nonIterationRegions, cond->getInfo()); ifBranch = ifBranch->getArguments()[0].getOperation(); } while (ifBranch->getOperationType() == CGOpCode::ElseIf); CPPADCG_ASSERT_UNKNOWN(iterationIndexOp != nullptr); // invert return invertIterationRanges(nonIterationRegions); } }
inline Plane2DIndexPattern(IndexPattern* pattern1, IndexPattern* pattern2) : pattern1_(pattern1), pattern2_(pattern2) { CPPADCG_ASSERT_UNKNOWN(pattern1_ != nullptr || pattern2_ != nullptr); }
inline size_t reserveArraySpace(const OperationNode<Base>& newArray) { size_t arraySize = newArray.getArguments().size(); if (arraySize == 0) return 0; // nothing to do (no space required) std::set<size_t> blackList; const std::vector<Argument<Base> >& args = newArray.getArguments(); for (size_t i = 0; i < args.size(); i++) { const OperationNode<Base>* argOp = args[i].getOperation(); if (argOp != nullptr && argOp->getOperationType() == CGOpCode::ArrayElement) { const OperationNode<Base>& otherArray = *argOp->getArguments()[0].getOperation(); CPPADCG_ASSERT_UNKNOWN(_varId[otherArray] > 0); // make sure it had already been assigned space size_t otherArrayStart = _varId[otherArray] - 1; size_t index = argOp->getInfo()[0]; blackList.insert(otherArrayStart + index); } } /** * Find the best location for the new array */ std::map<size_t, size_t>::reverse_iterator it; std::map<size_t, size_t>::reverse_iterator itBestFit = _freeArrayStartSpace.rend(); size_t bestCommonValues = 0; // the number of values likely to be the same for (it = _freeArrayStartSpace.rbegin(); it != _freeArrayStartSpace.rend(); ++it) { size_t start = it->first; size_t end = it->second; size_t space = end - start + 1; if (space < arraySize) { continue; } std::set<size_t>::const_iterator itBlack = blackList.lower_bound(start); if (itBlack != blackList.end() && *itBlack <= end) { continue; // cannot use this space } //possible candidate if (itBestFit == _freeArrayStartSpace.rend()) { itBestFit = it; } else { size_t bestSpace = itBestFit->second - itBestFit->first + 1; size_t commonVals = 0; for (size_t i = 0; i < arraySize; i++) { if (isSameArrayElement(_tmpArrayValues[start + i], args[i])) { commonVals++; } } if (space < bestSpace || commonVals > bestCommonValues) { // better fit itBestFit = it; bestCommonValues = commonVals; if (bestCommonValues == arraySize) { break; // jackpot } } } } size_t bestStart = std::numeric_limits<size_t>::max(); if (itBestFit != _freeArrayStartSpace.rend()) { /** * Use available space */ bestStart = itBestFit->first; size_t bestEnd = itBestFit->second; size_t bestSpace = bestEnd - bestStart + 1; _freeArrayStartSpace.erase(bestStart); if (bestSpace == arraySize) { // entire space _freeArrayEndSpace.erase(bestEnd); } else { // some space left size_t newFreeStart = bestStart + arraySize; _freeArrayStartSpace[newFreeStart] = bestEnd; _freeArrayEndSpace.at(bestEnd) = newFreeStart; } } else { /** * no space available, need more */ // check if there is some free space at the end std::map<size_t, size_t>::iterator itEnd; itEnd = _freeArrayEndSpace.find(_idArrayCount - 1 - 1); // IDcount - initialID - 1 if (itEnd != _freeArrayEndSpace.end()) { // check if it can be used size_t lastSpotStart = itEnd->second; size_t lastSpotEnd = itEnd->first; size_t lastSpotSize = lastSpotEnd - lastSpotStart + 1; std::set<size_t>::const_iterator itBlack = blackList.lower_bound(lastSpotStart); if (itBlack == blackList.end()) { // can use this space _freeArrayEndSpace.erase(itEnd); _freeArrayStartSpace.erase(lastSpotStart); _idArrayCount += arraySize - lastSpotSize; bestStart = lastSpotStart; } } if (bestStart == std::numeric_limits<size_t>::max()) { // brand new space size_t id = _idArrayCount; _idArrayCount += arraySize; bestStart = id - 1; } } for (size_t i = 0; i < arraySize; i++) { _tmpArrayValues[bestStart + i] = &args[i]; } CPPADCG_ASSERT_UNKNOWN(_freeArrayStartSpace.size() == _freeArrayEndSpace.size()); return bestStart; }