/// <summary> /// Returns the competeCollection - thisCollection /// </summary> /// <returns></returns> public RangeCollection Complement(long fullRangeBegin, long fullRangeLast) { RangeCollection result = new RangeCollection(); long rangeLeftToCoverBegin = fullRangeBegin; foreach (KeyValuePair <long, long> range in Ranges) { long start = range.Key; long last = range.Value; if (start > rangeLeftToCoverBegin) { result.AddRange(rangeLeftToCoverBegin, Math.Min(start - 1, fullRangeLast)); } rangeLeftToCoverBegin = Math.Max(rangeLeftToCoverBegin, last + 1); if (rangeLeftToCoverBegin > fullRangeLast) { break; } } if (rangeLeftToCoverBegin <= fullRangeLast) { result.AddRange(rangeLeftToCoverBegin, fullRangeLast); } return(result); }
/// <summary> /// Returns a collection of elements at what would be the i'th element for i \in [startIdx,lastIdx]. startIdx and lastIdx are 0-based. /// </summary> private RangeCollection ElementsAt(long startIndex, long lastIndex) { if (lastIndex < startIndex || startIndex < 0 || lastIndex >= Count()) { throw new ArgumentOutOfRangeException(string.Format("{0}-{1} must be a non-empty range that falls between 0 and {2}", startIndex, lastIndex, Count() - 1)); } RangeCollection result = new RangeCollection(); long countSoFar = 0; foreach (KeyValuePair <long, long> range in Ranges) { long rangeLength = range.Value - range.Key + 1; if (startIndex - countSoFar < rangeLength) { long start = range.Key + startIndex - countSoFar; long lastIfContinuousRange = range.Key + lastIndex - countSoFar; long last = Math.Min(range.Value, lastIfContinuousRange); // if startIdx-lastIdx falls completely in range, then take 2nd entry. result.AddRange(start, last); if (lastIfContinuousRange <= range.Value) // if this range covers the remaining indeces, we're done. { return(result); } else { startIndex = countSoFar + rangeLength; } } countSoFar += rangeLength; } throw new NotImplementedException("If we get here, then there's a bug in the implementation."); }