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();
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);
197 inline void addLinkedEquationsByNonIndexed(EquationPattern<Base>* eq1,
198 EquationPattern<Base>* eq2) {
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_;
221 inline LoopModel<Base>* releaseLoopModel() {
222 LoopModel<Base>* loopAtomic = loopModel_;
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)
246 g.equations.insert(
og.equations.begin(),
og.equations.end());
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++) {
324 const std::set<size_t>&
refItDep = group.iterationDependents[group.refIteration];
325 CPPADCG_ASSERT_UNKNOWN(
refItDep.size() == group.equations.size())
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();
401 for (
size_t g = 0;
g < eqGroups_.size();
g++) {
404 const std::vector<set<size_t> >& linkedDependents = group.linkedDependents;
411 size_t eqo_size = equationOrder_.size();
418 dependents.insert(
eq->dependents.begin(),
eq->dependents.end());
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);
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);
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);
634 const OperationNode<Base>* operation = it.first;
635 const OperationIndexedIndependents<Base>& opInd = it.second;
637 auto* arg2orderPos =
new OperationArgumentsIndepOrder<Base>();
638 op2Arg2IndepOrder_[operation] = arg2orderPos;
640 arg2IndepOrder_.push_front(arg2orderPos);
643 size_t aSize = opInd.arg2Independents.size();
644 for (
size_t argumentIndex = 0; argumentIndex < aSize; argumentIndex++) {
645 const std::map<size_t, const OperationNode<Base>*>& dep2Indep = opInd.arg2Independents[argumentIndex];
646 if (dep2Indep.empty())
649 std::vector<const OperationNode<Base>*> order(iterationCount_);
654 CPPADCG_ASSERT_UNKNOWN(dep2Indep.size() > 0 && dep2Indep.size() <= iterationCount_)
655 for (
const auto& itDep2Indep : dep2Indep) {
656 size_t iterationIndex = itDep2Indep.first;
657 const OperationNode<Base>* indep = itDep2Indep.second;
659 order[iterationIndex] = indep;
665 std::vector<IndependentOrder<Base>*>& availableOrders = firstIndep2orders_[order[0]];
666 IndependentOrder<Base>* match =
nullptr;
668 long a_size = availableOrders.size();
669 for (
long o = 0; o < a_size; o++) {
670 IndependentOrder<Base>* orderO = availableOrders[o];
672 for (
size_t iterationIndex = 0; iterationIndex < iterationCount_; iterationIndex++) {
673 if (orderO->order[iterationIndex] != order[iterationIndex]) {
684 if (match !=
nullptr) {
686 arg2orderPos->arg2Order[argumentIndex] = match;
689 auto* iOrder =
new IndependentOrder<Base>(order);
690 availableOrders.push_back(iOrder);
691 arg2orderPos->arg2Order[argumentIndex] = iOrder;
707 void createLoopTapeNModel(
const std::vector<CG<Base> >& dependents,
708 const std::vector<CG<Base> >& independents,
709 const std::map<
size_t, EquationPattern<Base>*>& dep2Equation,
710 std::map<OperationNode<Base>*,
size_t>& origTemp2Index) {
711 using CGB = CG<Base>;
712 using ADCGB = AD<CGB>;
713 CPPADCG_ASSERT_UNKNOWN(independents.size() > 0)
714 CPPADCG_ASSERT_UNKNOWN(independents[0].getCodeHandler() !=
nullptr)
715 CodeHandler<Base>& origHandler = *independents[0].getCodeHandler();
723 CPPADCG_ASSERT_UNKNOWN(equationOrder_.size() ==
equations.size())
727 for (
size_t g = 0; g < eqGroups_.size(); g++) {
728 const EquationGroup<Base>& group = eqGroups_[g];
729 const std::set<size_t>& iterationDependents = group.iterationDependents[group.refIteration];
731 for (
size_t depIndex : iterationDependents) {
732 EquationPattern<Base>* eq = dep2Equation.at(depIndex);
733 OperationNode<Base>* node = dependents[depIndex].getOperationNode();
735 Argument<Base> aClone;
737 if (node !=
nullptr) {
738 if (node->getOperationType() == CGOpCode::Inv) {
739 aClone = createIndependentClone(
nullptr, 0, *node);
741 aClone = makeGraphClones(*eq, *node);
744 aClone = dependents[depIndex].getValue();
747 size_t i = equationOrder_.at(eq);
748 deps[i] = CGB(aClone);
756 CPPADCG_ASSERT_UNKNOWN(indexedIndep2clone_.size() == independentsIndexed_.size());
758 std::vector<const OperationNode<Base>*> indexedCloneOrder;
759 indexedCloneOrder.reserve(indexedIndep2clone_.size());
761 std::map<const OperationNode<Base>*,
const IndependentOrder<Base>*> clone2indexedIndep;
762 for (
const auto& it : indexedIndep2clone_) {
763 clone2indexedIndep[it.second] = it.first;
764 indexedCloneOrder.push_back(it.second);
767 struct IndexedIndepSorter indexedSorter(clone2indexedIndep);
768 std::sort(indexedCloneOrder.begin(), indexedCloneOrder.end(), indexedSorter);
771 std::map<size_t, const OperationNode<Base>*> nonIndexedCloneOrder;
774 std::map<const OperationNode<Base>*,
const OperationNode<Base>*> clones2ConstIndep;
776 for (
auto itc = orig2ConstIndepClone_.begin(); itc != orig2ConstIndepClone_.end(); ++itc, s++) {
777 const OperationNode<Base>* orig = itc->first;
778 OperationNode<Base>* clone = itc->second;
780 size_t j = orig->getInfo()[0];
781 clones2ConstIndep[clone] = orig;
782 nonIndexedCloneOrder[j] = clone;
785 size_t nIndexed = indexedCloneOrder.size();
786 size_t nNonIndexed = nonIndexedCloneOrder.size();
787 size_t nTmpIndexed = independentsTemp_.size();
790 size_t nIndep = independentsIndexed_.size() +
791 independentsNonIndexed_.size() +
792 independentsTemp_.size();
793 std::vector<ADCGB> loopIndeps(nIndep);
795 typename std::map<const OperationNode<Base>*, IndexValue>::const_iterator itt;
796 typename std::map<size_t, const OperationNode<Base>*>::const_iterator origJ2CloneIt;
799 loopIndeps.resize(1);
800 loopIndeps[0] = Base(0);
807 for (
size_t j = 0; j < nIndexed; j++) {
808 const IndexValue& iv = independentsIndexed_.at(indexedCloneOrder[j]);
809 loopIndeps[j] = iv.second;
813 for (origJ2CloneIt = nonIndexedCloneOrder.begin(); origJ2CloneIt != nonIndexedCloneOrder.end(); ++origJ2CloneIt, s++) {
814 const IndexValue& iv = independentsNonIndexed_.at(origJ2CloneIt->second);
815 loopIndeps[nIndexed + s] = iv.second;
819 for (itt = independentsTemp_.begin(); itt != independentsTemp_.end(); ++itt, s++) {
820 const IndexValue& iv = itt->second;
821 loopIndeps[nIndexed + nNonIndexed + s] = iv.second;
833 std::vector<ADCGB> localIndeps(nIndep);
835 for (
size_t j = 0; j < nIndexed; j++) {
836 const IndexValue& iv = independentsIndexed_.at(indexedCloneOrder[j]);
837 size_t localIndex = iv.first;
838 localIndeps[localIndex] = loopIndeps[j];
842 for (origJ2CloneIt = nonIndexedCloneOrder.begin(); origJ2CloneIt != nonIndexedCloneOrder.end(); ++origJ2CloneIt, s++) {
843 size_t localIndex = independentsNonIndexed_.at(origJ2CloneIt->second).first;
844 localIndeps[localIndex] = loopIndeps[nIndexed + s];
848 for (itt = independentsTemp_.begin(); itt != independentsTemp_.end(); ++itt, s++) {
849 size_t localIndex = itt->second.first;
850 localIndeps[localIndex] = loopIndeps[nIndexed + nNonIndexed + s];
857 Evaluator<Base, CGB> evaluator1stIt(handler_);
860 const std::map<size_t, CGAbstractAtomicFun<Base>* >& atomicsOrig = origHandler.getAtomicFunctions();
861 std::map<size_t, atomic_base<CGB>* > atomics;
862 atomics.insert(atomicsOrig.begin(), atomicsOrig.end());
863 evaluator1stIt.addAtomicFunctions(atomics);
865 std::vector<ADCGB> newDeps = evaluator1stIt.evaluate(localIndeps, deps);
867 bool containsAtoms = evaluator1stIt.getNumberOfEvaluatedAtomics() > 0;
869 std::unique_ptr<ADFun<CGB> >funIndexed(
new ADFun<CGB>());
870 funIndexed->Dependent(newDeps);
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];
878 for (
size_t origDep : itDeps) {
879 EquationPattern<Base>* eq = dep2Equation.at(origDep);
880 size_t i = equationOrder_.at(eq);
881 dependentOrigIndexes[i][it] = origDep;
886 std::vector<std::vector<size_t> > indexedIndependents(nIndexed, std::vector<size_t>(iterationCount_));
887 for (
size_t j = 0; j < indexedCloneOrder.size(); j++) {
888 const IndependentOrder<Base>* origOrder = clone2indexedIndep.at(indexedCloneOrder[j]);
889 for (
size_t it = 0; it < iterationCount_; it++) {
890 const OperationNode<Base>* indep = origOrder->order[it];
892 if (indep !=
nullptr) {
893 index = indep->getInfo()[0];
895 index = (std::numeric_limits<size_t>::max)();
897 indexedIndependents[j][it] = index;
901 std::vector<size_t> temporaryIndependents(nTmpIndexed);
904 for (itt = independentsTemp_.begin(); itt != independentsTemp_.end(); ++itt, j++) {
905 const OperationNode<Base>* tmpClone = itt->first;
906 OperationNode<Base>* origTmpNode = temporaryClone2Orig_.at(tmpClone);
912 typename std::map<OperationNode<Base>*,
size_t>::const_iterator itz = origTemp2Index.find(origTmpNode);
913 if (itz == origTemp2Index.end()) {
914 k = origTemp2Index.size();
915 origTemp2Index[origTmpNode] = k;
920 temporaryIndependents[j] = k;
923 std::vector<size_t> nonIndexedIndependents(orig2ConstIndepClone_.size());
925 for (origJ2CloneIt = nonIndexedCloneOrder.begin(); origJ2CloneIt != nonIndexedCloneOrder.end(); ++origJ2CloneIt, s++) {
926 nonIndexedIndependents[s] = origJ2CloneIt->first;
929 loopModel_ =
new LoopModel<Base>(funIndexed.release(),
932 dependentOrigIndexes,
934 nonIndexedIndependents,
935 temporaryIndependents);
937 loopModel_->detectIndexPatterns();
940 inline Argument<Base> makeGraphClones(
const EquationPattern<Base>& eq,
941 OperationNode<Base>& node) {
943 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::Inv)
945 size_t id = (*varId_)[node];
949 return Argument<Base>(*clonesTemporary_.at(
id));
955 (*varId_)[node] = id;
957 if ((*varIndexed_)[node] || node.getOperationType() == CGOpCode::ArrayCreation) {
962 const std::vector<Argument<Base> >& args = node.getArguments();
963 size_t arg_size = args.size();
964 std::vector<Argument<Base> > cloneArgs(arg_size);
966 for (
size_t a = 0; a < arg_size; a++) {
967 OperationNode<Base>* argOp = args[a].getOperation();
968 if (argOp ==
nullptr) {
970 cloneArgs[a] = *args[a].getParameter();
973 if (argOp->getOperationType() == CGOpCode::Inv) {
974 cloneArgs[a] = createIndependentClone(&node, a, *argOp);
976 cloneArgs[a] = makeGraphClones(eq, *argOp);
981 OperationNode<Base>* cloneOp = handler_.makeNode(node.getOperationType(),
985 clonesTemporary_[id] = cloneOp;
986 return Argument<Base>(*cloneOp);
993 return makeTemporaryVarClone(node);
997 inline OperationNode<Base>& createIndependentClone(OperationNode<Base>* operation,
998 size_t argumentIndex,
999 OperationNode<Base>& independent) {
1002 typename std::map<const OperationNode<Base>*, OperationIndexedIndependents<Base> >::const_iterator it =
indexedOpIndep.op2Arguments.find(operation);
1004 const OperationIndexedIndependents<Base>& yyy = it->second;
1006 if (!yyy.arg2Independents[argumentIndex].empty()) {
1008 return getIndexedIndependentClone(operation, argumentIndex);
1013 return getNonIndexedIndependentClone(independent);
1016 OperationNode<Base>& getIndexedIndependentClone(
const OperationNode<Base>* operation,
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)
1022 OperationArgumentsIndepOrder<Base>* args2Order = op2Arg2IndepOrder_.at(operation);
1023 IndependentOrder<Base>* indepOrder = args2Order->arg2Order.at(argIndex);
1025 typename std::map<const IndependentOrder<Base>*, OperationNode<Base>*>::const_iterator it;
1026 it = indexedIndep2clone_.find(indepOrder);
1027 if (it != indexedIndep2clone_.end()) {
1031 handler_.makeVariable(newIndep);
1032 independentsIndexed_[newIndep.getOperationNode()] = IndexValue(nIndependents_, newIndep);
1035 OperationNode<Base>* clone = newIndep.getOperationNode();
1036 indexedIndep2clone_[indepOrder] = clone;
1041 OperationNode<Base>& getNonIndexedIndependentClone(
const OperationNode<Base>& node) {
1042 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() == CGOpCode::Inv)
1044 typename std::map<const OperationNode<Base>*, OperationNode<Base>*>::iterator it;
1045 it = orig2ConstIndepClone_.find(&node);
1046 if (it != orig2ConstIndepClone_.end()) {
1051 handler_.makeVariable(newIndep);
1052 independentsNonIndexed_[newIndep.getOperationNode()] = IndexValue(nIndependents_, newIndep);
1055 OperationNode<Base>* clone = newIndep.getOperationNode();
1056 orig2ConstIndepClone_[&node] = clone;
1066 OperationNode<Base>& makeTemporaryVarClone(OperationNode<Base>& node) {
1067 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::Inv)
1068 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::ArrayCreation)
1069 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::SparseArrayCreation)
1072 handler_.makeVariable(newIndep);
1073 OperationNode<Base>* cloneOp = newIndep.getOperationNode();
1075 temporaryClone2Orig_[cloneOp] = &node;
1076 independentsTemp_[cloneOp] = IndexValue(nIndependents_, newIndep);
1079 size_t id = idCounter_++;
1080 clonesTemporary_[id] = cloneOp;
1081 (*varId_)[node] = id;
1089 class DependentIndexSorter {
1091 const EquationGroup<Base>& group;
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;
1097 inline DependentIndexSorter(
const EquationGroup<Base>& g,
1098 const std::map<EquationPattern<Base>*, std::vector<size_t> >& f,
1099 const std::map<
size_t, EquationPattern<Base>*>& d2e) :
1113 inline std::pair<size_t, EquationPattern<Base>*> findBestDependentForIteration(
size_t dep, EquationPattern<Base>* eq) {
1115 return findBestDependent(dep, eq);
1120 inline size_t findRelativeFreeDependentInEq(EquationPattern<Base>* eq,
size_t dep) {
1122 const std::vector<size_t>& eqFreeDep = freeDependents.at(eq);
1123 for (
size_t depRelPos = 0; depRelPos < eqFreeDep.size(); depRelPos++) {
1124 if (eqFreeDep[depRelPos] == dep)
1129 return eqFreeDep.size();
1139 inline std::pair<size_t, EquationPattern<Base>*> findBestDependent(
size_t dep, EquationPattern<Base>* eq) {
1140 visitedEq.insert(eq);
1142 auto best = std::make_pair(dep, eq);
1145 long pos = group.findIndexedLinkedDependent(dep);
1147 size_t depRelPos = findRelativeFreeDependentInEq(eq, dep);
1151 for (
size_t dep2 : group.linkedDependents[pos]) {
1152 EquationPattern<Base>* eq2 = dep2Equation.at(dep2);
1153 if (visitedEq.find(eq2) != visitedEq.end())
continue;
1155 size_t dep2RelPos = findRelativeFreeDependentInEq(eq2, dep2);
1156 if (dep2RelPos > depRelPos) {
1159 best = std::make_pair(dep2, eq2);
1160 depRelPos = dep2RelPos;
1164 if (best.first != dep) {
1165 size_t bestDep = *freeDependents.at(best.second).begin();
1166 return findBestDependent(bestDep, best.second);
1179 struct IndexedIndepSorter {
1180 const std::map<const OperationNode<Base>*,
const IndependentOrder<Base>*>& clone2indexedIndep;
1182 IndexedIndepSorter(
const std::map<
const OperationNode<Base>*,
const IndependentOrder<Base>*>& clone2indexedIndep_) :
1183 clone2indexedIndep(clone2indexedIndep_) {
1186 bool operator()(
const OperationNode<Base>* node1,
1187 const OperationNode<Base>* node2) {
1188 const IndependentOrder<Base>* indepOrder1 = clone2indexedIndep.at(node1);
1189 const IndependentOrder<Base>* indepOrder2 = clone2indexedIndep.at(node2);
1190 CPPADCG_ASSERT_UNKNOWN(indepOrder1->order.size() == indepOrder2->order.size())
1192 size_t size = indepOrder1->order.size();
1193 for (
size_t j = 0; j < size; j++) {
1194 const OperationNode<Base>* indep1 = indepOrder1->order[j];
1195 const OperationNode<Base>* indep2 = indepOrder2->order[j];
1197 if (indep1 ==
nullptr) {
1198 if (indep2 ==
nullptr) {
1202 }
else if (indep2 ==
nullptr) {
1206 size_t index1 = indep1->getInfo()[0];
1207 size_t index2 = indep2->getInfo()[0];
1208 if (index1 < index2)
1210 else if (index1 > index2)
1214 CPPADCG_ASSERT_UNKNOWN(
false)