aboutsummaryrefslogtreecommitdiff
path: root/sys/libbio/phylo.c
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-04-28 16:32:06 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-04-28 16:32:06 -0700
commita48e7f9fd525b4da828605fb7be4d2a35dde4e23 (patch)
tree51b7def97deeaa70c8003225fabd2bb62a1101f4 /sys/libbio/phylo.c
parenta6d9c8be245ef171423ddeb8466a27ad715012e0 (diff)
feat: prototype of rerooting function
Diffstat (limited to 'sys/libbio/phylo.c')
-rw-r--r--sys/libbio/phylo.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/sys/libbio/phylo.c b/sys/libbio/phylo.c
index 316537c..4a4bcb1 100644
--- a/sys/libbio/phylo.c
+++ b/sys/libbio/phylo.c
@@ -146,3 +146,62 @@ phylo·ladderize(bio·Node *root)
return 0;
}
+
+static
+error
+rotateparent(bio·Node *node, bio·Node *to)
+{
+ error err;
+ bio·Node *it, *prev;
+
+ if (node->parent == to) {
+ return 0;
+ }
+
+ prev = nil;
+ for (it = node->child; it != nil; it = it->sibling) {
+ if (it == to) goto FOUND;
+ prev = it;
+ }
+ errorf("inconsistent topology: attempting to rotate to non-child");
+ return 1;
+
+FOUND:
+ if (err = rotateparent(node->parent, node), err) {
+ errorf("failure: broken tree");
+ return err;
+ }
+
+ if (!prev) {
+ node->child = node->parent;
+ } else {
+ prev->sibling = node->parent;
+ }
+ node->parent->sibling = it->sibling;
+ node->parent = to;
+
+ return 0;
+}
+
+#define FLOAT_PREC .00000001
+error
+phylo·reroot(bio·Tree *tree, bio·Node *node, double d)
+{
+ bio·Node *old;
+ bio·Node *new;
+
+ // TODO: should check that node is part of this tree?
+
+ old = tree->root;
+ if (fabs(d) < FLOAT_PREC) new = node;
+ if (fabs(d-node->dist) < FLOAT_PREC) new = node->parent;
+ else {
+ new = tree->heap.alloc(tree->h, 1, sizeof(*new));
+ memset(new, 0, sizeof(*new));
+ }
+
+ // TODO: Use rotateparent() to perform necessary flips
+
+ tree->root = new;
+ return 0;
+}