From 05275bbe5a14a0c05d6131948baa5064248a096c Mon Sep 17 00:00:00 2001 From: Sears Russell Date: Wed, 24 Jan 2007 18:25:38 +0000 Subject: [PATCH] Tracks ranges in O(m log n) time. --- src/lladd/io/rangeTracker.c | 159 ++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/lladd/io/rangeTracker.c diff --git a/src/lladd/io/rangeTracker.c b/src/lladd/io/rangeTracker.c new file mode 100644 index 0000000..dcc451b --- /dev/null +++ b/src/lladd/io/rangeTracker.c @@ -0,0 +1,159 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + + +struct rangeTracker { + struct RB_ENTRY(tree)* ranges; + int quantization; +}; + +static int cmp_transition(const void * a, const void * b, const void * arg) { + const transition * ta = a; + const transition * tb = b; + + return ta->pos - tb->pos; + +} + +rangeTracker * rangeTrackerInit(int quantization) { + rangeTracker * ret = malloc(sizeof(rangeTracker)); + ret->ranges = RB_ENTRY(init)(cmp_transition, 0); + ret->quantization = quantization; + return ret; +} + +void rangeTrackerDeinit(rangeTracker * rt) { + RB_ENTRY(destroy)(rt->ranges); + free(rt); +} + +static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) { + + assert(delta); // Otherwise, we'd be a no-op... + + /** Find predecessor of range */ + transition key; + int curpin; + key.pos = r->start; + // Discarding const. + transition * t = (transition *)RB_ENTRY(lookup)(RB_LULTEQ, &key, rt->ranges); + + if(t) { + if(t->pos != r->start) { + int newpins = t->pins + t->delta; + t = malloc(sizeof(transition)); + t->pos = r->start; + t->delta = delta; + t->pins = newpins; + RB_ENTRY(search)(t, rt->ranges); // insert + curpin = t->pins + t->delta; + } else { + t->delta += delta; + curpin = t->pins + t->delta; + if(t->delta == 0) { + RB_ENTRY(delete)(t, rt->ranges); + key.pos = t->pos; + free(t); + t = 0; + t = &key; + } + } + } else { + t = malloc(sizeof(transition)); + t->pos = r->start; + t->delta = delta; + t->pins = 0; + RB_ENTRY(search)(t, rt->ranges); // insert + curpin = t->pins + t->delta; + } + + // t is now set; iterate over the tree until we reach a transition + // with a >= pos. Increment each intermediate transition; allocate + // ranges as necessary. + + // libredblack does not provide a traversal function that starts at + // a particular point in the tree... + + // Discarding const. + while((t = (transition *) rblookup(RB_LUGREAT, t, rt->ranges)) && t->pos < r->end) { + assert(t); + t->pins += delta; + assert(t->delta); + assert(t->pins == curpin); + curpin = t->pins + t->delta; + } + if(!t || t->pos != r->end) { + // Need to allocate new transition + t = malloc(sizeof(transition)); + t->pos = r->end; + t->delta = 0-delta; + t->pins = curpin; + RB_ENTRY(search)(t, rt->ranges); // insert + } else { + // Found existing transition at end of range. + + assert(t->pos == r->end); + t->pins += delta; + assert(t->pins == curpin); + t->delta -= delta; + + if(t->delta == 0) { + RB_ENTRY(delete)(t, rt->ranges); + free(t); + } + } +} + +range ** rangeTrackerAdd(rangeTracker * rt, const range * r) { + rangeTrackerDelta(rt, r, 1); +} + +/** + Remove a range + @return a null terminated array of newly-unpinned, quantized ranges +*/ + +range ** rangeTrackerRemove(rangeTracker * rt, const range * r) { + rangeTrackerDelta(rt, r, -1); +} + +const transition ** enumTransitions(rangeTracker * rt) { + int transitionCount = 0; + const transition * t; + RBLIST * list = RB_ENTRY(openlist) (rt->ranges); + while((t = RB_ENTRY(readlist)(list))) { + transitionCount++; + } + RB_ENTRY(closelist)(list); + + const transition ** ret = malloc(sizeof(transition **) * (transitionCount + 1)); + + list = RB_ENTRY(openlist) (rt->ranges); + int i = 0; + + while((t = RB_ENTRY(readlist)(list))) { + ret[i] = t; + i++; + } + ret[i] = 0; + RB_ENTRY(closelist)(list); + return ret; +} + +char * rangeToString(const range * r) { + char * ret; + int err = asprintf(&ret, "[range %lld-%lld]", (long long)r->start, (long long)r->end); + assert(err !=-1); + return ret; +} + +char * transitionToString(const transition * t) { + char * ret; + int err = asprintf(&ret, "[transition pos=%lld delta=%d pins=%d]", (long long)t->pos, t->delta, t->pins); + assert(err !=-1); + return ret; +}