[Phylobase-commits] r615 - in pkg: R src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Thu Sep 3 01:47:30 CEST 2009


Author: regetz
Date: 2009-09-03 01:47:29 +0200 (Thu, 03 Sep 2009)
New Revision: 615

Added:
   pkg/src/descendants.c
Modified:
   pkg/R/treewalk.R
Log:
Reimplemented descendants() in C, leaving original R code commented out.


Modified: pkg/R/treewalk.R
===================================================================
--- pkg/R/treewalk.R	2009-09-02 22:52:59 UTC (rev 614)
+++ pkg/R/treewalk.R	2009-09-02 23:47:29 UTC (rev 615)
@@ -66,21 +66,54 @@
 {
     ## FIXME: allow vector of nodes? (or just let people lapply?)
     type <- match.arg(type)
-    if (type=="children") return(children(phy,node))
-    node <- getNode(phy,node)
-    if (is.na(node)) stop("node ",node," not found in tree")
+    if (type=="children") {
+        return(children(phy, node))
+    }
+    node <- getNode(phy, node)
+    if (is.na(node)) stop("node ", node, " not found in tree")
     n <- nTips(phy)
-    if (node <= n) return(node)
-    l <- numeric()
-    d <- children(phy, node)
-    for (j in d) {
-        if (j <= n)
-          l <- c(l,j)
-        else if (type=="all") l <- c(l,j,
-                   descendants(phy,j,type="all"))
-        else l <- c(l, descendants(phy,j,type=type))
+    if (node <= n) {
+        return(node)
     }
-    return(getNode(phy,l))
+
+    ## edge matrix must be in preorder for the C function!
+    if (phy at order=="preorder") {
+        edge <- phy at edge
+    } else {
+        edge <- reorder(phy, order="preorder")@edge
+    }
+    ## deal with NA root node
+    edge[is.na(edge)] <- 0
+    ## extract edge columns
+    ancestor <- as.integer(edge[, 1])
+    descendant <- as.integer(edge[, 2])
+    ## create indicator vector and seed it based on children
+    isChild <- rep(0L, length=nrow(edge))
+    isChild[ancestor==node] <- 1L
+    numEdges <- as.integer(length(isChild))
+
+    ## returned value of isChild will indicate *all* descendants 
+    isDescendant <- .C("descendants", isChild, ancestor, descendant,
+        numEdges)[[1]]
+
+    l <- descendant[as.logical(isDescendant)]
+    if (type=="tips") {
+        l <- l[l<=n]
+    }
+
+    ## Original pure R implementation of the above
+    ## (note that it does not require preorder ordering)
+    ##l <- numeric()
+    ##d <- children(phy, node)
+    ##for (j in d) {
+    ##    if (j <= n)
+    ##      l <- c(l,j)
+    ##    else if (type=="all") l <- c(l,j,
+    ##               descendants(phy,j,type="all"))
+    ##    else l <- c(l, descendants(phy,j,type=type))
+    ##}
+
+    return(getNode(phy, l))
 }
 
 siblings <- function(phy, node, include.self=FALSE) {

Added: pkg/src/descendants.c
===================================================================
--- pkg/src/descendants.c	                        (rev 0)
+++ pkg/src/descendants.c	2009-09-02 23:47:29 UTC (rev 615)
@@ -0,0 +1,24 @@
+/*
+  descendants.c:
+    Identify all descendants of a given node. Function inputs are
+  derived from a phylo4 edge matrix, which *must* be in preorder order.
+  The isDescendant input vector should contain 1 for the immediate
+  children of the node, and 0 otherwise. The function returns this
+  vector updated to include all further descendants.
+*/
+
+#include <R.h>
+
+void descendants(int *isDescendant, int *ancestor, int *descendant, 
+    int *numEdges) {
+
+    int child=0;
+    for (int i=0; i<*numEdges; i++) {
+        if (isDescendant[i]==1) {
+            child = descendant[i];
+            for (int j=i+1; j<*numEdges; j++) {
+                if (ancestor[j]==child) isDescendant[j]=1; 
+            }
+        }
+    }
+}


Property changes on: pkg/src/descendants.c
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Phylobase-commits mailing list