54 using IndexValue = std::pair<size_t, CG<Base> >;
74 std::unique_ptr<CodeHandlerVector<Base, size_t>> varId_;
78 std::unique_ptr<CodeHandlerVector<Base, bool>> varIndexed_;
82 size_t iterationCount_;
90 std::vector<EquationGroup<Base> > eqGroups_;
94 std::map<EquationPattern<Base>*,
size_t> equationOrder_;
99 std::vector<std::set<size_t> > iterationDependents_;
103 std::map<size_t, size_t> dep2Iteration_;
107 size_t nIndependents_;
115 std::map<const OperationNode<Base>*, IndexValue> independentsIndexed_;
119 std::map<const OperationNode<Base>*, IndexValue> independentsNonIndexed_;
123 std::map<const OperationNode<Base>*, IndexValue> independentsTemp_;
127 std::map<size_t, OperationNode<Base>*> clonesTemporary_;
145 std::map<const OperationNode<Base>*, std::vector<IndependentOrder<Base>*> > firstIndep2orders_;
154 std::forward_list<OperationArgumentsIndepOrder<Base>*> arg2IndepOrder_;
162 handlerOrig_(
eq.depRef.getCodeHandler()),
173 eqGroups_[0].equations.insert(&
eq);
175 if(varId_ !=
nullptr)
176 varId_->adjustSize();
184 eqGroups_[0].equations.insert(&
eq);
187 inline void setLinkedDependents(
const std::set<std::set<size_t>*>&
newLoopRelations) {
188 CPPADCG_ASSERT_UNKNOWN(eqGroups_.size() == 1);
190 eqGroups_[0].linkedDependents.clear();
194 eqGroups_[0].linkedDependents.push_back(*
it);
199 eqGroups_[0].addLinkedEquationsByNonIndexed(eq1, eq2);
202 inline size_t getLinkedEquationsByNonIndexedCount()
const {
203 return eqGroups_[0].getLinkedEquationsByNonIndexedCount();
210 return iterationCount_;
213 const std::vector<std::set<size_t> >& getIterationDependents()
const {
214 return iterationDependents_;
217 inline LoopModel<Base>* getModel()
const {
221 inline LoopModel<Base>* releaseLoopModel() {
223 loopModel_ =
nullptr;
235 CPPADCG_ASSERT_UNKNOWN(iterationCount_ ==
other.iterationCount_)
239 other.equations.clear();
241 CPPADCG_ASSERT_UNKNOWN(eqGroups_.size() == 1)
242 CPPADCG_ASSERT_UNKNOWN(
other.eqGroups_.size() == 1)
248 CPPADCG_ASSERT_UNKNOWN(equationOrder_.empty())
249 CPPADCG_ASSERT_UNKNOWN(iterationDependents_.empty())
251 g.linkedEquationsByNonIndexed.insert(
og.linkedEquationsByNonIndexed.begin(),
og.linkedEquationsByNonIndexed.end());
263 eqGroups_.insert(eqGroups_.end(),
other.eqGroups_.begin(),
other.eqGroups_.end());
267 other.equations.clear();
272 for (
const auto&
it :
other.equationOrder_) {
273 equationOrder_[
it.first] =
it.second +
nEq;
276 CPPADCG_ASSERT_UNKNOWN(iterationDependents_.size() ==
other.iterationDependents_.size())
277 for (
size_t iter = 0;
iter < iterationDependents_.size();
iter++) {
278 iterationDependents_[
iter].insert(
other.iterationDependents_[
iter].begin(),
other.iterationDependents_[
iter].end());
288 CPPADCG_ASSERT_UNKNOWN(dep2Iteration_.empty())
290 const std::set<size_t>&
deps = iterationDependents_[
iter];
292 for (
size_t d :
deps) {
293 dep2Iteration_[
d] =
iter;
297 if(varIndexed_ !=
nullptr) {
298 varIndexed_->adjustSize();
299 varIndexed_->fill(
false);
305 for (
size_t g = 0;
g < eqGroups_.size();
g++) {
306 eqGroups_[
g].findReferenceIteration();
307#ifdef CPPADCG_PRINT_DEBUG
308 std::cout <<
"reference iteration=" << eqGroups_[
g].refIteration <<
"\n";
309 print(eqGroups_[
g].iterationDependents);
310 std::cout << std::endl;
312 typename std::set<EquationPattern<Base>*>::const_iterator
iteq;
314 std::cout <<
"eq dependents=";
315 print((*iteq)->dependents);
316 std::cout << std::endl;
322 for (
size_t g = 0;
g < eqGroups_.size();
g++) {
338 if (
dep ==
eq->depRefIndex) {
339 for (
const auto&
itop2a :
eq->indexedOpIndep.op2Arguments) {
343 CPPADCG_ASSERT_UNKNOWN(
itop2a.first !=
nullptr)
344 addOperationArguments2Loop(
itop2a.first,
itop2a.second);
353 CPPADCG_ASSERT_UNKNOWN(
opLoopRef !=
nullptr)
361 eq->indexedOpIndep.op2Arguments.clear();
368 generateIndependentLoopIndexes();
370 if(varId_ !=
nullptr)
378 if(varId_ !=
nullptr)
385 iterationDependents_.clear();
386 equationOrder_.clear();
392 map<EquationPattern<Base>*, set<size_t> >
depsInEq;
401 for (
size_t g = 0;
g < eqGroups_.size();
g++) {
403 const set<EquationPattern<Base>*>&
eqs = group.
equations;
411 size_t eqo_size = equationOrder_.size();
416 set<size_t> dependents;
418 dependents.insert(
eq->dependents.begin(),
eq->dependents.end());
424 map<EquationPattern<Base>*, std::vector<size_t> > freeDependents;
426 freeDependents[
eq].assign(
eq->dependents.begin(),
eq->dependents.end());
429 DependentIndexSorter
depSorter(group, freeDependents, dep2Equation);
431 auto itDep = dependents.begin();
433 while (
itDep != dependents.end()) {
437 if (iterationDependents_.size() <=
i)
438 iterationDependents_.resize(
i + 1);
439 set<size_t>&
itDepi = iterationDependents_[
i];
452 long pos = group.findIndexedLinkedDependent(
dep);
455 for (
size_t dep2 : linkedDependents[
pos]) {
459 dependents.erase(
dep2);
462 std::vector<size_t>&
eq2FreeDep = freeDependents[eq2];
463 typename std::vector<size_t>::const_iterator
itFreeDep2;
473 long posN = group.findNonIndexedLinkedRel(
eq);
476 dependents.erase(
dep);
482 std::vector<size_t>&
eqFreeDep = freeDependents[
eq];
510 std::vector<size_t>
deps;
539 set<size_t>::const_iterator
itIter;
557 if (iterationDependents_.size() <=
i)
558 iterationDependents_.resize(
i + 1);
559 set<size_t>&
itDepi = iterationDependents_[
i];
577 iterationCount_ = std::max<size_t>(iterationCount_, iterationDependents_.size());
586 for (
const auto&
itf : firstIndep2orders_) {
610 CPPADCG_ASSERT_UNKNOWN(!dep2Iteration_.empty());
622 size_t iter = dep2Iteration_.at(
dep);
629 void generateIndependentLoopIndexes() {
630 CPPADCG_ASSERT_UNKNOWN(iterationCount_ > 0);
644 for (
size_t argumentIndex = 0; argumentIndex <
aSize; argumentIndex++) {
645 const std::map<size_t, const OperationNode<Base>*>&
dep2Indep =
opInd.arg2Independents[argumentIndex];
649 std::vector<const OperationNode<Base>*> order(iterationCount_);
665 std::vector<IndependentOrder<Base>*>&
availableOrders = firstIndep2orders_[order[0]];
684 if (
match !=
nullptr) {
707 void createLoopTapeNModel(
const std::vector<CG<Base> >& dependents,
711 using CGB = CG<Base>;
714 CPPADCG_ASSERT_UNKNOWN(
independents[0].getCodeHandler() !=
nullptr)
723 CPPADCG_ASSERT_UNKNOWN(equationOrder_.size() ==
equations.size())
727 for (
size_t g = 0;
g < eqGroups_.size();
g++) {
729 const std::set<size_t>& iterationDependents = group.iterationDependents[group.refIteration];
731 for (
size_t depIndex : iterationDependents) {
737 if (node !=
nullptr) {
738 if (node->getOperationType() == CGOpCode::Inv) {
739 aClone = createIndependentClone(
nullptr, 0, *node);
741 aClone = makeGraphClones(*
eq, *node);
747 size_t i = equationOrder_.at(
eq);
756 CPPADCG_ASSERT_UNKNOWN(indexedIndep2clone_.size() == independentsIndexed_.size());
762 for (
const auto&
it : indexedIndep2clone_) {
763 clone2indexedIndep[
it.second] =
it.first;
776 for (
auto itc = orig2ConstIndepClone_.begin();
itc != orig2ConstIndepClone_.end(); ++
itc, s++) {
780 size_t j =
orig->getInfo()[0];
790 size_t nIndep = independentsIndexed_.size() +
791 independentsNonIndexed_.size() +
792 independentsTemp_.size();
795 typename std::map<const OperationNode<Base>*, IndexValue>::const_iterator
itt;
796 typename std::map<size_t, const OperationNode<Base>*>::const_iterator
origJ2CloneIt;
814 const IndexValue&
iv = independentsNonIndexed_.at(
origJ2CloneIt->second);
819 for (
itt = independentsTemp_.begin();
itt != independentsTemp_.end(); ++
itt, s++) {
820 const IndexValue&
iv =
itt->second;
848 for (
itt = independentsTemp_.begin();
itt != independentsTemp_.end(); ++
itt, s++) {
861 std::map<size_t, atomic_base<CGB>* >
atomics;
875 std::vector<std::vector<size_t> >
dependentOrigIndexes(
equations.size(), std::vector<size_t> (iterationCount_, (std::numeric_limits<size_t>::max)()));
876 for (
size_t it = 0;
it < iterationCount_;
it++) {
877 const std::set<size_t>&
itDeps = iterationDependents_[
it];
880 size_t i = equationOrder_.at(
eq);
889 for (
size_t it = 0;
it < iterationCount_;
it++) {
892 if (
indep !=
nullptr) {
893 index =
indep->getInfo()[0];
895 index = (std::numeric_limits<size_t>::max)();
904 for (
itt = independentsTemp_.begin();
itt != independentsTemp_.end(); ++
itt,
j++) {
929 loopModel_ =
new LoopModel<Base>(
funIndexed.release(),
937 loopModel_->detectIndexPatterns();
943 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::Inv)
945 size_t id = (*varId_)[node];
955 (*varId_)[node] =
id;
957 if ((*varIndexed_)[node] || node.getOperationType() == CGOpCode::ArrayCreation) {
962 const std::vector<Argument<Base> >&
args = node.getArguments();
968 if (
argOp ==
nullptr) {
973 if (
argOp->getOperationType() == CGOpCode::Inv) {
993 return makeTemporaryVarClone(node);
998 size_t argumentIndex,
1006 if (!
yyy.arg2Independents[argumentIndex].empty()) {
1008 return getIndexedIndependentClone(
operation, argumentIndex);
1013 return getNonIndexedIndependentClone(independent);
1018 CPPADCG_ASSERT_UNKNOWN(
operation ==
nullptr ||
operation->getArguments().size() > argIndex)
1019 CPPADCG_ASSERT_UNKNOWN(
operation ==
nullptr ||
operation->getArguments()[argIndex].getOperation() !=
nullptr)
1020 CPPADCG_ASSERT_UNKNOWN(
operation ==
nullptr ||
operation->getArguments()[argIndex].getOperation()->getOperationType() == CGOpCode::Inv)
1025 typename std::map<
const IndependentOrder<Base>*, OperationNode<Base>*>::const_iterator
it;
1027 if (
it != indexedIndep2clone_.end()) {
1032 independentsIndexed_[
newIndep.getOperationNode()] = IndexValue(nIndependents_,
newIndep);
1042 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() == CGOpCode::Inv)
1045 it = orig2ConstIndepClone_.find(&node);
1046 if (
it != orig2ConstIndepClone_.end()) {
1052 independentsNonIndexed_[
newIndep.getOperationNode()] = IndexValue(nIndependents_,
newIndep);
1056 orig2ConstIndepClone_[&node] =
clone;
1067 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::Inv)
1068 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::ArrayCreation)
1069 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::SparseArrayCreation)
1075 temporaryClone2Orig_[
cloneOp] = &node;
1079 size_t id = idCounter_++;
1081 (*varId_)[node] =
id;
1089 class DependentIndexSorter {
1092 const std::map<EquationPattern<Base>*, std::vector<size_t> >& freeDependents;
1093 const std::map<size_t, EquationPattern<Base>*>& dep2Equation;
1094 std::set<EquationPattern<Base>*> visitedEq;
1115 return findBestDependent(
dep,
eq);
1122 const std::vector<size_t>&
eqFreeDep = freeDependents.at(
eq);
1140 visitedEq.insert(
eq);
1145 long pos = group.findIndexedLinkedDependent(
dep);
1151 for (
size_t dep2 : group.linkedDependents[
pos]) {
1153 if (visitedEq.find(eq2) != visitedEq.end())
continue;
1165 size_t bestDep = *freeDependents.at(
best.second).begin();
1179 struct IndexedIndepSorter {
1193 for (
size_t j = 0;
j < size;
j++) {
1202 }
else if (
indep2 ==
nullptr) {
1214 CPPADCG_ASSERT_UNKNOWN(
false)