lib/rangeTree.c

Go to the documentation of this file.
00001 /* rangeTree - This module is a way of keeping track of
00002  * non-overlapping ranges (half-open intervals). It is
00003  * based on the self-balancing rbTree code.  Use it in
00004  * place of a bitmap when the total number of ranges
00005  * is significantly smaller than the number of bits would
00006  * be. */
00007 
00008 #include "common.h"
00009 #include "localmem.h"
00010 #include "rbTree.h"
00011 #include "rangeTree.h"
00012 
00013 int rangeCmp(void *va, void *vb)
00014 /* Return -1 if a before b,  0 if a and b overlap,
00015  * and 1 if a after b. */
00016 {
00017 struct range *a = va;
00018 struct range *b = vb;
00019 if (a->end <= b->start)
00020     return -1;
00021 else if (b->end <= a->start)
00022     return 1;
00023 else
00024     return 0;
00025 }
00026 
00027 struct range *rangeTreeAdd(struct rbTree *tree, int start, int end)
00028 /* Add range to tree, merging with existing ranges if need be. */
00029 {
00030 struct range tempR, *existing;
00031 tempR.start = start;
00032 tempR.end = end;
00033 tempR.val = NULL;
00034 while ((existing = rbTreeRemove(tree, &tempR)) != NULL)
00035      {
00036      tempR.start = min(tempR.start, existing->start);
00037      tempR.end = max(tempR.end, existing->end);
00038      }
00039 struct range *r = lmCloneMem(tree->lm, &tempR, sizeof(tempR));
00040 rbTreeAdd(tree, r);
00041 return r;
00042 }
00043 
00044 boolean rangeTreeOverlaps(struct rbTree *tree, int start, int end)
00045 /* Return TRUE if start-end overlaps anything in tree */
00046 {
00047 struct range tempR;
00048 tempR.start = start;
00049 tempR.end = end;
00050 tempR.val = NULL;
00051 return rbTreeFind(tree, &tempR) != NULL;
00052 }
00053 
00054 static struct range *rangeList;
00055 
00056 static void rangeListAdd(void *v)
00057 /* Callback to add item to range list. */
00058 {
00059 struct range *r = v;
00060 slAddHead(&rangeList, r);
00061 }
00062 
00063 struct range *rangeTreeList(struct rbTree *tree)
00064 /* Return list of all ranges in tree in order.  Not thread safe. 
00065  * No need to free this when done, memory is local to tree. */
00066 {
00067 rangeList = NULL;
00068 rbTreeTraverse(tree, rangeListAdd);
00069 slReverse(&rangeList);
00070 return rangeList;
00071 }
00072 
00073 struct range *rangeTreeFindEnclosing(struct rbTree *tree, int start, int end)
00074 /* Find item in range tree that encloses range between start and end 
00075  * if there is any such item. */
00076 {
00077 struct range tempR, *r;
00078 tempR.start = start;
00079 tempR.end = end;
00080 r = rbTreeFind(tree, &tempR);
00081 if (r != NULL && r->start <= start && r->end >= end)
00082     return r;
00083 return NULL;
00084 }
00085 
00086 struct range *rangeTreeAllOverlapping(struct rbTree *tree, int start, int end)
00087 /* Return list of all items in range tree that overlap interval start-end.
00088  * Do not free this list, it is owned by tree.  However it is only good until
00089  * next call to rangeTreeFindInRange or rangTreeList. Not thread safe. */
00090 {
00091 struct range tempR;
00092 tempR.start = start;
00093 tempR.end = end;
00094 rangeList = NULL;
00095 rbTreeTraverseRange(tree, &tempR, &tempR, rangeListAdd);
00096 slReverse(&rangeList);
00097 return rangeList;
00098 }
00099 
00100 /* A couple of variables used to calculate total overlap. */
00101 static int totalOverlap;
00102 static int overlapStart, overlapEnd;
00103 
00104 static void addOverlap(void *v)
00105 /* Callback to add item to range list. */
00106 {
00107 struct range *r = v;
00108 totalOverlap += positiveRangeIntersection(r->start, r->end, 
00109         overlapStart, overlapEnd);
00110 }
00111 
00112 int rangeTreeOverlapSize(struct rbTree *tree, int start, int end)
00113 /* Return the total size of intersection between interval
00114  * from start to end, and items in range tree. Sadly not
00115  * thread-safe. */
00116 {
00117 struct range tempR;
00118 tempR.start = overlapStart = start;
00119 tempR.end = overlapEnd = end;
00120 totalOverlap = 0;
00121 rbTreeTraverseRange(tree, &tempR, &tempR, addOverlap);
00122 return totalOverlap;
00123 }
00124 
00125 
00126 struct rbTree *rangeTreeNew()
00127 /* Create a new, empty, rangeTree. */
00128 {
00129 return rbTreeNew(rangeCmp);
00130 }
00131 
00132 struct rbTree *rangeTreeNewDetailed(struct lm *lm, struct rbTreeNode *stack[128])
00133 /* Allocate rangeTree on an existing local memory & stack.  This is for cases
00134  * where you want a lot of trees, and don't want the overhead for each one. 
00135  * Note, to clean these up, just do freez(&rbTree) rather than rbFreeTree(&rbTree). */
00136 {
00137 return rbTreeNewDetailed(rangeCmp, lm, stack);
00138 }
00139 

Generated on Tue Dec 25 18:39:31 2007 for blat by  doxygen 1.5.2