int ANode::distance(ANode* anc, ANode* desc) { int distance = 0; for (ANode* x = desc; x != NULL; x = x->parent()) { if (x == anc) { return distance; } ++distance; } // If we arrive here, there was no path between 'anc' and 'desc' return -1; }
ANode* ANode::leastCommonAncestor(ANode* n1, ANode* n2) { // Collect all ancestors of n1 and n2. The root will be at the front // of the ancestor list. ANodeList anc1, anc2; for (ANode* a = n1->parent(); (a); a = a->parent()) { anc1.push_front(a); } for (ANode* a = n2->parent(); (a); a = a->parent()) { anc2.push_front(a); } // Find the most deeply nested common ancestor ANode* lca = NULL; while ( (!anc1.empty() && !anc2.empty()) && (anc1.front() == anc2.front())) { lca = anc1.front(); anc1.pop_front(); anc2.pop_front(); } return lca; }
bool ANode::mergePaths(ANode* lca, ANode* node_dst, ANode* node_src) { bool merged = false; // Should we verify that lca is really the lca? // Collect nodes along the paths 'lca' --> 'node_dst', 'node_src'. // Exclude 'lca'. Shallowest nodes are at beginning of list. ANodeList path_dst, path_src; for (ANode* x = node_dst; x != lca; x = x->parent()) { path_dst.push_front(x); } for (ANode* x = node_src; x != lca; x = x->parent()) { path_src.push_front(x); } DIAG_Assert(path_dst.size() > 0 && path_src.size() > 0, ""); // Merge nodes in 'path_src' into 'path_dst', shallowest to deepest, // exiting as soon as a merge fails ANodeList::iterator it_dst = path_dst.begin(); ANodeList::iterator it_src = path_src.begin(); for ( ; (it_dst != path_dst.end() && it_src != path_src.end()); ++it_src, ++it_dst) { ANode* x_src = *it_src; ANode* x_dst = *it_dst; if (isMergable(x_dst, x_src)) { merged |= merge(x_dst, x_src); } else { break; // done } } return merged; }
void ANode::aggregateMetrics(uint mBegId, uint mEndId) { if ( !(mBegId < mEndId) ) { return; // short circuit } const ANode* root = this; ANodeIterator it(root, NULL/*filter*/, false/*leavesOnly*/, IteratorStack::PostOrder); for (ANode* n = NULL; (n = it.current()); ++it) { ANode* n_parent = n->parent(); if (n != root) { for (uint mId = mBegId; mId < mEndId; ++mId) { double mVal = n->demandMetric(mId, mEndId/*size*/); n_parent->demandMetric(mId, mEndId/*size*/) += mVal; } } } }
bool ANode::arePathsOverlapping(ANode* lca, ANode* desc1, ANode* desc2) { // Ensure that d1 is on the longest path ANode* d1 = desc1, *d2 = desc2; int dist1 = distance(lca, d1); int dist2 = distance(lca, d2); if (dist2 > dist1) { ANode* t = d1; d1 = d2; d2 = t; } // Iterate over the longest path (d1 -> lca) searching for d2. Stop // when x is NULL or lca. for (ANode* x = d1; (x && x != lca); x = x->parent()) { if (x == d2) { return true; } } // If we arrive here, we did not encounter d2. Divergent. return false; }
int ANodeSortedIterator::cmpByStructureInfo(const void* a, const void* b) { ANode* x = (*(ANode**)a); ANode* y = (*(ANode**)b); if (x && y) { // 0. test for equality if (x == y) { return 0; } // INVARIANT: x != y, so never return 0 // 1. distinguish by structure ids uint x_id = x->structureId(); uint y_id = y->structureId(); int cmp_sid = cmp(x_id, y_id); if (cmp_sid != 0) { return cmp_sid; } // 2. distinguish by types int cmp_ty = (int)x->type() - (int)y->type(); if (cmp_ty != 0) { return cmp_ty; } // 3. distinguish by dynamic info (unnormalized CCTs) // (for determinism, ensure x and y are both ADynNodes) ADynNode* x_dyn = dynamic_cast<ADynNode*>(x); ADynNode* y_dyn = dynamic_cast<ADynNode*>(y); if (x_dyn && y_dyn) { int cmp_dyn = cmpByDynInfoSpecial(x_dyn, y_dyn); if (cmp_dyn != 0) { return cmp_dyn; } } // 5. distinguish by id int cmp_id = (int)x->id() - (int)y->id(); if (cmp_id != 0) { return cmp_id; } // 4. distinguish by tree context ANode* x_parent = x->parent(); ANode* y_parent = y->parent(); if (x_parent != y_parent) { int cmp_ctxt = cmpByStructureInfo(&x_parent, &y_parent); if (cmp_ctxt != 0) { return cmp_ctxt; } } // *. Could compare childCount() and other aspects of children. DIAG_Die("Prof::CCT::ANodeSortedIterator::cmpByStructureInfo: cannot compare:" << "\n\tx: " << x->toStringMe(Prof::CCT::Tree::OFlg_Debug) << "\n\ty: " << y->toStringMe(Prof::CCT::Tree::OFlg_Debug)); return 0; } else if (x) { return 1; // x > y=NULL (only used for recursive case) } else if (y) { return -1; // x=NULL < y (only used for recursive case) } else { DIAG_Die(DIAG_UnexpectedInput); } }