forceinline void ValSet::add(Space& home, int v) { RangeList* c = fst; RangeList** p = &fst; while (c != NULL) { if (v < c->min()) { if (v+1 == c->min()) { c->min(v); n++; return; } else { *p = new (home) RangeList(v,v,c); n++; return; } } else if (v <= c->max()) { // Value already included return; } else if (v == c->max()+1) { if ((c->next() != NULL) && (v+1 == c->next()->min())) { c->next()->min(c->min()); *p = c->next(); c->dispose(home,c); } else { c->max(v); } n++; return; } else { // FIXME: HOW TO CAST HERE? p = reinterpret_cast<RangeList**>(c->nextRef()); c = *p; } } *p = new (home) RangeList(v,v,NULL); n++; lst = *p; }
forceinline void IntTraceView::prune(Space& home, IntView y, const Delta& d) { if (y.range() && (dom->next() == NULL)) { dom->min(y.min()); dom->max(y.max()); } else if (!y.any(d) && (y.max(d)+1 == y.min())) { // The lower bound has been adjusted if (y.min() > dom->max()) { RangeList* p = dom; RangeList* l = p->next(); while ((l != NULL) && (l->max() < y.min())) { p=l; l=l->next(); } dom->dispose(home,p); dom = l; } dom->min(y.min()); } else if (!y.any(d) && (y.max()+1 == y.min(d))) { // upper bound has been adjusted if ((y.max() <= dom->max()) && (dom->next() == NULL)) { dom->max(y.max()); } else { RangeList* p = dom; RangeList* l = p->next(); while ((l != NULL) && (l->min() <= y.max())) { p=l; l=l->next(); } p->max(y.max()); if (p->next() != NULL) p->next()->dispose(home); p->next(NULL); } } else { // Just copy the domain ViewRanges<IntView> yr(y); RangeList::overwrite(home,dom,yr); } }
forceinline void ValSet::update(Space& home, bool share, ValSet& vs) { (void) share; if (vs.n > 0) { n = vs.n; // Count number of ranges int m = 0; for (RangeList* c = vs.fst; c != NULL; c = c->next()) m++; fst = home.alloc<RangeList>(m); lst = fst + (m-1); int i=0; for (RangeList* c = vs.fst; c != NULL; c = c->next()) { fst[i].min(c->min()); fst[i].max(c->max()); fst[i].next(fst+i+1); i++; } lst->next(NULL); } }
bool GLBndSet::include_full(Space& home, int mi, int ma, SetDelta& d) { assert(ma >= mi); assert(fst() != NULL); RangeList* p = NULL; RangeList* c = fst(); while (c != NULL) { if (c->max() >= mi-1){ if (c->min() > ma+1) { //in a hole before c _size+=(ma-mi+1); d._glbMin = mi; d._glbMax = ma; RangeList* q = new (home) RangeList(mi,ma,c); if (p==NULL) //the new range is the first fst(q); else p->next(q); return true; } //if the range starts before c, update c->min and size bool result = false; if (c->min()>mi) { _size+=(c->min()-mi); c->min(mi); d._glbMin = mi; result = true; } else { d._glbMin = c->max()+1; } assert(c->min()<=mi); assert(c->max()+1>=mi); if (c->max() >= ma) { d._glbMax = c->min()-1; return result; } RangeList* q = c; //sum up the size of holes eaten int prevMax = c->max(); int growth = 0; // invariant: q->min()<=ma+1 while (q->next() != NULL && q->next()->min() <= ma+1) { q = q->next(); growth += q->min()-prevMax-1; prevMax = q->max(); } assert(growth>=0); _size+=growth; if (q->max() < ma) { _size += ma-q->max(); d._glbMax = ma; } else { d._glbMax = q->min()-1; } c->max(std::max(ma,q->max())); if (c!=q) { RangeList* oldCNext = c->next(); assert(oldCNext!=NULL); //q would have stayed c if c was last. c->next(q->next()); if (q->next()==NULL){ assert(q==lst()); lst(c); } oldCNext->dispose(home,q); } return true; } RangeList* nc = c->next(); p=c; c=nc; } //the new range is disjoint from the old domain and we add it as last: assert(mi>max()+1); RangeList* q = new (home) RangeList(mi, ma, NULL); lst()->next(q); lst(q); _size+= q->width(); d._glbMin = mi; d._glbMax = ma; return true; }
bool LUBndSet::exclude_full(Space& home, int mi, int ma, SetDelta& d) { assert(ma >= mi); assert(mi <= max() && ma >= min() && (mi > min() || ma < max())); bool result=false; RangeList* p = NULL; RangeList* c = fst(); d._lubMin = Limits::max+1; while (c != NULL) { if (c->max() >= mi){ if (c->min() > ma) { return result; } //in a hole if (c->min()<mi && c->max() > ma) { //Range split: RangeList* q = new (home) RangeList(ma+1,c->max(),c->next()); c->max(mi-1); if (c == lst()) { lst(q); } c->next(q); _size -= (ma-mi+1); d._lubMin = mi; d._lubMax = ma; return true; } if (c->max() > ma) { //start of range clipped, end remains d._lubMin = std::min(d._lubMin, c->min()); d._lubMax = ma; _size-=(ma-c->min()+1); c->min(ma+1); return true; } if (c->min() < mi) { //end of range clipped, start remains _size-=(c->max()-mi+1); d._lubMin = mi; d._lubMax = c->max(); c->max(mi-1); result=true; } else { //range *c destroyed d._lubMin = c->min(); _size-=c->width(); RangeList *cend = c; while ((cend->next()!=NULL) && (cend->next()->max()<=ma)){ cend = cend->next(); _size-=cend->width(); } d._lubMax = cend->max(); if (fst()==c) { fst(cend->next()); } else { p->next(cend->next()); } if (lst()==cend) { lst(p); } RangeList* nc=cend->next(); //performs loop step! c->dispose(home,cend); p=cend; c=nc; if (c != NULL && c->min() <= ma ) { //start of range clipped, end remains _size-=(ma-c->min()+1); c->min(ma+1); d._lubMax = ma; } return true; } } RangeList *nc = c->next(); p=c; c=nc; } return result; }
bool LUBndSet::intersect_full(Space& home, int mi, int ma) { RangeList* p = NULL; RangeList* c = fst(); assert(c != NULL); // Never intersect with an empty set // Skip ranges that are before mi while (c != NULL && c->max() < mi) { _size -= c->width(); RangeList *nc = c->next(); p=c; c=nc; } if (c == NULL) { // Delete entire domain fst()->dispose(home, lst()); fst(NULL); lst(NULL); return true; } bool changed = false; if (c != fst()) { fst()->dispose(home, p); fst(c); p = NULL; changed = true; } // We have found the first range that intersects with [mi,ma] if (mi > c->min()) { _size -= mi-c->min(); c->min(mi); changed = true; } while (c != NULL && c->max() <= ma) { RangeList *nc = c->next(); p=c; c=nc; } if (c == NULL) return changed; RangeList* newlst = p; if (ma >= c->min()) { _size -= c->max() - ma; c->max(ma); newlst = c; RangeList* nc = c->next(); c->next(NULL); p=c; c=nc; } else if (p != NULL) { p->next(NULL); } if (c != NULL) { for (RangeList* cc = c ; cc != NULL; cc = cc->next()) _size -= cc->width(); c->dispose(home, lst()); } lst(newlst); if (newlst==NULL) fst(NULL); return true; }