/** @brief Annotes unoriented tree nodes \a tr with their subtree size * * This function recursively updates the subtree size of each inner node. * @note The subtree size of node \a p->number is the number of nodes included in the subtree where node record \a p is the virtual root. * * @param p * Pointer to node * * @param maxTips * Number of tips in the tree * * @param rvec * Recomputation info * * @param count * Number of visited nodes */ void computeTraversalInfoStlen(nodeptr p, int maxTips, recompVectors *rvec, int *count) { if(isTip(p->number, maxTips)) return; else { nodeptr q = p->next->back, r = p->next->next->back; *count += 1; /* set xnode info at this point */ if(isTip(r->number, maxTips) && isTip(q->number, maxTips)) { rvec->stlen[p->number - maxTips - 1] = 2; #ifdef _DEBUG_RECOMPUTATION assert(rvec->stlen[p->number - maxTips - 1] == subtreeSize(p, maxTips)); #endif } else { if(isTip(r->number, maxTips) || isTip(q->number, maxTips)) { nodeptr tmp; if(isTip(r->number, maxTips)) { tmp = r; r = q; q = tmp; } if(!r->x) computeTraversalInfoStlen(r, maxTips, rvec, count); rvec->stlen[p->number - maxTips - 1] = rvec->stlen[r->number - maxTips - 1] + 1; #ifdef _DEBUG_RECOMPUTATION assert(rvec->stlen[p->number - maxTips - 1] == subtreeSize(p, maxTips)); #endif } else { if(!r->x) computeTraversalInfoStlen(r, maxTips, rvec, count); if(!q->x) computeTraversalInfoStlen(q, maxTips, rvec, count); rvec->stlen[p->number - maxTips - 1] = rvec->stlen[q->number - maxTips - 1] + rvec->stlen[r->number - maxTips - 1]; #ifdef _DEBUG_RECOMPUTATION assert(rvec->stlen[p->number - maxTips - 1] == subtreeSize(p, maxTips)); #endif } } } }
static int subtreeSize(nodeptr p, int maxTips) { if(isTip(p->number, maxTips)) return 1; else return (subtreeSize(p->next->back, maxTips) + subtreeSize(p->next->next->back, maxTips)); }
unsigned subtreeSize(struct NHXnode *n) /* Count the number of nodes in subtree rooted at n */ { if (n == NULL) { return 0; } else { return 1 + subtreeSize(n->left) + subtreeSize(n->right); } }
/** @brief Annotes all tree nodes \a tr with their subtree size * * Similar to \a computeTraversalInfoStlen, but does a full traversal ignoring orientation. * The minum cost is defined as the minimum subtree size. In general, the closer a vector is to the tips, * the less recomputations are required to re-establish its likelihood entries * * @param p * Pointer to node * * @param maxTips * Number of tips in the tree * * @param rvec * Recomputation info */ void computeFullTraversalInfoStlen(nodeptr p, int maxTips, recompVectors *rvec) { if(isTip(p->number, maxTips)) return; else { nodeptr q = p->next->back, r = p->next->next->back; if(isTip(r->number, maxTips) && isTip(q->number, maxTips)) { rvec->stlen[p->number - maxTips - 1] = 2; #ifdef _DEBUG_RECOMPUTATION assert(rvec->stlen[p->number - maxTips - 1] == subtreeSize(p, maxTips)); #endif } else { if(isTip(r->number, maxTips) || isTip(q->number, maxTips)) { nodeptr tmp; if(isTip(r->number, maxTips)) { tmp = r; r = q; q = tmp; } computeFullTraversalInfoStlen(r, maxTips, rvec); rvec->stlen[p->number - maxTips - 1] = rvec->stlen[r->number - maxTips - 1] + 1; #ifdef _DEBUG_RECOMPUTATION assert(rvec->stlen[p->number - maxTips - 1] == subtreeSize(p, maxTips)); #endif } else { computeFullTraversalInfoStlen(r, maxTips, rvec); computeFullTraversalInfoStlen(q, maxTips, rvec); rvec->stlen[p->number - maxTips - 1] = rvec->stlen[q->number - maxTips - 1] + rvec->stlen[r->number - maxTips - 1]; #ifdef _DEBUG_RECOMPUTATION assert(rvec->stlen[p->number - maxTips - 1] == subtreeSize(p, maxTips)); #endif } } } }
unsigned treeSize(const struct NHXtree *tree) { struct NHXnode *r = 0; if (tree == 0) { return 0; } r = tree->root; if (r == 0) { return 0; } else { return subtreeSize(r); } }