// copy on write so we can cache a..a intervals and sets of that protected internal virtual void Add(Interval addition) { if (@readonly) { throw new InvalidOperationException("can't alter readonly IntervalSet"); } //System.out.println("add "+addition+" to "+intervals.toString()); if (addition.b < addition.a) { return; } // find position in list // Use iterators as we modify list in place for (int i = 0; i < intervals.Count; i++) { Interval r = intervals[i]; if (addition.Equals(r)) { return; } if (addition.Adjacent(r) || !addition.Disjoint(r)) { // next to each other, make a single larger interval Interval bigger = addition.Union(r); intervals[i] = bigger; // make sure we didn't just create an interval that // should be merged with next interval in list while (i < intervals.Count - 1) { i++; Interval next = intervals[i]; if (!bigger.Adjacent(next) && bigger.Disjoint(next)) { break; } // if we bump up against or overlap next, merge intervals.RemoveAt(i); // remove this one i--; // move backwards to what we just set intervals[i] = bigger.Union(next); // set to 3 merged ones } // first call to next after previous duplicates the result return; } if (addition.StartsBeforeDisjoint(r)) { // insert before r intervals.Insert(i, addition); return; } } // if disjoint and after r, a future iteration will handle it // ok, must be after last interval (and disjoint from last interval) // just add it intervals.Add(addition); }
/// <summary> /// <inheritDoc/> /// /// </summary> public virtual Antlr4.Runtime.Misc.IntervalSet And(IIntSet other) { if (other == null) { //|| !(other instanceof IntervalSet) ) { return(null); } // nothing in common with null set IList <Interval> myIntervals = this.intervals; IList <Interval> theirIntervals = ((Antlr4.Runtime.Misc.IntervalSet)other).intervals; Antlr4.Runtime.Misc.IntervalSet intersection = null; int mySize = myIntervals.Count; int theirSize = theirIntervals.Count; int i = 0; int j = 0; // iterate down both interval lists looking for nondisjoint intervals while (i < mySize && j < theirSize) { Interval mine = myIntervals[i]; Interval theirs = theirIntervals[j]; //System.out.println("mine="+mine+" and theirs="+theirs); if (mine.StartsBeforeDisjoint(theirs)) { // move this iterator looking for interval that might overlap i++; } else { if (theirs.StartsBeforeDisjoint(mine)) { // move other iterator looking for interval that might overlap j++; } else { if (mine.ProperlyContains(theirs)) { // overlap, add intersection, get next theirs if (intersection == null) { intersection = new Antlr4.Runtime.Misc.IntervalSet(); } intersection.Add(mine.Intersection(theirs)); j++; } else { if (theirs.ProperlyContains(mine)) { // overlap, add intersection, get next mine if (intersection == null) { intersection = new Antlr4.Runtime.Misc.IntervalSet(); } intersection.Add(mine.Intersection(theirs)); i++; } else { if (!mine.Disjoint(theirs)) { // overlap, add intersection if (intersection == null) { intersection = new Antlr4.Runtime.Misc.IntervalSet(); } intersection.Add(mine.Intersection(theirs)); // Move the iterator of lower range [a..b], but not // the upper range as it may contain elements that will collide // with the next iterator. So, if mine=[0..115] and // theirs=[115..200], then intersection is 115 and move mine // but not theirs as theirs may collide with the next range // in thisIter. // move both iterators to next ranges if (mine.StartsAfterNonDisjoint(theirs)) { j++; } else { if (theirs.StartsAfterNonDisjoint(mine)) { i++; } } } } } } } } if (intersection == null) { return(new Antlr4.Runtime.Misc.IntervalSet()); } return(intersection); }